]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/options.c
- Merge changes between 3.0.3RC1 and 3.0.4-BETA-3 into HEAD (silence
[thirdparty/dhcp.git] / common / options.c
1 /* options.c
2
3 DHCP options parsing and reassembly. */
4
5 /*
6 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
33 */
34
35 #ifndef lint
36 static char copyright[] =
37 "$Id: options.c,v 1.89 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
39
40 #define DHCP_OPTION_DATA
41 #include "dhcpd.h"
42 #include <omapip/omapip_p.h>
43
44 struct option *vendor_cfg_option;
45
46 static void do_option_set PROTO ((pair *,
47 struct option_cache *,
48 enum statement_op));
49
50 /* Parse all available options out of the specified packet. */
51
52 int parse_options (packet)
53 struct packet *packet;
54 {
55 int i;
56 struct option_cache *op = (struct option_cache *)0;
57
58 /* Allocate a new option state. */
59 if (!option_state_allocate (&packet -> options, MDL)) {
60 packet -> options_valid = 0;
61 return 0;
62 }
63
64 /* If we don't see the magic cookie, there's nothing to parse. */
65 if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
66 packet -> options_valid = 0;
67 return 1;
68 }
69
70 /* Go through the options field, up to the end of the packet
71 or the End field. */
72 if (!parse_option_buffer (packet -> options,
73 &packet -> raw -> options [4],
74 (packet -> packet_length -
75 DHCP_FIXED_NON_UDP - 4),
76 &dhcp_universe)) {
77
78 /* STSN servers have a bug where they send a mangled
79 domain-name option, and whatever is beyond that in
80 the packet is junk. Microsoft clients accept this,
81 which is probably why whoever implemented the STSN
82 server isn't aware of the problem yet. To work around
83 this, we will accept corrupt packets from the server if
84 they contain a valid DHCP_MESSAGE_TYPE option, but
85 will not accept any corrupt client packets (the ISC DHCP
86 server is sufficiently widely used that it is probably
87 beneficial for it to be picky) and will not accept
88 packets whose type can't be determined. */
89
90 if ((op = lookup_option (&dhcp_universe, packet -> options,
91 DHO_DHCP_MESSAGE_TYPE))) {
92 if (!op -> data.data ||
93 (op -> data.data [0] != DHCPOFFER &&
94 op -> data.data [0] != DHCPACK &&
95 op -> data.data [0] != DHCPNAK))
96 return 0;
97 } else
98 return 0;
99 }
100
101 /* If we parsed a DHCP Option Overload option, parse more
102 options out of the buffer(s) containing them. */
103 if ((op = lookup_option (&dhcp_universe, packet -> options,
104 DHO_DHCP_OPTION_OVERLOAD))) {
105 if (op -> data.data [0] & 1) {
106 if (!parse_option_buffer
107 (packet -> options,
108 (unsigned char *)packet -> raw -> file,
109 sizeof packet -> raw -> file,
110 &dhcp_universe))
111 return 0;
112 }
113 if (op -> data.data [0] & 2) {
114 if (!parse_option_buffer
115 (packet -> options,
116 (unsigned char *)packet -> raw -> sname,
117 sizeof packet -> raw -> sname,
118 &dhcp_universe))
119 return 0;
120 }
121 }
122 packet -> options_valid = 1;
123 return 1;
124 }
125
126 /* Parse options out of the specified buffer, storing addresses of option
127 values in packet -> options and setting packet -> options_valid if no
128 errors are encountered. */
129
130 int parse_option_buffer (options, buffer, length, universe)
131 struct option_state *options;
132 const unsigned char *buffer;
133 unsigned length;
134 struct universe *universe;
135 {
136 unsigned char *t;
137 const unsigned char *end = buffer + length;
138 unsigned len, offset;
139 int code;
140 struct option_cache *op = (struct option_cache *)0;
141 struct buffer *bp = (struct buffer *)0;
142
143 if (!buffer_allocate (&bp, length, MDL)) {
144 log_error ("no memory for option buffer.");
145 return 0;
146 }
147 memcpy (bp -> data, buffer, length);
148
149 for (offset = 0; buffer [offset] != DHO_END && offset < length; ) {
150 code = buffer [offset];
151 /* Pad options don't have a length - just skip them. */
152 if (code == DHO_PAD) {
153 ++offset;
154 continue;
155 }
156
157 /* Don't look for length if the buffer isn't that big. */
158 if (offset + 2 > length) {
159 len = 65536;
160 goto bogus;
161 }
162
163 /* All other fields (except end, see above) have a
164 one-byte length. */
165 len = buffer [offset + 1];
166
167 /* If the length is outrageous, the options are bad. */
168 if (offset + len + 2 > length) {
169 bogus:
170 log_error ("parse_option_buffer: option %s (%d) %s.",
171 dhcp_options [code].name, len,
172 "larger than buffer");
173 buffer_dereference (&bp, MDL);
174 return 0;
175 }
176
177 /* If the option contains an encapsulation, parse it. If
178 the parse fails, or the option isn't an encapsulation (by
179 far the most common case), or the option isn't entirely
180 an encapsulation, keep the raw data as well. */
181 if (universe -> options [code] &&
182 !((universe -> options [code] -> format [0] == 'e' ||
183 universe -> options [code] -> format [0] == 'E') &&
184 (parse_encapsulated_suboptions
185 (options, universe -> options [code],
186 buffer + offset + 2, len,
187 universe, (const char *)0)))) {
188 op = lookup_option (universe, options, code);
189 if (op) {
190 struct data_string new;
191 memset (&new, 0, sizeof new);
192 if (!buffer_allocate (&new.buffer, op -> data.len + len,
193 MDL)) {
194 log_error ("parse_option_buffer: No memory.");
195 return 0;
196 }
197 memcpy (new.buffer -> data, op -> data.data,
198 op -> data.len);
199 memcpy (&new.buffer -> data [op -> data.len],
200 &bp -> data [offset + 2], len);
201 new.len = op -> data.len + len;
202 new.data = new.buffer -> data;
203 data_string_forget (&op -> data, MDL);
204 data_string_copy (&op -> data, &new, MDL);
205 data_string_forget (&new, MDL);
206 } else {
207 save_option_buffer (universe, options, bp,
208 &bp -> data [offset + 2], len,
209 universe -> options [code], 1);
210 }
211 }
212 offset += len + 2;
213 }
214 buffer_dereference (&bp, MDL);
215 return 1;
216 }
217
218 /* If an option in an option buffer turns out to be an encapsulation,
219 figure out what to do. If we don't know how to de-encapsulate it,
220 or it's not well-formed, return zero; otherwise, return 1, indicating
221 that we succeeded in de-encapsulating it. */
222
223 struct universe *find_option_universe (struct option *eopt, const char *uname)
224 {
225 int i;
226 char *s, *t;
227 struct universe *universe = (struct universe *)0;
228
229 /* Look for the E option in the option format. */
230 s = strchr (eopt -> format, 'E');
231 if (!s) {
232 log_error ("internal encapsulation format error 1.");
233 return 0;
234 }
235 /* Look for the universe name in the option format. */
236 t = strchr (++s, '.');
237 /* If there was no trailing '.', or there's something after the
238 trailing '.', the option is bogus and we can't use it. */
239 if (!t || t [1]) {
240 log_error ("internal encapsulation format error 2.");
241 return 0;
242 }
243 if (t == s && uname) {
244 for (i = 0; i < universe_count; i++) {
245 if (!strcmp (universes [i] -> name, uname)) {
246 universe = universes [i];
247 break;
248 }
249 }
250 } else if (t != s) {
251 for (i = 0; i < universe_count; i++) {
252 if (strlen (universes [i] -> name) == t - s &&
253 !memcmp (universes [i] -> name,
254 s, (unsigned)(t - s))) {
255 universe = universes [i];
256 break;
257 }
258 }
259 }
260 return universe;
261 }
262
263 /* If an option in an option buffer turns out to be an encapsulation,
264 figure out what to do. If we don't know how to de-encapsulate it,
265 or it's not well-formed, return zero; otherwise, return 1, indicating
266 that we succeeded in de-encapsulating it. */
267
268 int parse_encapsulated_suboptions (struct option_state *options,
269 struct option *eopt,
270 const unsigned char *buffer,
271 unsigned len, struct universe *eu,
272 const char *uname)
273 {
274 int i;
275 struct universe *universe = find_option_universe (eopt, uname);
276
277 /* If we didn't find the universe, we can't do anything with it
278 right now (e.g., we can't decode vendor options until we've
279 decoded the packet and executed the scopes that it matches). */
280 if (!universe)
281 return 0;
282
283 /* If we don't have a decoding function for it, we can't decode
284 it. */
285 if (!universe -> decode)
286 return 0;
287
288 i = (*universe -> decode) (options, buffer, len, universe);
289
290 /* If there is stuff before the suboptions, we have to keep it. */
291 if (eopt -> format [0] != 'E')
292 return 0;
293 /* Otherwise, return the status of the decode function. */
294 return i;
295 }
296
297 int fqdn_universe_decode (struct option_state *options,
298 const unsigned char *buffer,
299 unsigned length, struct universe *u)
300 {
301 char *name;
302 struct buffer *bp = (struct buffer *)0;
303
304 /* FQDN options have to be at least four bytes long. */
305 if (length < 3)
306 return 0;
307
308 /* Save the contents of the option in a buffer. */
309 if (!buffer_allocate (&bp, length + 4, MDL)) {
310 log_error ("no memory for option buffer.");
311 return 0;
312 }
313 memcpy (&bp -> data [3], buffer + 1, length - 1);
314
315 if (buffer [0] & 4) /* encoded */
316 bp -> data [0] = 1;
317 else
318 bp -> data [0] = 0;
319 if (!save_option_buffer (&fqdn_universe, options, bp,
320 &bp -> data [0], 1,
321 &fqdn_options [FQDN_ENCODED], 0)) {
322 bad:
323 buffer_dereference (&bp, MDL);
324 return 0;
325 }
326
327 if (buffer [0] & 1) /* server-update */
328 bp -> data [2] = 1;
329 else
330 bp -> data [2] = 0;
331 if (buffer [0] & 2) /* no-client-update */
332 bp -> data [1] = 1;
333 else
334 bp -> data [1] = 0;
335
336 /* XXX Ideally we should store the name in DNS format, so if the
337 XXX label isn't in DNS format, we convert it to DNS format,
338 XXX rather than converting labels specified in DNS format to
339 XXX the plain ASCII representation. But that's hard, so
340 XXX not now. */
341
342 /* Not encoded using DNS format? */
343 if (!bp -> data [0]) {
344 unsigned i;
345
346 /* Some broken clients NUL-terminate this option. */
347 if (buffer [length - 1] == 0) {
348 --length;
349 bp -> data [1] = 1;
350 }
351
352 /* Determine the length of the hostname component of the
353 name. If the name contains no '.' character, it
354 represents a non-qualified label. */
355 for (i = 3; i < length && buffer [i] != '.'; i++);
356 i -= 3;
357
358 /* Note: If the client sends a FQDN, the first '.' will
359 be used as a NUL terminator for the hostname. */
360 if (i)
361 if (!save_option_buffer (&fqdn_universe, options, bp,
362 &bp -> data[5], i,
363 &fqdn_options [FQDN_HOSTNAME],
364 0))
365 goto bad;
366 /* Note: If the client sends a single label, the
367 FQDN_DOMAINNAME option won't be set. */
368 if (length > 4 + i &&
369 !save_option_buffer (&fqdn_universe, options, bp,
370 &bp -> data[6 + i], length - 4 - i,
371 &fqdn_options [FQDN_DOMAINNAME], 1))
372 goto bad;
373 /* Also save the whole name. */
374 if (length > 3)
375 if (!save_option_buffer (&fqdn_universe, options, bp,
376 &bp -> data [5], length - 3,
377 &fqdn_options [FQDN_FQDN], 1))
378 goto bad;
379 } else {
380 unsigned len;
381 unsigned total_len = 0;
382 unsigned first_len = 0;
383 int terminated = 0;
384 unsigned char *s;
385
386 s = &bp -> data[5];
387
388 while (s < &bp -> data[0] + length + 2) {
389 len = *s;
390 if (len > 63) {
391 log_info ("fancy bits in fqdn option");
392 return 0;
393 }
394 if (len == 0) {
395 terminated = 1;
396 break;
397 }
398 if (s + len > &bp -> data [0] + length + 3) {
399 log_info ("fqdn tag longer than buffer");
400 return 0;
401 }
402
403 if (first_len == 0) {
404 first_len = len;
405 }
406
407 *s = '.';
408 s += len + 1;
409 total_len += len + 1;
410 }
411
412 /* We wind up with a length that's one too many because
413 we shouldn't increment for the last label, but there's
414 no way to tell we're at the last label until we exit
415 the loop. :'*/
416 if (total_len > 0)
417 total_len--;
418
419 if (!terminated) {
420 first_len = total_len;
421 }
422
423 if (first_len > 0 &&
424 !save_option_buffer (&fqdn_universe, options, bp,
425 &bp -> data[6], first_len,
426 &fqdn_options [FQDN_HOSTNAME], 0))
427 goto bad;
428 if (total_len > 0 && first_len != total_len) {
429 if (!save_option_buffer
430 (&fqdn_universe, options, bp,
431 &bp -> data[6 + first_len], total_len - first_len,
432 &fqdn_options [FQDN_DOMAINNAME], 1))
433 goto bad;
434 }
435 if (total_len > 0)
436 if (!save_option_buffer (&fqdn_universe, options, bp,
437 &bp -> data [6], total_len,
438 &fqdn_options [FQDN_FQDN], 1))
439 goto bad;
440 }
441
442 if (!save_option_buffer (&fqdn_universe, options, bp,
443 &bp -> data [1], 1,
444 &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
445 goto bad;
446 if (!save_option_buffer (&fqdn_universe, options, bp,
447 &bp -> data [2], 1,
448 &fqdn_options [FQDN_SERVER_UPDATE], 0))
449 goto bad;
450
451 if (!save_option_buffer (&fqdn_universe, options, bp,
452 &bp -> data [3], 1,
453 &fqdn_options [FQDN_RCODE1], 0))
454 goto bad;
455 if (!save_option_buffer (&fqdn_universe, options, bp,
456 &bp -> data [4], 1,
457 &fqdn_options [FQDN_RCODE2], 0))
458 goto bad;
459
460 buffer_dereference (&bp, MDL);
461 return 1;
462 }
463
464 /* cons options into a big buffer, and then split them out into the
465 three seperate buffers if needed. This allows us to cons up a set
466 of vendor options using the same routine. */
467
468 int cons_options (inpacket, outpacket, lease, client_state,
469 mms, in_options, cfg_options,
470 scope, overload, terminate, bootpp, prl, vuname)
471 struct packet *inpacket;
472 struct dhcp_packet *outpacket;
473 struct lease *lease;
474 struct client_state *client_state;
475 int mms;
476 struct option_state *in_options;
477 struct option_state *cfg_options;
478 struct binding_scope **scope;
479 int overload; /* Overload flags that may be set. */
480 int terminate;
481 int bootpp;
482 struct data_string *prl;
483 const char *vuname;
484 {
485 #define PRIORITY_COUNT 300
486 unsigned priority_list [PRIORITY_COUNT];
487 int priority_len;
488 unsigned char buffer [4096]; /* Really big buffer... */
489 unsigned main_buffer_size, mb_max;
490 unsigned mainbufix, bufix, agentix;
491 int fileix;
492 int snameix;
493 unsigned option_size;
494 unsigned length;
495 int i;
496 struct option_cache *op;
497 struct data_string ds;
498 pair pp, *hash;
499 int need_endopt = 0;
500 int have_sso = 0;
501 int ocount = 0;
502 int ofbuf1=0, ofbuf2=0;
503
504 memset (&ds, 0, sizeof ds);
505
506 /* If there's a Maximum Message Size option in the incoming packet
507 and no alternate maximum message size has been specified, take the
508 one in the packet. */
509
510 if (inpacket &&
511 (op = lookup_option (&dhcp_universe, inpacket -> options,
512 DHO_DHCP_MAX_MESSAGE_SIZE))) {
513 evaluate_option_cache (&ds, inpacket,
514 lease, client_state, in_options,
515 cfg_options, scope, op, MDL);
516 if (ds.len >= sizeof (u_int16_t)) {
517 i = getUShort (ds.data);
518
519 if(!mms || (i < mms))
520 mms = i;
521 }
522 data_string_forget (&ds, MDL);
523 }
524
525 /* If the client has provided a maximum DHCP message size,
526 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
527 use up to the minimum IP MTU size (576 bytes). */
528 /* XXX if a BOOTP client specifies a max message size, we will
529 honor it. */
530
531 if (mms) {
532 main_buffer_size = mms - DHCP_FIXED_LEN;
533
534 /* Enforce a minimum packet size... */
535 if (main_buffer_size < (576 - DHCP_FIXED_LEN))
536 main_buffer_size = 576 - DHCP_FIXED_LEN;
537 } else if (bootpp) {
538 if (inpacket) {
539 main_buffer_size =
540 inpacket -> packet_length - DHCP_FIXED_LEN;
541 if (main_buffer_size < 64)
542 main_buffer_size = 64;
543 } else
544 main_buffer_size = 64;
545 } else
546 main_buffer_size = 576 - DHCP_FIXED_LEN;
547
548 /* Set a hard limit at the size of the output buffer. */
549 mb_max = sizeof(buffer) - (((overload & 1) ? DHCP_FILE_LEN : 0) +
550 ((overload & 2) ? DHCP_SNAME_LEN : 0));
551 if (main_buffer_size > mb_max)
552 main_buffer_size = mb_max;
553
554 /* Preload the option priority list with mandatory options. */
555 priority_len = 0;
556 priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE;
557 priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
558 priority_list [priority_len++] = DHO_DHCP_LEASE_TIME;
559 priority_list [priority_len++] = DHO_DHCP_MESSAGE;
560 priority_list [priority_len++] = DHO_DHCP_REQUESTED_ADDRESS;
561 priority_list [priority_len++] = DHO_FQDN;
562
563 if (prl && prl -> len > 0) {
564 if ((op = lookup_option (&dhcp_universe, cfg_options,
565 DHO_SUBNET_SELECTION))) {
566 if (priority_len < PRIORITY_COUNT)
567 priority_list [priority_len++] =
568 DHO_SUBNET_SELECTION;
569 }
570
571 data_string_truncate (prl, (PRIORITY_COUNT - priority_len));
572
573 for (i = 0; i < prl -> len; i++) {
574 /* Prevent client from changing order of delivery
575 of relay agent information option. */
576 if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS)
577 priority_list [priority_len++] =
578 prl -> data [i];
579 }
580 } else {
581 /* First, hardcode some more options that ought to be
582 sent first... */
583 priority_list [priority_len++] = DHO_SUBNET_MASK;
584 priority_list [priority_len++] = DHO_ROUTERS;
585 priority_list [priority_len++] = DHO_DOMAIN_NAME_SERVERS;
586 priority_list [priority_len++] = DHO_HOST_NAME;
587
588 /* Append a list of the standard DHCP options from the
589 standard DHCP option space. Actually, if a site
590 option space hasn't been specified, we wind up
591 treating the dhcp option space as the site option
592 space, and the first for loop is skipped, because
593 it's slightly more general to do it this way,
594 taking the 1Q99 DHCP futures work into account. */
595 if (cfg_options -> site_code_min) {
596 for (i = 0; i < OPTION_HASH_SIZE; i++) {
597 hash = cfg_options -> universes [dhcp_universe.index];
598 if (hash) {
599 for (pp = hash [i]; pp; pp = pp -> cdr) {
600 op = (struct option_cache *)(pp -> car);
601 if (op -> option -> code <
602 cfg_options -> site_code_min &&
603 priority_len < PRIORITY_COUNT &&
604 (op -> option -> code !=
605 DHO_DHCP_AGENT_OPTIONS))
606 priority_list [priority_len++] =
607 op -> option -> code;
608 }
609 }
610 }
611 }
612
613 /* Now cycle through the site option space, or if there
614 is no site option space, we'll be cycling through the
615 dhcp option space. */
616 for (i = 0; i < OPTION_HASH_SIZE; i++) {
617 hash = (cfg_options -> universes
618 [cfg_options -> site_universe]);
619 if (hash)
620 for (pp = hash [i]; pp; pp = pp -> cdr) {
621 op = (struct option_cache *)(pp -> car);
622 if (op -> option -> code >=
623 cfg_options -> site_code_min &&
624 priority_len < PRIORITY_COUNT &&
625 (op -> option -> code !=
626 DHO_DHCP_AGENT_OPTIONS))
627 priority_list [priority_len++] =
628 op -> option -> code;
629 }
630 }
631
632 /* Now go through all the universes for which options
633 were set and see if there are encapsulations for
634 them; if there are, put the encapsulation options
635 on the priority list as well. */
636 for (i = 0; i < cfg_options -> universe_count; i++) {
637 if (cfg_options -> universes [i] &&
638 universes [i] -> enc_opt &&
639 priority_len < PRIORITY_COUNT &&
640 universes [i] -> enc_opt -> universe == &dhcp_universe)
641 {
642 if (universes [i] -> enc_opt -> code !=
643 DHO_DHCP_AGENT_OPTIONS)
644 priority_list [priority_len++] =
645 universes [i] -> enc_opt -> code;
646 }
647 }
648
649 /* The vendor option space can't stand on its own, so always
650 add it to the list. */
651 if (priority_len < PRIORITY_COUNT)
652 priority_list [priority_len++] =
653 DHO_VENDOR_ENCAPSULATED_OPTIONS;
654 }
655
656 /* Figure out the overload buffer offset(s). */
657 if (overload) {
658 ofbuf1 = main_buffer_size - 4;
659 if (overload == 3)
660 ofbuf2 = main_buffer_size - 4 + DHCP_FILE_LEN;
661 }
662
663 /* Copy the options into the big buffer... */
664 option_size = store_options (&ocount, buffer,
665 (main_buffer_size - 4 +
666 ((overload & 1) ? DHCP_FILE_LEN : 0) +
667 ((overload & 2) ? DHCP_SNAME_LEN : 0)),
668 inpacket, lease, client_state,
669 in_options, cfg_options, scope,
670 priority_list, priority_len,
671 ofbuf1, ofbuf2, terminate, vuname);
672 /* If store_options failed. */
673 if (option_size == 0)
674 return 0;
675 if (overload) {
676 if (ocount == 1 && (overload & 1))
677 overload = 1;
678 else if (ocount == 1 && (overload & 2))
679 overload = 2;
680 else if (ocount == 3)
681 overload = 3;
682 else
683 overload = 0;
684 }
685
686 /* Put the cookie up front... */
687 memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4);
688 mainbufix = 4;
689
690 /* If we're going to have to overload, store the overload
691 option at the beginning. If we can, though, just store the
692 whole thing in the packet's option buffer and leave it at
693 that. */
694 memcpy (&outpacket -> options [mainbufix],
695 buffer, option_size);
696 mainbufix += option_size;
697 if (overload) {
698 outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
699 outpacket -> options [mainbufix++] = 1;
700 outpacket -> options [mainbufix++] = overload;
701
702 if (overload & 1) {
703 memcpy (outpacket -> file,
704 &buffer [ofbuf1], DHCP_FILE_LEN);
705 }
706 if (overload & 2) {
707 if (ofbuf2) {
708 memcpy (outpacket -> sname, &buffer [ofbuf2],
709 DHCP_SNAME_LEN);
710 } else {
711 memcpy (outpacket -> sname, &buffer [ofbuf1],
712 DHCP_SNAME_LEN);
713 }
714 }
715 }
716 agentix = mainbufix;
717 if (mainbufix < main_buffer_size)
718 need_endopt = 1;
719 length = DHCP_FIXED_NON_UDP + mainbufix;
720
721 /* Now hack in the agent options if there are any. */
722 priority_list [0] = DHO_DHCP_AGENT_OPTIONS;
723 priority_len = 1;
724 agentix +=
725 store_options (0, &outpacket -> options [agentix],
726 DHCP_OPTION_LEN - agentix,
727 inpacket, lease, client_state,
728 in_options, cfg_options, scope,
729 priority_list, priority_len,
730 0, 0, 0, (char *)0);
731
732 /* Tack a DHO_END option onto the packet if we need to. */
733 if (agentix < DHCP_OPTION_LEN && need_endopt)
734 outpacket -> options [agentix++] = DHO_END;
735
736 /* Figure out the length. */
737 length = DHCP_FIXED_NON_UDP + agentix;
738 return length;
739 }
740
741 /* Store all the requested options into the requested buffer. */
742
743 int store_options (ocount, buffer, buflen, packet, lease, client_state,
744 in_options, cfg_options, scope, priority_list, priority_len,
745 first_cutoff, second_cutoff, terminate, vuname)
746 int *ocount;
747 unsigned char *buffer;
748 unsigned buflen;
749 struct packet *packet;
750 struct lease *lease;
751 struct client_state *client_state;
752 struct option_state *in_options;
753 struct option_state *cfg_options;
754 struct binding_scope **scope;
755 unsigned *priority_list;
756 int priority_len;
757 unsigned first_cutoff, second_cutoff;
758 int terminate;
759 const char *vuname;
760 {
761 int bufix = 0, six = 0, tix = 0;
762 int i;
763 int ix;
764 int tto;
765 int bufend, sbufend;
766 struct data_string od;
767 struct option_cache *oc;
768 unsigned code;
769
770 if (first_cutoff) {
771 if (first_cutoff >= buflen)
772 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL);
773
774 bufend = first_cutoff;
775 } else
776 bufend = buflen;
777
778 if (second_cutoff) {
779 if (second_cutoff >= buflen)
780 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL);
781
782 sbufend = second_cutoff;
783 } else
784 sbufend = buflen;
785
786 memset (&od, 0, sizeof od);
787
788 /* Eliminate duplicate options in the parameter request list.
789 There's got to be some clever knuthian way to do this:
790 Eliminate all but the first occurance of a value in an array
791 of values without otherwise disturbing the order of the array. */
792 for (i = 0; i < priority_len - 1; i++) {
793 tto = 0;
794 for (ix = i + 1; ix < priority_len + tto; ix++) {
795 if (tto)
796 priority_list [ix - tto] =
797 priority_list [ix];
798 if (priority_list [i] == priority_list [ix]) {
799 tto++;
800 priority_len--;
801 }
802 }
803 }
804
805 /* Copy out the options in the order that they appear in the
806 priority list... */
807 for (i = 0; i < priority_len; i++) {
808 /* Number of bytes left to store (some may already
809 have been stored by a previous pass). */
810 unsigned length;
811 int optstart, soptstart, toptstart;
812 struct universe *u;
813 int have_encapsulation = 0;
814 struct data_string encapsulation;
815 int splitup;
816
817 memset (&encapsulation, 0, sizeof encapsulation);
818
819 /* Code for next option to try to store. */
820 code = priority_list [i];
821
822 /* Look up the option in the site option space if the code
823 is above the cutoff, otherwise in the DHCP option space. */
824 if (code >= cfg_options -> site_code_min)
825 u = universes [cfg_options -> site_universe];
826 else
827 u = &dhcp_universe;
828
829 oc = lookup_option (u, cfg_options, code);
830
831 /* It's an encapsulation, try to find the universe
832 to be encapsulated first, except that if it's a straight
833 encapsulation and the user has provided a value for the
834 encapsulation option, use the user-provided value. */
835 if (u -> options [code] &&
836 ((u -> options [code] -> format [0] == 'E' && !oc) ||
837 u -> options [code] -> format [0] == 'e')) {
838 int uix;
839 static char *s, *t;
840 struct option_cache *tmp;
841 struct data_string name;
842
843 s = strchr (u -> options [code] -> format, 'E');
844 if (s)
845 t = strchr (++s, '.');
846 if (s && t) {
847 memset (&name, 0, sizeof name);
848
849 /* A zero-length universe name means the vendor
850 option space, if one is defined. */
851 if (t == s) {
852 if (vendor_cfg_option) {
853 tmp = lookup_option (vendor_cfg_option -> universe,
854 cfg_options,
855 vendor_cfg_option -> code);
856 if (tmp)
857 evaluate_option_cache (&name, packet, lease,
858 client_state,
859 in_options,
860 cfg_options,
861 scope, tmp, MDL);
862 } else if (vuname) {
863 name.data = (unsigned char *)s;
864 name.len = strlen (s);
865 }
866 } else {
867 name.data = (unsigned char *)s;
868 name.len = t - s;
869 }
870
871 /* If we found a universe, and there are options configured
872 for that universe, try to encapsulate it. */
873 if (name.len) {
874 have_encapsulation =
875 (option_space_encapsulate
876 (&encapsulation, packet, lease, client_state,
877 in_options, cfg_options, scope, &name));
878 data_string_forget (&name, MDL);
879 }
880 }
881 }
882
883 /* In order to avoid memory leaks, we have to get to here
884 with any option cache that we allocated in tmp not being
885 referenced by tmp, and whatever option cache is referenced
886 by oc being an actual reference. lookup_option doesn't
887 generate a reference (this needs to be fixed), so the
888 preceding goop ensures that if we *didn't* generate a new
889 option cache, oc still winds up holding an actual reference. */
890
891 /* If no data is available for this option, skip it. */
892 if (!oc && !have_encapsulation) {
893 continue;
894 }
895
896 /* Find the value of the option... */
897 if (oc) {
898 evaluate_option_cache (&od, packet,
899 lease, client_state, in_options,
900 cfg_options, scope, oc, MDL);
901 if (!od.len) {
902 data_string_forget (&encapsulation, MDL);
903 data_string_forget (&od, MDL);
904 have_encapsulation = 0;
905 continue;
906 }
907 }
908
909 /* We should now have a constant length for the option. */
910 length = od.len;
911 if (have_encapsulation) {
912 length += encapsulation.len;
913 if (!od.len) {
914 data_string_copy (&od, &encapsulation, MDL);
915 data_string_forget (&encapsulation, MDL);
916 } else {
917 struct buffer *bp = (struct buffer *)0;
918 if (!buffer_allocate (&bp, length, MDL)) {
919 option_cache_dereference (&oc, MDL);
920 data_string_forget (&od, MDL);
921 data_string_forget (&encapsulation, MDL);
922 continue;
923 }
924 memcpy (&bp -> data [0], od.data, od.len);
925 memcpy (&bp -> data [od.len], encapsulation.data,
926 encapsulation.len);
927 data_string_forget (&od, MDL);
928 data_string_forget (&encapsulation, MDL);
929 od.data = &bp -> data [0];
930 buffer_reference (&od.buffer, bp, MDL);
931 buffer_dereference (&bp, MDL);
932 od.len = length;
933 od.terminated = 0;
934 }
935 }
936
937 /* Do we add a NUL? */
938 if (terminate && dhcp_options [code].format [0] == 't') {
939 length++;
940 tto = 1;
941 } else {
942 tto = 0;
943 }
944
945 /* Try to store the option. */
946
947 /* If the option's length is more than 255, we must store it
948 in multiple hunks. Store 255-byte hunks first. However,
949 in any case, if the option data will cross a buffer
950 boundary, split it across that boundary. */
951
952
953 if (length > 255)
954 splitup = 1;
955 else
956 splitup = 0;
957
958 ix = 0;
959 optstart = bufix;
960 soptstart = six;
961 toptstart = tix;
962 while (length) {
963 unsigned incr = length;
964 int consumed = 0;
965 int *pix;
966 unsigned char *base;
967
968 /* Try to fit it in the options buffer. */
969 if (!splitup &&
970 ((!six && !tix && (i == priority_len - 1) &&
971 (bufix + 2 + length < bufend)) ||
972 (bufix + 5 + length < bufend))) {
973 base = buffer;
974 pix = &bufix;
975 /* Try to fit it in the second buffer. */
976 } else if (!splitup && first_cutoff &&
977 (first_cutoff + six + 3 + length < sbufend)) {
978 base = &buffer[first_cutoff];
979 pix = &six;
980 /* Try to fit it in the third buffer. */
981 } else if (!splitup && second_cutoff &&
982 (second_cutoff + tix + 3 + length < buflen)) {
983 base = &buffer[second_cutoff];
984 pix = &tix;
985 /* Split the option up into the remaining space. */
986 } else {
987 splitup = 1;
988
989 /* Use any remaining options space. */
990 if (bufix + 6 < bufend) {
991 incr = bufend - bufix - 5;
992 base = buffer;
993 pix = &bufix;
994 /* Use any remaining first_cutoff space. */
995 } else if (first_cutoff &&
996 (first_cutoff + six + 4 < sbufend)) {
997 incr = sbufend - (first_cutoff + six) - 3;
998 base = &buffer[first_cutoff];
999 pix = &six;
1000 /* Use any remaining second_cutoff space. */
1001 } else if (second_cutoff &&
1002 (second_cutoff + tix + 4 < buflen)) {
1003 incr = buflen - (second_cutoff + tix) - 3;
1004 base = &buffer[second_cutoff];
1005 pix = &tix;
1006 /* Give up, roll back this option. */
1007 } else {
1008 bufix = optstart;
1009 six = soptstart;
1010 tix = toptstart;
1011 break;
1012 }
1013 }
1014
1015 if (incr > length)
1016 incr = length;
1017 if (incr > 255)
1018 incr = 255;
1019
1020 /* Everything looks good - copy it in! */
1021 base [*pix] = code;
1022 base [*pix + 1] = (unsigned char)incr;
1023 if (tto && incr == length) {
1024 if (incr > 1)
1025 memcpy (base + *pix + 2,
1026 od.data + ix, (unsigned)(incr - 1));
1027 base [*pix + 2 + incr - 1] = 0;
1028 } else {
1029 memcpy (base + *pix + 2,
1030 od.data + ix, (unsigned)incr);
1031 }
1032 length -= incr;
1033 ix += incr;
1034 *pix += 2 + incr;
1035 }
1036 data_string_forget (&od, MDL);
1037 }
1038
1039 /* If we can overload, and we have, then PAD and END those spaces. */
1040 if (first_cutoff && six) {
1041 if ((first_cutoff + six + 1) < sbufend)
1042 memset (&buffer[first_cutoff + six + 1], DHO_PAD,
1043 sbufend - (first_cutoff + six + 1));
1044 else if (first_cutoff + six >= sbufend)
1045 log_fatal("Second buffer overflow in overloaded options.");
1046
1047 buffer[first_cutoff + six] = DHO_END;
1048 *ocount |= 1; /* So that caller knows there's data there. */
1049 }
1050
1051 if (second_cutoff && tix) {
1052 if (second_cutoff + tix + 1 < buflen) {
1053 memset (&buffer[second_cutoff + tix + 1], DHO_PAD,
1054 buflen - (second_cutoff + tix + 1));
1055 } else if (second_cutoff + tix >= buflen)
1056 log_fatal("Third buffer overflow in overloaded options.");
1057
1058 buffer[second_cutoff + tix] = DHO_END;
1059 *ocount |= 2; /* So that caller knows there's data there. */
1060 }
1061
1062 if ((six || tix) && (bufix + 3 > bufend))
1063 log_fatal("Not enough space for option overload option.");
1064
1065 return bufix;
1066 }
1067
1068 /* Return true if the format string has a variable length text option
1069 * ("t"), return false otherwise.
1070 */
1071
1072 int
1073 format_has_text(format)
1074 const char *format;
1075 {
1076 const char *p;
1077 int retval = 0;
1078
1079 p = format;
1080 while (*p != '\0') {
1081 switch (*p++) {
1082 case 'd':
1083 case 't':
1084 return 1;
1085
1086 /* These symbols are arbitrary, not fixed or
1087 * determinable length...text options with them is
1088 * invalid.
1089 */
1090 case 'A':
1091 case 'a':
1092 case 'X':
1093 case 'x':
1094 return 0;
1095
1096 /* 'E' is variable length, but not arbitrary...you
1097 * can find its length if you can find an END option.
1098 * N is one-byte in length but trails a name of a
1099 * space defining the enumeration values. So treat
1100 * both the same - valid, fixed-length fields.
1101 */
1102 case 'E':
1103 case 'N':
1104 /* Consume the space name. */
1105 while ((*p != '\0') && (*p++ != '.'))
1106 ;
1107 break;
1108
1109 default:
1110 break;
1111 }
1112 }
1113
1114 return 0;
1115 }
1116
1117 /* Determine the minimum length of a DHCP option prior to any variable
1118 * or inconsistent length formats, according to its configured format
1119 * variable (and possibly from supplied option cache contents for variable
1120 * length format symbols).
1121 */
1122
1123 int
1124 format_min_length(format, oc)
1125 const char *format;
1126 struct option_cache *oc;
1127 {
1128 const char *p;
1129 int min_len = 0;
1130 int last_size = 0;
1131
1132 p = format;
1133 while (*p != '\0') {
1134 switch (*p++) {
1135 case 'I': /* IPv4 Address */
1136 case 'l': /* int32_t */
1137 case 'L': /* uint32_t */
1138 case 'T': /* Lease Time, uint32_t equivalent */
1139 min_len += 4;
1140 last_size = 4;
1141 break;
1142
1143 case 's': /* int16_t */
1144 case 'S': /* uint16_t */
1145 min_len += 2;
1146 last_size = 2;
1147 break;
1148
1149 case 'N': /* Enumeration in 1-byte values. */
1150 /* Consume space name. */
1151 while ((*p != '\0') && (*p++ != '.'))
1152 ;
1153
1154 /* Fall Through to handle as one-byte field */
1155
1156 case 'b': /* int8_t */
1157 case 'B': /* uint8_t */
1158 case 'F': /* Flag that is always true. */
1159 case 'f': /* Flag */
1160 min_len++;
1161 last_size = 1;
1162 break;
1163
1164 case 'o': /* Last argument is optional. */
1165 min_len -= last_size;
1166 case 'e': /* Encapsulation hint (there is an 'E' later). */
1167 last_size = 0;
1168 break;
1169
1170 case 'E': /* Encapsulated options. */
1171 /* Consume space name. */
1172 while ((*p != '\0') && (*p++ != '.'))
1173 ;
1174
1175 /* Find an end option, or find that the encaps options
1176 * go all the way to the end (or beyond) of the data
1177 * portion of the option.
1178 */
1179 last_size = 0;
1180 while (min_len < oc->data.len) {
1181 if (oc->data.data[min_len] == DHO_END) {
1182 min_len++;
1183 last_size++;
1184 break;
1185 } else if (oc->data.data[min_len] == DHO_PAD) {
1186 min_len++;
1187 last_size++;
1188 } else if ((min_len + 1) < oc->data.len) {
1189 min_len += oc->data.data[min_len+1]+2;
1190 last_size += oc->data.data[min_len+1]+2;
1191 } else {
1192 /* Suboption length is out of bounds,
1193 * advance beyond the code/length pair
1194 * to trigger below error conditonal.
1195 */
1196 min_len += 2;
1197 last_size += 2;
1198 break;
1199 }
1200 }
1201
1202 if (min_len > oc->data.len) {
1203 log_error("format_min_length(%s): "
1204 "Encapsulated options exceed "
1205 "supplied buffer.", format);
1206 return INT_MAX;
1207 }
1208
1209 break;
1210
1211 case 'd': /* "Domain name" */
1212 case 't': /* "ASCII Text" */
1213 case 'X': /* "ASCII or Hex Conditional */
1214 case 'x': /* "Hex" */
1215 case 'A': /* Array of all that precedes. */
1216 case 'a': /* Array of preceding symbol. */
1217 return min_len;
1218
1219 default:
1220 /* No safe value is known. */
1221 log_error("format_min_length(%s): No safe value "
1222 "for unknown format symbols.", format);
1223 return INT_MAX;
1224 }
1225 }
1226
1227 return min_len;
1228 }
1229
1230
1231 /* Format the specified option so that a human can easily read it. */
1232
1233 const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
1234 struct option *option;
1235 const unsigned char *data;
1236 unsigned len;
1237 int emit_commas;
1238 int emit_quotes;
1239 {
1240 static char optbuf [32768]; /* XXX */
1241 int hunksize = 0;
1242 int opthunk = 0;
1243 int hunkinc = 0;
1244 int numhunk = -1;
1245 int numelem = 0;
1246 char fmtbuf [32];
1247 struct enumeration *enumbuf [32];
1248 int i, j, k, l;
1249 char *op = optbuf;
1250 const unsigned char *dp = data;
1251 struct in_addr foo;
1252 char comma;
1253 unsigned long tval;
1254
1255 if (emit_commas)
1256 comma = ',';
1257 else
1258 comma = ' ';
1259
1260 memset (enumbuf, 0, sizeof enumbuf);
1261
1262 /* Figure out the size of the data. */
1263 for (l = i = 0; option -> format [i]; i++, l++) {
1264 if (!numhunk) {
1265 log_error ("%s: Extra codes in format string: %s",
1266 option -> name,
1267 &(option -> format [i]));
1268 break;
1269 }
1270 numelem++;
1271 fmtbuf [l] = option -> format [i];
1272 switch (option -> format [i]) {
1273 case 'a':
1274 --numelem;
1275 fmtbuf [l] = 0;
1276 numhunk = 0;
1277 break;
1278 case 'A':
1279 --numelem;
1280 fmtbuf [l] = 0;
1281 numhunk = 0;
1282 break;
1283 case 'E':
1284 /* Skip the universe name. */
1285 while (option -> format [i] &&
1286 option -> format [i] != '.')
1287 i++;
1288 case 'X':
1289 for (k = 0; k < len; k++) {
1290 if (!isascii (data [k]) ||
1291 !isprint (data [k]))
1292 break;
1293 }
1294 /* If we found no bogus characters, or the bogus
1295 character we found is a trailing NUL, it's
1296 okay to print this option as text. */
1297 if (k == len || (k + 1 == len && data [k] == 0)) {
1298 fmtbuf [l] = 't';
1299 numhunk = -2;
1300 } else {
1301 fmtbuf [l] = 'x';
1302 hunksize++;
1303 comma = ':';
1304 numhunk = 0;
1305 }
1306 fmtbuf [l + 1] = 0;
1307 break;
1308 case 'd':
1309 case 't':
1310 fmtbuf [l] = 't';
1311 fmtbuf [l + 1] = 0;
1312 numhunk = -2;
1313 break;
1314 case 'N':
1315 k = i;
1316 while (option -> format [i] &&
1317 option -> format [i] != '.')
1318 i++;
1319 enumbuf [l] =
1320 find_enumeration (&option -> format [k] + 1,
1321 i - k - 1);
1322 hunksize += 1;
1323 hunkinc = 1;
1324 break;
1325 case 'I':
1326 case 'l':
1327 case 'L':
1328 case 'T':
1329 hunksize += 4;
1330 hunkinc = 4;
1331 break;
1332 case 's':
1333 case 'S':
1334 hunksize += 2;
1335 hunkinc = 2;
1336 break;
1337 case 'b':
1338 case 'B':
1339 case 'f':
1340 hunksize++;
1341 hunkinc = 1;
1342 break;
1343 case 'e':
1344 break;
1345 case 'o':
1346 opthunk += hunkinc;
1347 break;
1348 default:
1349 log_error ("%s: garbage in format string: %s",
1350 option -> name,
1351 &(option -> format [i]));
1352 break;
1353 }
1354 }
1355
1356 /* Check for too few bytes... */
1357 if (hunksize - opthunk > len) {
1358 log_error ("%s: expecting at least %d bytes; got %d",
1359 option -> name,
1360 hunksize, len);
1361 return "<error>";
1362 }
1363 /* Check for too many bytes... */
1364 if (numhunk == -1 && hunksize < len)
1365 log_error ("%s: %d extra bytes",
1366 option -> name,
1367 len - hunksize);
1368
1369 /* If this is an array, compute its size. */
1370 if (!numhunk)
1371 numhunk = len / hunksize;
1372 /* See if we got an exact number of hunks. */
1373 if (numhunk > 0 && numhunk * hunksize < len)
1374 log_error ("%s: %d extra bytes at end of array\n",
1375 option -> name,
1376 len - numhunk * hunksize);
1377
1378 /* A one-hunk array prints the same as a single hunk. */
1379 if (numhunk < 0)
1380 numhunk = 1;
1381
1382 /* Cycle through the array (or hunk) printing the data. */
1383 for (i = 0; i < numhunk; i++) {
1384 for (j = 0; j < numelem; j++) {
1385 switch (fmtbuf [j]) {
1386 case 't':
1387 if (emit_quotes)
1388 *op++ = '"';
1389 for (; dp < data + len; dp++) {
1390 if (!isascii (*dp) ||
1391 !isprint (*dp)) {
1392 /* Skip trailing NUL. */
1393 if (dp + 1 != data + len ||
1394 *dp != 0) {
1395 sprintf (op, "\\%03o",
1396 *dp);
1397 op += 4;
1398 }
1399 } else if (*dp == '"' ||
1400 *dp == '\'' ||
1401 *dp == '$' ||
1402 *dp == '`' ||
1403 *dp == '\\') {
1404 *op++ = '\\';
1405 *op++ = *dp;
1406 } else
1407 *op++ = *dp;
1408 }
1409 if (emit_quotes)
1410 *op++ = '"';
1411 *op = 0;
1412 break;
1413 /* pretty-printing an array of enums is
1414 going to get ugly. */
1415 case 'N':
1416 if (!enumbuf [j])
1417 goto enum_as_num;
1418 for (i = 0; ;i++) {
1419 if (!enumbuf [j] -> values [i].name)
1420 goto enum_as_num;
1421 if (enumbuf [j] -> values [i].value ==
1422 *dp)
1423 break;
1424 }
1425 strcpy (op, enumbuf [j] -> values [i].name);
1426 op += strlen (op);
1427 break;
1428 case 'I':
1429 foo.s_addr = htonl (getULong (dp));
1430 strcpy (op, inet_ntoa (foo));
1431 dp += 4;
1432 break;
1433 case 'l':
1434 sprintf (op, "%ld", (long)getLong (dp));
1435 dp += 4;
1436 break;
1437 case 'T':
1438 tval = getULong (dp);
1439 if (tval == -1)
1440 sprintf (op, "%s", "infinite");
1441 else
1442 sprintf (op, "%ld", tval);
1443 break;
1444 case 'L':
1445 sprintf (op, "%ld",
1446 (unsigned long)getULong (dp));
1447 dp += 4;
1448 break;
1449 case 's':
1450 sprintf (op, "%d", (int)getShort (dp));
1451 dp += 2;
1452 break;
1453 case 'S':
1454 sprintf (op, "%d", (unsigned)getUShort (dp));
1455 dp += 2;
1456 break;
1457 case 'b':
1458 sprintf (op, "%d", *(const char *)dp++);
1459 break;
1460 case 'B':
1461 enum_as_num:
1462 sprintf (op, "%d", *dp++);
1463 break;
1464 case 'x':
1465 sprintf (op, "%x", *dp++);
1466 break;
1467 case 'f':
1468 strcpy (op, *dp++ ? "true" : "false");
1469 break;
1470 default:
1471 log_error ("Unexpected format code %c",
1472 fmtbuf [j]);
1473 }
1474 op += strlen (op);
1475 if (dp == data + len)
1476 break;
1477 if (j + 1 < numelem && comma != ':')
1478 *op++ = ' ';
1479 }
1480 if (i + 1 < numhunk) {
1481 *op++ = comma;
1482 }
1483 if (dp == data + len)
1484 break;
1485 }
1486 return optbuf;
1487 }
1488
1489 int get_option (result, universe, packet, lease, client_state,
1490 in_options, cfg_options, options, scope, code, file, line)
1491 struct data_string *result;
1492 struct universe *universe;
1493 struct packet *packet;
1494 struct lease *lease;
1495 struct client_state *client_state;
1496 struct option_state *in_options;
1497 struct option_state *cfg_options;
1498 struct option_state *options;
1499 struct binding_scope **scope;
1500 unsigned code;
1501 const char *file;
1502 int line;
1503 {
1504 struct option_cache *oc;
1505
1506 if (!universe -> lookup_func)
1507 return 0;
1508 oc = ((*universe -> lookup_func) (universe, options, code));
1509 if (!oc)
1510 return 0;
1511 if (!evaluate_option_cache (result, packet, lease, client_state,
1512 in_options, cfg_options, scope, oc,
1513 file, line))
1514 return 0;
1515 return 1;
1516 }
1517
1518 void set_option (universe, options, option, op)
1519 struct universe *universe;
1520 struct option_state *options;
1521 struct option_cache *option;
1522 enum statement_op op;
1523 {
1524 struct option_cache *oc, *noc;
1525
1526 switch (op) {
1527 case if_statement:
1528 case add_statement:
1529 case eval_statement:
1530 case break_statement:
1531 default:
1532 log_error ("bogus statement type in do_option_set.");
1533 break;
1534
1535 case default_option_statement:
1536 oc = lookup_option (universe, options,
1537 option -> option -> code);
1538 if (oc)
1539 break;
1540 save_option (universe, options, option);
1541 break;
1542
1543 case supersede_option_statement:
1544 case send_option_statement:
1545 /* Install the option, replacing any existing version. */
1546 save_option (universe, options, option);
1547 break;
1548
1549 case append_option_statement:
1550 case prepend_option_statement:
1551 oc = lookup_option (universe, options,
1552 option -> option -> code);
1553 if (!oc) {
1554 save_option (universe, options, option);
1555 break;
1556 }
1557 /* If it's not an expression, make it into one. */
1558 if (!oc -> expression && oc -> data.len) {
1559 if (!expression_allocate (&oc -> expression, MDL)) {
1560 log_error ("Can't allocate const expression.");
1561 break;
1562 }
1563 oc -> expression -> op = expr_const_data;
1564 data_string_copy
1565 (&oc -> expression -> data.const_data,
1566 &oc -> data, MDL);
1567 data_string_forget (&oc -> data, MDL);
1568 }
1569 noc = (struct option_cache *)0;
1570 if (!option_cache_allocate (&noc, MDL))
1571 break;
1572 if (op == append_option_statement) {
1573 if (!make_concat (&noc -> expression,
1574 oc -> expression,
1575 option -> expression)) {
1576 option_cache_dereference (&noc, MDL);
1577 break;
1578 }
1579 } else {
1580 if (!make_concat (&noc -> expression,
1581 option -> expression,
1582 oc -> expression)) {
1583 option_cache_dereference (&noc, MDL);
1584 break;
1585 }
1586 }
1587 noc -> option = oc -> option;
1588 save_option (universe, options, noc);
1589 option_cache_dereference (&noc, MDL);
1590 break;
1591 }
1592 }
1593
1594 struct option_cache *lookup_option (universe, options, code)
1595 struct universe *universe;
1596 struct option_state *options;
1597 unsigned code;
1598 {
1599 if (!options)
1600 return (struct option_cache *)0;
1601 if (universe -> lookup_func)
1602 return (*universe -> lookup_func) (universe, options, code);
1603 else
1604 log_error ("can't look up options in %s space.",
1605 universe -> name);
1606 return (struct option_cache *)0;
1607 }
1608
1609 struct option_cache *lookup_hashed_option (universe, options, code)
1610 struct universe *universe;
1611 struct option_state *options;
1612 unsigned code;
1613 {
1614 int hashix;
1615 pair bptr;
1616 pair *hash;
1617
1618 /* Make sure there's a hash table. */
1619 if (universe -> index >= options -> universe_count ||
1620 !(options -> universes [universe -> index]))
1621 return (struct option_cache *)0;
1622
1623 hash = options -> universes [universe -> index];
1624
1625 hashix = compute_option_hash (code);
1626 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1627 if (((struct option_cache *)(bptr -> car)) -> option -> code ==
1628 code)
1629 return (struct option_cache *)(bptr -> car);
1630 }
1631 return (struct option_cache *)0;
1632 }
1633
1634 int save_option_buffer (struct universe *universe,
1635 struct option_state *options,
1636 struct buffer *bp,
1637 unsigned char *buffer, unsigned length,
1638 struct option *option, int tp)
1639 {
1640 struct buffer *lbp = (struct buffer *)0;
1641 struct option_cache *op = (struct option_cache *)0;
1642
1643 if (!option_cache_allocate (&op, MDL)) {
1644 log_error ("No memory for option %s.%s.",
1645 universe -> name,
1646 option -> name);
1647 return 0;
1648 }
1649
1650 /* If we weren't passed a buffer in which the data are saved and
1651 refcounted, allocate one now. */
1652 if (!bp) {
1653 if (!buffer_allocate (&lbp, length, MDL)) {
1654 log_error ("no memory for option buffer.");
1655
1656 option_cache_dereference (&op, MDL);
1657 return 0;
1658 }
1659 memcpy (lbp -> data, buffer, length + tp);
1660 bp = lbp;
1661 buffer = &bp -> data [0]; /* Refer to saved buffer. */
1662 }
1663
1664 /* Reference buffer copy to option cache. */
1665 op -> data.buffer = (struct buffer *)0;
1666 buffer_reference (&op -> data.buffer, bp, MDL);
1667
1668 /* Point option cache into buffer. */
1669 op -> data.data = buffer;
1670 op -> data.len = length;
1671
1672 if (tp) {
1673 /* NUL terminate (we can get away with this because we (or
1674 the caller!) allocated one more than the buffer size, and
1675 because the byte following the end of an option is always
1676 the code of the next option, which the caller is getting
1677 out of the *original* buffer. */
1678 buffer [length] = 0;
1679 op -> data.terminated = 1;
1680 } else
1681 op -> data.terminated = 0;
1682
1683 op -> option = option;
1684
1685 /* If this option is ultimately a text option, null determinate to
1686 * comply with RFC2132 section 2. Mark a flag so this can be sensed
1687 * later to echo NULLs back to clients that supplied them (they
1688 * probably expect them).
1689 */
1690 if (format_has_text(option->format)) {
1691 int min_len = format_min_length(option->format, op);
1692
1693 while ((op->data.len > min_len) &&
1694 (op->data.data[op->data.len-1] == '\0')) {
1695 op->data.len--;
1696 op->flags |= OPTION_HAD_NULLS;
1697 }
1698 }
1699
1700 /* Now store the option. */
1701 save_option (universe, options, op);
1702
1703 /* And let go of our reference. */
1704 option_cache_dereference (&op, MDL);
1705
1706 return 1;
1707 }
1708
1709 void save_option (struct universe *universe,
1710 struct option_state *options, struct option_cache *oc)
1711 {
1712 if (universe -> save_func)
1713 (*universe -> save_func) (universe, options, oc);
1714 else
1715 log_error ("can't store options in %s space.",
1716 universe -> name);
1717 }
1718
1719 void save_hashed_option (universe, options, oc)
1720 struct universe *universe;
1721 struct option_state *options;
1722 struct option_cache *oc;
1723 {
1724 int hashix;
1725 pair bptr;
1726 pair *hash = options -> universes [universe -> index];
1727
1728 if (oc -> refcnt == 0)
1729 abort ();
1730
1731 /* Compute the hash. */
1732 hashix = compute_option_hash (oc -> option -> code);
1733
1734 /* If there's no hash table, make one. */
1735 if (!hash) {
1736 hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL);
1737 if (!hash) {
1738 log_error ("no memory to store %s.%s",
1739 universe -> name, oc -> option -> name);
1740 return;
1741 }
1742 memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash);
1743 options -> universes [universe -> index] = (VOIDPTR)hash;
1744 } else {
1745 /* Try to find an existing option matching the new one. */
1746 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1747 if (((struct option_cache *)
1748 (bptr -> car)) -> option -> code ==
1749 oc -> option -> code)
1750 break;
1751 }
1752
1753 /* If we find one, dereference it and put the new one
1754 in its place. */
1755 if (bptr) {
1756 option_cache_dereference
1757 ((struct option_cache **)&bptr -> car, MDL);
1758 option_cache_reference
1759 ((struct option_cache **)&bptr -> car,
1760 oc, MDL);
1761 return;
1762 }
1763 }
1764
1765 /* Otherwise, just put the new one at the head of the list. */
1766 bptr = new_pair (MDL);
1767 if (!bptr) {
1768 log_error ("No memory for option_cache reference.");
1769 return;
1770 }
1771 bptr -> cdr = hash [hashix];
1772 bptr -> car = 0;
1773 option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL);
1774 hash [hashix] = bptr;
1775 }
1776
1777 void delete_option (universe, options, code)
1778 struct universe *universe;
1779 struct option_state *options;
1780 int code;
1781 {
1782 if (universe -> delete_func)
1783 (*universe -> delete_func) (universe, options, code);
1784 else
1785 log_error ("can't delete options from %s space.",
1786 universe -> name);
1787 }
1788
1789 void delete_hashed_option (universe, options, code)
1790 struct universe *universe;
1791 struct option_state *options;
1792 int code;
1793 {
1794 int hashix;
1795 pair bptr, prev = (pair)0;
1796 pair *hash = options -> universes [universe -> index];
1797
1798 /* There may not be any options in this space. */
1799 if (!hash)
1800 return;
1801
1802 /* Try to find an existing option matching the new one. */
1803 hashix = compute_option_hash (code);
1804 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1805 if (((struct option_cache *)(bptr -> car)) -> option -> code
1806 == code)
1807 break;
1808 prev = bptr;
1809 }
1810 /* If we found one, wipe it out... */
1811 if (bptr) {
1812 if (prev)
1813 prev -> cdr = bptr -> cdr;
1814 else
1815 hash [hashix] = bptr -> cdr;
1816 option_cache_dereference
1817 ((struct option_cache **)(&bptr -> car), MDL);
1818 free_pair (bptr, MDL);
1819 }
1820 }
1821
1822 extern struct option_cache *free_option_caches; /* XXX */
1823
1824 int option_cache_dereference (ptr, file, line)
1825 struct option_cache **ptr;
1826 const char *file;
1827 int line;
1828 {
1829 if (!ptr || !*ptr) {
1830 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1831 file, line);
1832 #if defined (POINTER_DEBUG)
1833 abort ();
1834 #else
1835 return 0;
1836 #endif
1837 }
1838
1839 (*ptr) -> refcnt--;
1840 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
1841 if (!(*ptr) -> refcnt) {
1842 if ((*ptr) -> data.buffer)
1843 data_string_forget (&(*ptr) -> data, file, line);
1844 if ((*ptr) -> expression)
1845 expression_dereference (&(*ptr) -> expression,
1846 file, line);
1847 if ((*ptr) -> next)
1848 option_cache_dereference (&((*ptr) -> next),
1849 file, line);
1850 /* Put it back on the free list... */
1851 (*ptr) -> expression = (struct expression *)free_option_caches;
1852 free_option_caches = *ptr;
1853 dmalloc_reuse (free_option_caches, (char *)0, 0, 0);
1854 }
1855 if ((*ptr) -> refcnt < 0) {
1856 log_error ("%s(%d): negative refcnt!", file, line);
1857 #if defined (DEBUG_RC_HISTORY)
1858 dump_rc_history (*ptr);
1859 #endif
1860 #if defined (POINTER_DEBUG)
1861 abort ();
1862 #else
1863 *ptr = (struct option_cache *)0;
1864 return 0;
1865 #endif
1866 }
1867 *ptr = (struct option_cache *)0;
1868 return 1;
1869
1870 }
1871
1872 int hashed_option_state_dereference (universe, state, file, line)
1873 struct universe *universe;
1874 struct option_state *state;
1875 const char *file;
1876 int line;
1877 {
1878 pair *heads;
1879 pair cp, next;
1880 int i;
1881
1882 /* Get the pointer to the array of hash table bucket heads. */
1883 heads = (pair *)(state -> universes [universe -> index]);
1884 if (!heads)
1885 return 0;
1886
1887 /* For each non-null head, loop through all the buckets dereferencing
1888 the attached option cache structures and freeing the buckets. */
1889 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1890 for (cp = heads [i]; cp; cp = next) {
1891 next = cp -> cdr;
1892 option_cache_dereference
1893 ((struct option_cache **)&cp -> car,
1894 file, line);
1895 free_pair (cp, file, line);
1896 }
1897 }
1898
1899 dfree (heads, file, line);
1900 state -> universes [universe -> index] = (void *)0;
1901 return 1;
1902 }
1903
1904 int store_option (result, universe, packet, lease, client_state,
1905 in_options, cfg_options, scope, oc)
1906 struct data_string *result;
1907 struct universe *universe;
1908 struct packet *packet;
1909 struct lease *lease;
1910 struct client_state *client_state;
1911 struct option_state *in_options;
1912 struct option_state *cfg_options;
1913 struct binding_scope **scope;
1914 struct option_cache *oc;
1915 {
1916 struct data_string d1, d2;
1917
1918 memset (&d1, 0, sizeof d1);
1919 memset (&d2, 0, sizeof d2);
1920
1921 if (evaluate_option_cache (&d2, packet, lease, client_state,
1922 in_options, cfg_options, scope, oc, MDL)) {
1923 if (!buffer_allocate (&d1.buffer,
1924 (result -> len +
1925 universe -> length_size +
1926 universe -> tag_size + d2.len), MDL)) {
1927 data_string_forget (result, MDL);
1928 data_string_forget (&d2, MDL);
1929 return 0;
1930 }
1931 d1.data = &d1.buffer -> data [0];
1932 if (result -> len)
1933 memcpy (d1.buffer -> data,
1934 result -> data, result -> len);
1935 d1.len = result -> len;
1936 (*universe -> store_tag) (&d1.buffer -> data [d1.len],
1937 oc -> option -> code);
1938 d1.len += universe -> tag_size;
1939 (*universe -> store_length) (&d1.buffer -> data [d1.len],
1940 d2.len);
1941 d1.len += universe -> length_size;
1942 memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len);
1943 d1.len += d2.len;
1944 data_string_forget (&d2, MDL);
1945 data_string_forget (result, MDL);
1946 data_string_copy (result, &d1, MDL);
1947 data_string_forget (&d1, MDL);
1948 return 1;
1949 }
1950 return 0;
1951 }
1952
1953 int option_space_encapsulate (result, packet, lease, client_state,
1954 in_options, cfg_options, scope, name)
1955 struct data_string *result;
1956 struct packet *packet;
1957 struct lease *lease;
1958 struct client_state *client_state;
1959 struct option_state *in_options;
1960 struct option_state *cfg_options;
1961 struct binding_scope **scope;
1962 struct data_string *name;
1963 {
1964 struct universe *u;
1965
1966 u = (struct universe *)0;
1967 universe_hash_lookup (&u, universe_hash,
1968 (const char *)name -> data, name -> len, MDL);
1969 if (!u)
1970 return 0;
1971
1972 if (u -> encapsulate)
1973 return (*u -> encapsulate) (result, packet, lease,
1974 client_state,
1975 in_options, cfg_options, scope, u);
1976 log_error ("encapsulation requested for %s with no support.",
1977 name -> data);
1978 return 0;
1979 }
1980
1981 int hashed_option_space_encapsulate (result, packet, lease, client_state,
1982 in_options, cfg_options, scope, universe)
1983 struct data_string *result;
1984 struct packet *packet;
1985 struct lease *lease;
1986 struct client_state *client_state;
1987 struct option_state *in_options;
1988 struct option_state *cfg_options;
1989 struct binding_scope **scope;
1990 struct universe *universe;
1991 {
1992 pair p, *hash;
1993 int status;
1994 int i;
1995
1996 if (universe -> index >= cfg_options -> universe_count)
1997 return 0;
1998
1999 hash = cfg_options -> universes [universe -> index];
2000 if (!hash)
2001 return 0;
2002
2003 status = 0;
2004 for (i = 0; i < OPTION_HASH_SIZE; i++) {
2005 for (p = hash [i]; p; p = p -> cdr) {
2006 if (store_option (result, universe, packet,
2007 lease, client_state, in_options,
2008 cfg_options, scope,
2009 (struct option_cache *)p -> car))
2010 status = 1;
2011 }
2012 }
2013
2014 return status;
2015 }
2016
2017 int nwip_option_space_encapsulate (result, packet, lease, client_state,
2018 in_options, cfg_options, scope, universe)
2019 struct data_string *result;
2020 struct packet *packet;
2021 struct lease *lease;
2022 struct client_state *client_state;
2023 struct option_state *in_options;
2024 struct option_state *cfg_options;
2025 struct binding_scope **scope;
2026 struct universe *universe;
2027 {
2028 pair ocp;
2029 int status;
2030 int i;
2031 static struct option_cache *no_nwip;
2032 struct data_string ds;
2033 struct option_chain_head *head;
2034
2035 if (universe -> index >= cfg_options -> universe_count)
2036 return 0;
2037 head = ((struct option_chain_head *)
2038 cfg_options -> universes [fqdn_universe.index]);
2039 if (!head)
2040 return 0;
2041
2042 status = 0;
2043 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
2044 struct option_cache *oc = (struct option_cache *)(ocp -> car);
2045 if (store_option (result, universe, packet,
2046 lease, client_state, in_options,
2047 cfg_options, scope,
2048 (struct option_cache *)ocp -> car))
2049 status = 1;
2050 }
2051
2052 /* If there's no data, the nwip suboption is supposed to contain
2053 a suboption saying there's no data. */
2054 if (!status) {
2055 if (!no_nwip) {
2056 static unsigned char nni [] = { 1, 0 };
2057 memset (&ds, 0, sizeof ds);
2058 ds.data = nni;
2059 ds.len = 2;
2060 if (option_cache_allocate (&no_nwip, MDL))
2061 data_string_copy (&no_nwip -> data, &ds, MDL);
2062 no_nwip -> option = nwip_universe.options [1];
2063 }
2064 if (no_nwip) {
2065 if (store_option (result, universe, packet, lease,
2066 client_state, in_options,
2067 cfg_options, scope, no_nwip))
2068 status = 1;
2069 }
2070 } else {
2071 memset (&ds, 0, sizeof ds);
2072
2073 /* If we have nwip options, the first one has to be the
2074 nwip-exists-in-option-area option. */
2075 if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) {
2076 data_string_forget (result, MDL);
2077 return 0;
2078 }
2079 ds.data = &ds.buffer -> data [0];
2080 ds.buffer -> data [0] = 2;
2081 ds.buffer -> data [1] = 0;
2082 memcpy (&ds.buffer -> data [2], result -> data, result -> len);
2083 data_string_forget (result, MDL);
2084 data_string_copy (result, &ds, MDL);
2085 data_string_forget (&ds, MDL);
2086 }
2087
2088 return status;
2089 }
2090
2091 int fqdn_option_space_encapsulate (result, packet, lease, client_state,
2092 in_options, cfg_options, scope, universe)
2093 struct data_string *result;
2094 struct packet *packet;
2095 struct lease *lease;
2096 struct client_state *client_state;
2097 struct option_state *in_options;
2098 struct option_state *cfg_options;
2099 struct binding_scope **scope;
2100 struct universe *universe;
2101 {
2102 pair ocp;
2103 struct data_string results [FQDN_SUBOPTION_COUNT + 1];
2104 unsigned i;
2105 unsigned len;
2106 struct buffer *bp = (struct buffer *)0;
2107 struct option_chain_head *head;
2108
2109 /* If there's no FQDN universe, don't encapsulate. */
2110 if (fqdn_universe.index >= cfg_options -> universe_count)
2111 return 0;
2112 head = ((struct option_chain_head *)
2113 cfg_options -> universes [fqdn_universe.index]);
2114 if (!head)
2115 return 0;
2116
2117 /* Figure out the values of all the suboptions. */
2118 memset (results, 0, sizeof results);
2119 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
2120 struct option_cache *oc = (struct option_cache *)(ocp -> car);
2121 if (oc -> option -> code > FQDN_SUBOPTION_COUNT)
2122 continue;
2123 evaluate_option_cache (&results [oc -> option -> code],
2124 packet, lease, client_state, in_options,
2125 cfg_options, scope, oc, MDL);
2126 }
2127 len = 4 + results [FQDN_FQDN].len;
2128 /* Save the contents of the option in a buffer. */
2129 if (!buffer_allocate (&bp, len, MDL)) {
2130 log_error ("no memory for option buffer.");
2131 return 0;
2132 }
2133 buffer_reference (&result -> buffer, bp, MDL);
2134 result -> len = 3;
2135 result -> data = &bp -> data [0];
2136
2137 memset (&bp -> data [0], 0, len);
2138 if (results [FQDN_NO_CLIENT_UPDATE].len &&
2139 results [FQDN_NO_CLIENT_UPDATE].data [0])
2140 bp -> data [0] |= 2;
2141 if (results [FQDN_SERVER_UPDATE].len &&
2142 results [FQDN_SERVER_UPDATE].data [0])
2143 bp -> data [0] |= 1;
2144 if (results [FQDN_RCODE1].len)
2145 bp -> data [1] = results [FQDN_RCODE1].data [0];
2146 if (results [FQDN_RCODE2].len)
2147 bp -> data [2] = results [FQDN_RCODE2].data [0];
2148
2149 if (results [FQDN_ENCODED].len &&
2150 results [FQDN_ENCODED].data [0]) {
2151 unsigned char *out;
2152 int i;
2153 bp -> data [0] |= 4;
2154 out = &bp -> data [3];
2155 if (results [FQDN_FQDN].len) {
2156 i = 0;
2157 while (i < results [FQDN_FQDN].len) {
2158 int j;
2159 for (j = i; ('.' !=
2160 results [FQDN_FQDN].data [j]) &&
2161 j < results [FQDN_FQDN].len; j++)
2162 ;
2163 *out++ = j - i;
2164 memcpy (out, &results [FQDN_FQDN].data [i],
2165 (unsigned)(j - i));
2166 out += j - i;
2167 i = j;
2168 if (results [FQDN_FQDN].data [j] == '.')
2169 i++;
2170 }
2171 if ((results [FQDN_FQDN].data
2172 [results [FQDN_FQDN].len - 1] == '.'))
2173 *out++ = 0;
2174 result -> len = out - result -> data;
2175 result -> terminated = 0;
2176 }
2177 } else {
2178 if (results [FQDN_FQDN].len) {
2179 memcpy (&bp -> data [3], results [FQDN_FQDN].data,
2180 results [FQDN_FQDN].len);
2181 result -> len += results [FQDN_FQDN].len;
2182 result -> terminated = 0;
2183 }
2184 }
2185 for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) {
2186 if (results [i].len)
2187 data_string_forget (&results [i], MDL);
2188 }
2189 buffer_dereference (&bp, MDL);
2190 return 1;
2191 }
2192
2193 void option_space_foreach (struct packet *packet, struct lease *lease,
2194 struct client_state *client_state,
2195 struct option_state *in_options,
2196 struct option_state *cfg_options,
2197 struct binding_scope **scope,
2198 struct universe *u, void *stuff,
2199 void (*func) (struct option_cache *,
2200 struct packet *,
2201 struct lease *, struct client_state *,
2202 struct option_state *,
2203 struct option_state *,
2204 struct binding_scope **,
2205 struct universe *, void *))
2206 {
2207 if (u -> foreach)
2208 (*u -> foreach) (packet, lease, client_state, in_options,
2209 cfg_options, scope, u, stuff, func);
2210 }
2211
2212 void suboption_foreach (struct packet *packet, struct lease *lease,
2213 struct client_state *client_state,
2214 struct option_state *in_options,
2215 struct option_state *cfg_options,
2216 struct binding_scope **scope,
2217 struct universe *u, void *stuff,
2218 void (*func) (struct option_cache *,
2219 struct packet *,
2220 struct lease *, struct client_state *,
2221 struct option_state *,
2222 struct option_state *,
2223 struct binding_scope **,
2224 struct universe *, void *),
2225 struct option_cache *oc,
2226 const char *vsname)
2227 {
2228 struct universe *universe = find_option_universe (oc -> option,
2229 vsname);
2230 int i;
2231
2232 if (universe -> foreach)
2233 (*universe -> foreach) (packet, lease, client_state,
2234 in_options, cfg_options,
2235 scope, universe, stuff, func);
2236 }
2237
2238 void hashed_option_space_foreach (struct packet *packet, struct lease *lease,
2239 struct client_state *client_state,
2240 struct option_state *in_options,
2241 struct option_state *cfg_options,
2242 struct binding_scope **scope,
2243 struct universe *u, void *stuff,
2244 void (*func) (struct option_cache *,
2245 struct packet *,
2246 struct lease *,
2247 struct client_state *,
2248 struct option_state *,
2249 struct option_state *,
2250 struct binding_scope **,
2251 struct universe *, void *))
2252 {
2253 pair *hash;
2254 int i;
2255 struct option_cache *oc;
2256
2257 if (cfg_options -> universe_count <= u -> index)
2258 return;
2259
2260 hash = cfg_options -> universes [u -> index];
2261 if (!hash)
2262 return;
2263 for (i = 0; i < OPTION_HASH_SIZE; i++) {
2264 pair p;
2265 /* XXX save _all_ options! XXX */
2266 for (p = hash [i]; p; p = p -> cdr) {
2267 oc = (struct option_cache *)p -> car;
2268 (*func) (oc, packet, lease, client_state,
2269 in_options, cfg_options, scope, u, stuff);
2270 }
2271 }
2272 }
2273
2274 void save_linked_option (universe, options, oc)
2275 struct universe *universe;
2276 struct option_state *options;
2277 struct option_cache *oc;
2278 {
2279 pair *tail;
2280 pair np = (pair )0;
2281 struct option_chain_head *head;
2282
2283 if (universe -> index >= options -> universe_count)
2284 return;
2285 head = ((struct option_chain_head *)
2286 options -> universes [universe -> index]);
2287 if (!head) {
2288 if (!option_chain_head_allocate (((struct option_chain_head **)
2289 &options -> universes
2290 [universe -> index]), MDL))
2291 return;
2292 head = ((struct option_chain_head *)
2293 options -> universes [universe -> index]);
2294 }
2295
2296 /* Find the tail of the list. */
2297 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2298 if (oc -> option ==
2299 ((struct option_cache *)((*tail) -> car)) -> option) {
2300 option_cache_dereference ((struct option_cache **)
2301 (&(*tail) -> car), MDL);
2302 option_cache_reference ((struct option_cache **)
2303 (&(*tail) -> car), oc, MDL);
2304 return;
2305 }
2306 }
2307
2308 *tail = cons (0, 0);
2309 if (*tail) {
2310 option_cache_reference ((struct option_cache **)
2311 (&(*tail) -> car), oc, MDL);
2312 }
2313 }
2314
2315 int linked_option_space_encapsulate (result, packet, lease, client_state,
2316 in_options, cfg_options, scope, universe)
2317 struct data_string *result;
2318 struct packet *packet;
2319 struct lease *lease;
2320 struct client_state *client_state;
2321 struct option_state *in_options;
2322 struct option_state *cfg_options;
2323 struct binding_scope **scope;
2324 struct universe *universe;
2325 {
2326 int status;
2327 pair oc;
2328 struct option_chain_head *head;
2329
2330 if (universe -> index >= cfg_options -> universe_count)
2331 return 0;
2332 head = ((struct option_chain_head *)
2333 cfg_options -> universes [universe -> index]);
2334 if (!head)
2335 return 0;
2336
2337 status = 0;
2338 for (oc = head -> first; oc; oc = oc -> cdr) {
2339 if (store_option (result, universe, packet,
2340 lease, client_state, in_options, cfg_options,
2341 scope, (struct option_cache *)(oc -> car)))
2342 status = 1;
2343 }
2344
2345 return status;
2346 }
2347
2348 void delete_linked_option (universe, options, code)
2349 struct universe *universe;
2350 struct option_state *options;
2351 int code;
2352 {
2353 pair *tail, tmp = (pair)0;
2354 struct option_chain_head *head;
2355
2356 if (universe -> index >= options -> universe_count)
2357 return;
2358 head = ((struct option_chain_head *)
2359 options -> universes [universe -> index]);
2360 if (!head)
2361 return;
2362
2363 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2364 if (code ==
2365 ((struct option_cache *)(*tail) -> car) -> option -> code)
2366 {
2367 tmp = (*tail) -> cdr;
2368 option_cache_dereference ((struct option_cache **)
2369 (&(*tail) -> car), MDL);
2370 dfree (*tail, MDL);
2371 (*tail) = tmp;
2372 break;
2373 }
2374 }
2375 }
2376
2377 struct option_cache *lookup_linked_option (universe, options, code)
2378 struct universe *universe;
2379 struct option_state *options;
2380 unsigned code;
2381 {
2382 pair oc;
2383 struct option_chain_head *head;
2384
2385 if (universe -> index >= options -> universe_count)
2386 return 0;
2387 head = ((struct option_chain_head *)
2388 options -> universes [universe -> index]);
2389 if (!head)
2390 return 0;
2391
2392 for (oc = head -> first; oc; oc = oc -> cdr) {
2393 if (code ==
2394 ((struct option_cache *)(oc -> car)) -> option -> code) {
2395 return (struct option_cache *)(oc -> car);
2396 }
2397 }
2398
2399 return (struct option_cache *)0;
2400 }
2401
2402 int linked_option_state_dereference (universe, state, file, line)
2403 struct universe *universe;
2404 struct option_state *state;
2405 const char *file;
2406 int line;
2407 {
2408 return (option_chain_head_dereference
2409 ((struct option_chain_head **)
2410 (&state -> universes [universe -> index]), MDL));
2411 }
2412
2413 void linked_option_space_foreach (struct packet *packet, struct lease *lease,
2414 struct client_state *client_state,
2415 struct option_state *in_options,
2416 struct option_state *cfg_options,
2417 struct binding_scope **scope,
2418 struct universe *u, void *stuff,
2419 void (*func) (struct option_cache *,
2420 struct packet *,
2421 struct lease *,
2422 struct client_state *,
2423 struct option_state *,
2424 struct option_state *,
2425 struct binding_scope **,
2426 struct universe *, void *))
2427 {
2428 pair car;
2429 struct option_chain_head *head;
2430
2431 if (u -> index >= cfg_options -> universe_count)
2432 return;
2433 head = ((struct option_chain_head *)
2434 cfg_options -> universes [u -> index]);
2435 if (!head)
2436 return;
2437 for (car = head -> first; car; car = car -> cdr) {
2438 (*func) ((struct option_cache *)(car -> car),
2439 packet, lease, client_state,
2440 in_options, cfg_options, scope, u, stuff);
2441 }
2442 }
2443
2444 void do_packet (interface, packet, len, from_port, from, hfrom)
2445 struct interface_info *interface;
2446 struct dhcp_packet *packet;
2447 unsigned len;
2448 unsigned int from_port;
2449 struct iaddr from;
2450 struct hardware *hfrom;
2451 {
2452 int i;
2453 struct option_cache *op;
2454 struct packet *decoded_packet;
2455 #if defined (DEBUG_MEMORY_LEAKAGE)
2456 unsigned long previous_outstanding = dmalloc_outstanding;
2457 #endif
2458
2459 #if defined (TRACING)
2460 trace_inpacket_stash (interface, packet, len, from_port, from, hfrom);
2461 #endif
2462
2463 decoded_packet = (struct packet *)0;
2464 if (!packet_allocate (&decoded_packet, MDL)) {
2465 log_error ("do_packet: no memory for incoming packet!");
2466 return;
2467 }
2468 decoded_packet -> raw = packet;
2469 decoded_packet -> packet_length = len;
2470 decoded_packet -> client_port = from_port;
2471 decoded_packet -> client_addr = from;
2472 interface_reference (&decoded_packet -> interface, interface, MDL);
2473 decoded_packet -> haddr = hfrom;
2474
2475 if (packet -> hlen > sizeof packet -> chaddr) {
2476 packet_dereference (&decoded_packet, MDL);
2477 log_info ("Discarding packet with bogus hlen.");
2478 return;
2479 }
2480
2481 /* If there's an option buffer, try to parse it. */
2482 if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) {
2483 if (!parse_options (decoded_packet)) {
2484 if (decoded_packet -> options)
2485 option_state_dereference
2486 (&decoded_packet -> options, MDL);
2487 packet_dereference (&decoded_packet, MDL);
2488 return;
2489 }
2490
2491 if (decoded_packet -> options_valid &&
2492 (op = lookup_option (&dhcp_universe,
2493 decoded_packet -> options,
2494 DHO_DHCP_MESSAGE_TYPE))) {
2495 struct data_string dp;
2496 memset (&dp, 0, sizeof dp);
2497 evaluate_option_cache (&dp, decoded_packet,
2498 (struct lease *)0,
2499 (struct client_state *)0,
2500 decoded_packet -> options,
2501 (struct option_state *)0,
2502 (struct binding_scope **)0,
2503 op, MDL);
2504 if (dp.len > 0)
2505 decoded_packet -> packet_type = dp.data [0];
2506 else
2507 decoded_packet -> packet_type = 0;
2508 data_string_forget (&dp, MDL);
2509 }
2510 }
2511
2512 if (decoded_packet -> packet_type)
2513 dhcp (decoded_packet);
2514 else
2515 bootp (decoded_packet);
2516
2517 /* If the caller kept the packet, they'll have upped the refcnt. */
2518 packet_dereference (&decoded_packet, MDL);
2519
2520 #if defined (DEBUG_MEMORY_LEAKAGE)
2521 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2522 dmalloc_generation,
2523 dmalloc_outstanding - previous_outstanding,
2524 dmalloc_outstanding, dmalloc_longterm);
2525 #endif
2526 #if defined (DEBUG_MEMORY_LEAKAGE)
2527 dmalloc_dump_outstanding ();
2528 #endif
2529 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2530 dump_rc_history (0);
2531 #endif
2532 }
2533