Deleted Added
full compact
dovend.c (13573) dovend.c (18471)
1/*
2 * dovend.c : Inserts all but the first few vendor options.
1/*
2 * dovend.c : Inserts all but the first few vendor options.
3 *
4 * $Id$
3 */
4
5#include <sys/types.h>
6
7#include <netinet/in.h>
8#include <arpa/inet.h> /* inet_ntoa */
9
10#include <stdlib.h>
11#include <stdio.h>
12#include <string.h>
13#include <errno.h>
14#include <syslog.h>
15
16#ifndef USE_BFUNCS
17# include <memory.h>
18/* Yes, memcpy is OK here (no overlapped copies). */
19# define bcopy(a,b,c) memcpy(b,a,c)
20# define bzero(p,l) memset(p,0,l)
21# define bcmp(a,b,c) memcmp(a,b,c)
22# define index strchr
23#endif
24
25#include "bootp.h"
26#include "bootpd.h"
27#include "report.h"
28#include "dovend.h"
29
30#ifdef __STDC__
31#define P(args) args
32#else
33#define P(args) ()
34#endif
35
36PRIVATE int insert_generic P((struct shared_bindata *, byte **, int *));
37
38/*
39 * Insert the 2nd part of the options into an option buffer.
40 * Return amount of space used.
41 *
42 * This inserts everything EXCEPT:
43 * magic cookie, subnet mask, gateway, bootsize, extension file
44 * Those are handled separately (in bootpd.c) to allow this function
45 * to be shared between bootpd and bootpef.
46 *
47 * When an "extension file" is in use, the options inserted by
48 * this function go into the exten_file, not the bootp response.
49 */
50
51int
52dovend_rfc1497(hp, buf, len)
53 struct host *hp;
54 byte *buf;
55 int len;
56{
57 int bytesleft = len;
58 byte *vp = buf;
59
60 static char noroom[] = "%s: No room for \"%s\" option";
61#define NEED(LEN, MSG) do \
62 if (bytesleft < (LEN)) { \
63 report(LOG_NOTICE, noroom, \
64 hp->hostname->string, MSG); \
65 return (vp - buf); \
66 } while (0)
67
68 /*
69 * Note that the following have already been inserted:
70 * magic_cookie, subnet_mask, gateway, bootsize
71 *
72 * The remaining options are inserted in order of importance.
73 * (Of course the importance of each is a matter of opinion.)
74 * The option insertion order should probably be configurable.
75 *
76 * This is the order used in the NetBSD version. Can anyone
77 * explain why the time_offset and swap_server are first?
78 * Also, why is the hostname so far down the list? -gwr
79 */
80
81 if (hp->flags.time_offset) {
82 NEED(6, "to");
83 *vp++ = TAG_TIME_OFFSET;/* -1 byte */
84 *vp++ = 4; /* -1 byte */
85 insert_u_long(htonl(hp->time_offset), &vp); /* -4 bytes */
86 bytesleft -= 6;
87 }
88 /*
89 * swap server, root path, dump path
90 */
91 if (hp->flags.swap_server) {
92 NEED(6, "sw");
93 /* There is just one SWAP_SERVER, so it is not an iplist. */
94 *vp++ = TAG_SWAP_SERVER;/* -1 byte */
95 *vp++ = 4; /* -1 byte */
96 insert_u_long(hp->swap_server.s_addr, &vp); /* -4 bytes */
97 bytesleft -= 6; /* Fix real count */
98 }
99 if (hp->flags.root_path) {
100 /*
101 * Check for room for root_path. Add 2 to account for
102 * TAG_ROOT_PATH and length.
103 */
104 len = strlen(hp->root_path->string);
105 NEED((len + 2), "rp");
106 *vp++ = TAG_ROOT_PATH;
107 *vp++ = (byte) (len & 0xFF);
108 bcopy(hp->root_path->string, vp, len);
109 vp += len;
110 bytesleft -= len + 2;
111 }
112 if (hp->flags.dump_file) {
113 /*
114 * Check for room for dump_file. Add 2 to account for
115 * TAG_DUMP_FILE and length.
116 */
117 len = strlen(hp->dump_file->string);
118 NEED((len + 2), "df");
119 *vp++ = TAG_DUMP_FILE;
120 *vp++ = (byte) (len & 0xFF);
121 bcopy(hp->dump_file->string, vp, len);
122 vp += len;
123 bytesleft -= len + 2;
124 }
125 /*
126 * DNS server and domain
127 */
128 if (hp->flags.domain_server) {
129 if (insert_ip(TAG_DOMAIN_SERVER,
130 hp->domain_server,
131 &vp, &bytesleft))
132 NEED(8, "ds");
133 }
134 if (hp->flags.domain_name) {
135 /*
136 * Check for room for domain_name. Add 2 to account for
137 * TAG_DOMAIN_NAME and length.
138 */
139 len = strlen(hp->domain_name->string);
140 NEED((len + 2), "dn");
141 *vp++ = TAG_DOMAIN_NAME;
142 *vp++ = (byte) (len & 0xFF);
143 bcopy(hp->domain_name->string, vp, len);
144 vp += len;
145 bytesleft -= len + 2;
146 }
147 /*
148 * NIS (YP) server and domain
149 */
150 if (hp->flags.nis_server) {
151 if (insert_ip(TAG_NIS_SERVER,
152 hp->nis_server,
153 &vp, &bytesleft))
154 NEED(8, "ds");
155 }
156 if (hp->flags.nis_domain) {
157 /*
158 * Check for room for nis_domain. Add 2 to account for
159 * TAG_NIS_DOMAIN and length.
160 */
161 len = strlen(hp->nis_domain->string);
162 NEED((len + 2), "dn");
163 *vp++ = TAG_NIS_DOMAIN;
164 *vp++ = (byte) (len & 0xFF);
165 bcopy(hp->nis_domain->string, vp, len);
166 vp += len;
167 bytesleft -= len + 2;
168 }
169 /* IEN 116 name server */
170 if (hp->flags.name_server) {
171 if (insert_ip(TAG_NAME_SERVER,
172 hp->name_server,
173 &vp, &bytesleft))
174 NEED(8, "ns");
175 }
176 if (hp->flags.rlp_server) {
177 if (insert_ip(TAG_RLP_SERVER,
178 hp->rlp_server,
179 &vp, &bytesleft))
180 NEED(8, "rl");
181 }
182 /* Time server (RFC 868) */
183 if (hp->flags.time_server) {
184 if (insert_ip(TAG_TIME_SERVER,
185 hp->time_server,
186 &vp, &bytesleft))
187 NEED(8, "ts");
188 }
189 /* NTP (time) Server (RFC 1129) */
190 if (hp->flags.ntp_server) {
191 if (insert_ip(TAG_NTP_SERVER,
192 hp->ntp_server,
193 &vp, &bytesleft))
194 NEED(8, "ts");
195 }
196 /*
197 * I wonder: If the hostname were "promoted" into the BOOTP
198 * response part, might these "extension" files possibly be
199 * shared between several clients?
200 *
201 * Also, why not just use longer BOOTP packets with all the
202 * additional length used as option data. This bootpd version
203 * already supports that feature by replying with the same
204 * packet length as the client request packet. -gwr
205 */
206 if (hp->flags.name_switch && hp->flags.send_name) {
207 /*
208 * Check for room for hostname. Add 2 to account for
209 * TAG_HOST_NAME and length.
210 */
211 len = strlen(hp->hostname->string);
212#if 0
213 /*
214 * XXX - Too much magic. The user can always set the hostname
215 * to the short version in the bootptab file. -gwr
216 */
217 if ((len + 2) > bytesleft) {
218 /*
219 * Not enough room for full (domain-qualified) hostname, try
220 * stripping it down to just the first field (host).
221 */
222 char *tmpstr = hp->hostname->string;
223 len = 0;
224 while (*tmpstr && (*tmpstr != '.')) {
225 tmpstr++;
226 len++;
227 }
228 }
229#endif
230 NEED((len + 2), "hn");
231 *vp++ = TAG_HOST_NAME;
232 *vp++ = (byte) (len & 0xFF);
233 bcopy(hp->hostname->string, vp, len);
234 vp += len;
235 bytesleft -= len + 2;
236 }
237 /*
238 * The rest of these are less important, so they go last.
239 */
240 if (hp->flags.lpr_server) {
241 if (insert_ip(TAG_LPR_SERVER,
242 hp->lpr_server,
243 &vp, &bytesleft))
244 NEED(8, "lp");
245 }
246 if (hp->flags.cookie_server) {
247 if (insert_ip(TAG_COOKIE_SERVER,
248 hp->cookie_server,
249 &vp, &bytesleft))
250 NEED(8, "cs");
251 }
252 if (hp->flags.log_server) {
253 if (insert_ip(TAG_LOG_SERVER,
254 hp->log_server,
255 &vp, &bytesleft))
256 NEED(8, "lg");
257 }
258 /*
259 * XXX - Add new tags here (to insert options)
260 */
261 if (hp->flags.generic) {
262 if (insert_generic(hp->generic, &vp, &bytesleft))
263 NEED(64, "(generic)");
264 }
265 /*
266 * The end marker is inserted by the caller.
267 */
268 return (vp - buf);
269#undef NEED
270} /* dovend_rfc1497 */
271
272
273
274/*
275 * Insert a tag value, a length value, and a list of IP addresses into the
276 * memory buffer indirectly pointed to by "dest". "tag" is the RFC1048 tag
277 * number to use, "iplist" is a pointer to a list of IP addresses
278 * (struct in_addr_list), and "bytesleft" points to an integer which
279 * indicates the size of the "dest" buffer.
280 *
281 * Return zero if everything fits.
282 *
283 * This is used to fill the vendor-specific area of a bootp packet in
284 * conformance to RFC1048.
285 */
286
287int
288insert_ip(tag, iplist, dest, bytesleft)
289 byte tag;
290 struct in_addr_list *iplist;
291 byte **dest;
292 int *bytesleft;
293{
294 struct in_addr *addrptr;
295 unsigned addrcount = 1;
296 byte *d;
297
298 if (iplist == NULL)
299 return (0);
300
301 if (*bytesleft >= 6) {
302 d = *dest; /* Save pointer for later */
303 **dest = tag;
304 (*dest) += 2;
305 (*bytesleft) -= 2; /* Account for tag and length */
306 addrptr = iplist->addr;
307 addrcount = iplist->addrcount;
308 while ((*bytesleft >= 4) && (addrcount > 0)) {
309 insert_u_long(addrptr->s_addr, dest);
310 addrptr++;
311 addrcount--;
312 (*bytesleft) -= 4; /* Four bytes per address */
313 }
314 d[1] = (byte) ((*dest - d - 2) & 0xFF);
315 }
316 return (addrcount);
317}
318
319
320
321/*
322 * Insert generic data into a bootp packet. The data is assumed to already
323 * be in RFC1048 format. It is inserted using a first-fit algorithm which
324 * attempts to insert as many tags as possible. Tags and data which are
325 * too large to fit are skipped; any remaining tags are tried until they
326 * have all been exhausted.
327 * Return zero if everything fits.
328 */
329
330static int
331insert_generic(gendata, buff, bytesleft)
332 struct shared_bindata *gendata;
333 byte **buff;
334 int *bytesleft;
335{
336 byte *srcptr;
337 int length, numbytes;
338 int skipped = 0;
339
340 if (gendata == NULL)
341 return (0);
342
343 srcptr = gendata->data;
344 length = gendata->length;
345 while ((length > 0) && (*bytesleft > 0)) {
346 switch (*srcptr) {
347 case TAG_END:
348 length = 0; /* Force an exit on next iteration */
349 break;
350 case TAG_PAD:
351 *(*buff)++ = *srcptr++;
352 (*bytesleft)--;
353 length--;
354 break;
355 default:
356 numbytes = srcptr[1] + 2;
357 if (*bytesleft < numbytes)
358 skipped += numbytes;
359 else {
360 bcopy(srcptr, *buff, numbytes);
361 (*buff) += numbytes;
362 (*bytesleft) -= numbytes;
363 }
364 srcptr += numbytes;
365 length -= numbytes;
366 break;
367 }
368 } /* while */
369 return (skipped);
370}
371
372/*
373 * Insert the unsigned long "value" into memory starting at the byte
374 * pointed to by the byte pointer (*dest). (*dest) is updated to
375 * point to the next available byte.
376 *
377 * Since it is desirable to internally store network addresses in network
378 * byte order (in struct in_addr's), this routine expects longs to be
379 * passed in network byte order.
380 *
381 * However, due to the nature of the main algorithm, the long must be in
382 * host byte order, thus necessitating the use of ntohl() first.
383 */
384
385void
386insert_u_long(value, dest)
387 u_int32 value;
388 byte **dest;
389{
390 byte *temp;
391 int n;
392
393 value = ntohl(value); /* Must use host byte order here */
394 temp = (*dest += 4);
395 for (n = 4; n > 0; n--) {
396 *--temp = (byte) (value & 0xFF);
397 value >>= 8;
398 }
399 /* Final result is network byte order */
400}
401
402/*
403 * Local Variables:
404 * tab-width: 4
405 * c-indent-level: 4
406 * c-argdecl-indent: 4
407 * c-continued-statement-offset: 4
408 * c-continued-brace-offset: -4
409 * c-label-offset: -4
410 * c-brace-offset: 0
411 * End:
412 */
5 */
6
7#include <sys/types.h>
8
9#include <netinet/in.h>
10#include <arpa/inet.h> /* inet_ntoa */
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <string.h>
15#include <errno.h>
16#include <syslog.h>
17
18#ifndef USE_BFUNCS
19# include <memory.h>
20/* Yes, memcpy is OK here (no overlapped copies). */
21# define bcopy(a,b,c) memcpy(b,a,c)
22# define bzero(p,l) memset(p,0,l)
23# define bcmp(a,b,c) memcmp(a,b,c)
24# define index strchr
25#endif
26
27#include "bootp.h"
28#include "bootpd.h"
29#include "report.h"
30#include "dovend.h"
31
32#ifdef __STDC__
33#define P(args) args
34#else
35#define P(args) ()
36#endif
37
38PRIVATE int insert_generic P((struct shared_bindata *, byte **, int *));
39
40/*
41 * Insert the 2nd part of the options into an option buffer.
42 * Return amount of space used.
43 *
44 * This inserts everything EXCEPT:
45 * magic cookie, subnet mask, gateway, bootsize, extension file
46 * Those are handled separately (in bootpd.c) to allow this function
47 * to be shared between bootpd and bootpef.
48 *
49 * When an "extension file" is in use, the options inserted by
50 * this function go into the exten_file, not the bootp response.
51 */
52
53int
54dovend_rfc1497(hp, buf, len)
55 struct host *hp;
56 byte *buf;
57 int len;
58{
59 int bytesleft = len;
60 byte *vp = buf;
61
62 static char noroom[] = "%s: No room for \"%s\" option";
63#define NEED(LEN, MSG) do \
64 if (bytesleft < (LEN)) { \
65 report(LOG_NOTICE, noroom, \
66 hp->hostname->string, MSG); \
67 return (vp - buf); \
68 } while (0)
69
70 /*
71 * Note that the following have already been inserted:
72 * magic_cookie, subnet_mask, gateway, bootsize
73 *
74 * The remaining options are inserted in order of importance.
75 * (Of course the importance of each is a matter of opinion.)
76 * The option insertion order should probably be configurable.
77 *
78 * This is the order used in the NetBSD version. Can anyone
79 * explain why the time_offset and swap_server are first?
80 * Also, why is the hostname so far down the list? -gwr
81 */
82
83 if (hp->flags.time_offset) {
84 NEED(6, "to");
85 *vp++ = TAG_TIME_OFFSET;/* -1 byte */
86 *vp++ = 4; /* -1 byte */
87 insert_u_long(htonl(hp->time_offset), &vp); /* -4 bytes */
88 bytesleft -= 6;
89 }
90 /*
91 * swap server, root path, dump path
92 */
93 if (hp->flags.swap_server) {
94 NEED(6, "sw");
95 /* There is just one SWAP_SERVER, so it is not an iplist. */
96 *vp++ = TAG_SWAP_SERVER;/* -1 byte */
97 *vp++ = 4; /* -1 byte */
98 insert_u_long(hp->swap_server.s_addr, &vp); /* -4 bytes */
99 bytesleft -= 6; /* Fix real count */
100 }
101 if (hp->flags.root_path) {
102 /*
103 * Check for room for root_path. Add 2 to account for
104 * TAG_ROOT_PATH and length.
105 */
106 len = strlen(hp->root_path->string);
107 NEED((len + 2), "rp");
108 *vp++ = TAG_ROOT_PATH;
109 *vp++ = (byte) (len & 0xFF);
110 bcopy(hp->root_path->string, vp, len);
111 vp += len;
112 bytesleft -= len + 2;
113 }
114 if (hp->flags.dump_file) {
115 /*
116 * Check for room for dump_file. Add 2 to account for
117 * TAG_DUMP_FILE and length.
118 */
119 len = strlen(hp->dump_file->string);
120 NEED((len + 2), "df");
121 *vp++ = TAG_DUMP_FILE;
122 *vp++ = (byte) (len & 0xFF);
123 bcopy(hp->dump_file->string, vp, len);
124 vp += len;
125 bytesleft -= len + 2;
126 }
127 /*
128 * DNS server and domain
129 */
130 if (hp->flags.domain_server) {
131 if (insert_ip(TAG_DOMAIN_SERVER,
132 hp->domain_server,
133 &vp, &bytesleft))
134 NEED(8, "ds");
135 }
136 if (hp->flags.domain_name) {
137 /*
138 * Check for room for domain_name. Add 2 to account for
139 * TAG_DOMAIN_NAME and length.
140 */
141 len = strlen(hp->domain_name->string);
142 NEED((len + 2), "dn");
143 *vp++ = TAG_DOMAIN_NAME;
144 *vp++ = (byte) (len & 0xFF);
145 bcopy(hp->domain_name->string, vp, len);
146 vp += len;
147 bytesleft -= len + 2;
148 }
149 /*
150 * NIS (YP) server and domain
151 */
152 if (hp->flags.nis_server) {
153 if (insert_ip(TAG_NIS_SERVER,
154 hp->nis_server,
155 &vp, &bytesleft))
156 NEED(8, "ds");
157 }
158 if (hp->flags.nis_domain) {
159 /*
160 * Check for room for nis_domain. Add 2 to account for
161 * TAG_NIS_DOMAIN and length.
162 */
163 len = strlen(hp->nis_domain->string);
164 NEED((len + 2), "dn");
165 *vp++ = TAG_NIS_DOMAIN;
166 *vp++ = (byte) (len & 0xFF);
167 bcopy(hp->nis_domain->string, vp, len);
168 vp += len;
169 bytesleft -= len + 2;
170 }
171 /* IEN 116 name server */
172 if (hp->flags.name_server) {
173 if (insert_ip(TAG_NAME_SERVER,
174 hp->name_server,
175 &vp, &bytesleft))
176 NEED(8, "ns");
177 }
178 if (hp->flags.rlp_server) {
179 if (insert_ip(TAG_RLP_SERVER,
180 hp->rlp_server,
181 &vp, &bytesleft))
182 NEED(8, "rl");
183 }
184 /* Time server (RFC 868) */
185 if (hp->flags.time_server) {
186 if (insert_ip(TAG_TIME_SERVER,
187 hp->time_server,
188 &vp, &bytesleft))
189 NEED(8, "ts");
190 }
191 /* NTP (time) Server (RFC 1129) */
192 if (hp->flags.ntp_server) {
193 if (insert_ip(TAG_NTP_SERVER,
194 hp->ntp_server,
195 &vp, &bytesleft))
196 NEED(8, "ts");
197 }
198 /*
199 * I wonder: If the hostname were "promoted" into the BOOTP
200 * response part, might these "extension" files possibly be
201 * shared between several clients?
202 *
203 * Also, why not just use longer BOOTP packets with all the
204 * additional length used as option data. This bootpd version
205 * already supports that feature by replying with the same
206 * packet length as the client request packet. -gwr
207 */
208 if (hp->flags.name_switch && hp->flags.send_name) {
209 /*
210 * Check for room for hostname. Add 2 to account for
211 * TAG_HOST_NAME and length.
212 */
213 len = strlen(hp->hostname->string);
214#if 0
215 /*
216 * XXX - Too much magic. The user can always set the hostname
217 * to the short version in the bootptab file. -gwr
218 */
219 if ((len + 2) > bytesleft) {
220 /*
221 * Not enough room for full (domain-qualified) hostname, try
222 * stripping it down to just the first field (host).
223 */
224 char *tmpstr = hp->hostname->string;
225 len = 0;
226 while (*tmpstr && (*tmpstr != '.')) {
227 tmpstr++;
228 len++;
229 }
230 }
231#endif
232 NEED((len + 2), "hn");
233 *vp++ = TAG_HOST_NAME;
234 *vp++ = (byte) (len & 0xFF);
235 bcopy(hp->hostname->string, vp, len);
236 vp += len;
237 bytesleft -= len + 2;
238 }
239 /*
240 * The rest of these are less important, so they go last.
241 */
242 if (hp->flags.lpr_server) {
243 if (insert_ip(TAG_LPR_SERVER,
244 hp->lpr_server,
245 &vp, &bytesleft))
246 NEED(8, "lp");
247 }
248 if (hp->flags.cookie_server) {
249 if (insert_ip(TAG_COOKIE_SERVER,
250 hp->cookie_server,
251 &vp, &bytesleft))
252 NEED(8, "cs");
253 }
254 if (hp->flags.log_server) {
255 if (insert_ip(TAG_LOG_SERVER,
256 hp->log_server,
257 &vp, &bytesleft))
258 NEED(8, "lg");
259 }
260 /*
261 * XXX - Add new tags here (to insert options)
262 */
263 if (hp->flags.generic) {
264 if (insert_generic(hp->generic, &vp, &bytesleft))
265 NEED(64, "(generic)");
266 }
267 /*
268 * The end marker is inserted by the caller.
269 */
270 return (vp - buf);
271#undef NEED
272} /* dovend_rfc1497 */
273
274
275
276/*
277 * Insert a tag value, a length value, and a list of IP addresses into the
278 * memory buffer indirectly pointed to by "dest". "tag" is the RFC1048 tag
279 * number to use, "iplist" is a pointer to a list of IP addresses
280 * (struct in_addr_list), and "bytesleft" points to an integer which
281 * indicates the size of the "dest" buffer.
282 *
283 * Return zero if everything fits.
284 *
285 * This is used to fill the vendor-specific area of a bootp packet in
286 * conformance to RFC1048.
287 */
288
289int
290insert_ip(tag, iplist, dest, bytesleft)
291 byte tag;
292 struct in_addr_list *iplist;
293 byte **dest;
294 int *bytesleft;
295{
296 struct in_addr *addrptr;
297 unsigned addrcount = 1;
298 byte *d;
299
300 if (iplist == NULL)
301 return (0);
302
303 if (*bytesleft >= 6) {
304 d = *dest; /* Save pointer for later */
305 **dest = tag;
306 (*dest) += 2;
307 (*bytesleft) -= 2; /* Account for tag and length */
308 addrptr = iplist->addr;
309 addrcount = iplist->addrcount;
310 while ((*bytesleft >= 4) && (addrcount > 0)) {
311 insert_u_long(addrptr->s_addr, dest);
312 addrptr++;
313 addrcount--;
314 (*bytesleft) -= 4; /* Four bytes per address */
315 }
316 d[1] = (byte) ((*dest - d - 2) & 0xFF);
317 }
318 return (addrcount);
319}
320
321
322
323/*
324 * Insert generic data into a bootp packet. The data is assumed to already
325 * be in RFC1048 format. It is inserted using a first-fit algorithm which
326 * attempts to insert as many tags as possible. Tags and data which are
327 * too large to fit are skipped; any remaining tags are tried until they
328 * have all been exhausted.
329 * Return zero if everything fits.
330 */
331
332static int
333insert_generic(gendata, buff, bytesleft)
334 struct shared_bindata *gendata;
335 byte **buff;
336 int *bytesleft;
337{
338 byte *srcptr;
339 int length, numbytes;
340 int skipped = 0;
341
342 if (gendata == NULL)
343 return (0);
344
345 srcptr = gendata->data;
346 length = gendata->length;
347 while ((length > 0) && (*bytesleft > 0)) {
348 switch (*srcptr) {
349 case TAG_END:
350 length = 0; /* Force an exit on next iteration */
351 break;
352 case TAG_PAD:
353 *(*buff)++ = *srcptr++;
354 (*bytesleft)--;
355 length--;
356 break;
357 default:
358 numbytes = srcptr[1] + 2;
359 if (*bytesleft < numbytes)
360 skipped += numbytes;
361 else {
362 bcopy(srcptr, *buff, numbytes);
363 (*buff) += numbytes;
364 (*bytesleft) -= numbytes;
365 }
366 srcptr += numbytes;
367 length -= numbytes;
368 break;
369 }
370 } /* while */
371 return (skipped);
372}
373
374/*
375 * Insert the unsigned long "value" into memory starting at the byte
376 * pointed to by the byte pointer (*dest). (*dest) is updated to
377 * point to the next available byte.
378 *
379 * Since it is desirable to internally store network addresses in network
380 * byte order (in struct in_addr's), this routine expects longs to be
381 * passed in network byte order.
382 *
383 * However, due to the nature of the main algorithm, the long must be in
384 * host byte order, thus necessitating the use of ntohl() first.
385 */
386
387void
388insert_u_long(value, dest)
389 u_int32 value;
390 byte **dest;
391{
392 byte *temp;
393 int n;
394
395 value = ntohl(value); /* Must use host byte order here */
396 temp = (*dest += 4);
397 for (n = 4; n > 0; n--) {
398 *--temp = (byte) (value & 0xFF);
399 value >>= 8;
400 }
401 /* Final result is network byte order */
402}
403
404/*
405 * Local Variables:
406 * tab-width: 4
407 * c-indent-level: 4
408 * c-argdecl-indent: 4
409 * c-continued-statement-offset: 4
410 * c-continued-brace-offset: -4
411 * c-label-offset: -4
412 * c-brace-offset: 0
413 * End:
414 */