3 DHCP options parsing and reassembly. */
6 * Copyright (c) 1995-2002 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
45 static char copyright[] =
46 "$Id: options.c,v 1.85.2.9 2002/11/17 02:26:58 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium. All rights reserved.\n";
49 #define DHCP_OPTION_DATA
51 #include <omapip/omapip_p.h>
53 struct option *vendor_cfg_option;
55 static void do_option_set PROTO ((pair *,
56 struct option_cache *,
59 /* Parse all available options out of the specified packet. */
61 int parse_options (packet)
62 struct packet *packet;
65 struct option_cache *op = (struct option_cache *)0;
67 /* Allocate a new option state. */
68 if (!option_state_allocate (&packet -> options, MDL)) {
69 packet -> options_valid = 0;
73 /* If we don't see the magic cookie, there's nothing to parse. */
74 if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
75 packet -> options_valid = 0;
79 /* Go through the options field, up to the end of the packet
81 if (!parse_option_buffer (packet -> options,
82 &packet -> raw -> options [4],
83 (packet -> packet_length -
84 DHCP_FIXED_NON_UDP - 4),
88 /* If we parsed a DHCP Option Overload option, parse more
89 options out of the buffer(s) containing them. */
90 if (packet -> options_valid &&
91 (op = lookup_option (&dhcp_universe, packet -> options,
92 DHO_DHCP_OPTION_OVERLOAD))) {
93 if (op -> data.data [0] & 1) {
94 if (!parse_option_buffer
96 (unsigned char *)packet -> raw -> file,
97 sizeof packet -> raw -> file,
101 if (op -> data.data [0] & 2) {
102 if (!parse_option_buffer
104 (unsigned char *)packet -> raw -> sname,
105 sizeof packet -> raw -> sname,
110 packet -> options_valid = 1;
114 /* Parse options out of the specified buffer, storing addresses of option
115 values in packet -> options and setting packet -> options_valid if no
116 errors are encountered. */
118 int parse_option_buffer (options, buffer, length, universe)
119 struct option_state *options;
120 const unsigned char *buffer;
122 struct universe *universe;
125 const unsigned char *end = buffer + length;
126 unsigned len, offset;
128 struct option_cache *op = (struct option_cache *)0;
129 struct buffer *bp = (struct buffer *)0;
131 if (!buffer_allocate (&bp, length, MDL)) {
132 log_error ("no memory for option buffer.");
135 memcpy (bp -> data, buffer, length);
137 for (offset = 0; buffer [offset] != DHO_END && offset < length; ) {
138 code = buffer [offset];
139 /* Pad options don't have a length - just skip them. */
140 if (code == DHO_PAD) {
145 /* Don't look for length if the buffer isn't that big. */
146 if (offset + 2 > length) {
151 /* All other fields (except end, see above) have a
153 len = buffer [offset + 1];
155 /* If the length is outrageous, the options are bad. */
156 if (offset + len + 2 > length) {
158 log_error ("parse_option_buffer: option %s (%d) %s.",
159 dhcp_options [code].name, len,
160 "larger than buffer");
161 buffer_dereference (&bp, MDL);
165 /* If the option contains an encapsulation, parse it. If
166 the parse fails, or the option isn't an encapsulation (by
167 far the most common case), or the option isn't entirely
168 an encapsulation, keep the raw data as well. */
169 if (!((universe -> options [code] -> format [0] == 'e' ||
170 universe -> options [code] -> format [0] == 'E') &&
171 (parse_encapsulated_suboptions
172 (options, universe -> options [code],
173 buffer + offset + 2, len,
174 universe, (const char *)0)))) {
175 save_option_buffer (universe, options, bp,
176 &bp -> data [offset + 2], len,
177 universe -> options [code], 1);
181 buffer_dereference (&bp, MDL);
185 /* If an option in an option buffer turns out to be an encapsulation,
186 figure out what to do. If we don't know how to de-encapsulate it,
187 or it's not well-formed, return zero; otherwise, return 1, indicating
188 that we succeeded in de-encapsulating it. */
190 struct universe *find_option_universe (struct option *eopt, const char *uname)
194 struct universe *universe = (struct universe *)0;
196 /* Look for the E option in the option format. */
197 s = strchr (eopt -> format, 'E');
199 log_error ("internal encapsulation format error 1.");
202 /* Look for the universe name in the option format. */
203 t = strchr (++s, '.');
204 /* If there was no trailing '.', or there's something after the
205 trailing '.', the option is bogus and we can't use it. */
207 log_error ("internal encapsulation format error 2.");
210 if (t == s && uname) {
211 for (i = 0; i < universe_count; i++) {
212 if (!strcmp (universes [i] -> name, uname)) {
213 universe = universes [i];
218 for (i = 0; i < universe_count; i++) {
219 if (strlen (universes [i] -> name) == t - s &&
220 !memcmp (universes [i] -> name,
221 s, (unsigned)(t - s))) {
222 universe = universes [i];
230 /* If an option in an option buffer turns out to be an encapsulation,
231 figure out what to do. If we don't know how to de-encapsulate it,
232 or it's not well-formed, return zero; otherwise, return 1, indicating
233 that we succeeded in de-encapsulating it. */
235 int parse_encapsulated_suboptions (struct option_state *options,
237 const unsigned char *buffer,
238 unsigned len, struct universe *eu,
242 struct universe *universe = find_option_universe (eopt, uname);
244 /* If we didn't find the universe, we can't do anything with it
245 right now (e.g., we can't decode vendor options until we've
246 decoded the packet and executed the scopes that it matches). */
250 /* If we don't have a decoding function for it, we can't decode
252 if (!universe -> decode)
255 i = (*universe -> decode) (options, buffer, len, universe);
257 /* If there is stuff before the suboptions, we have to keep it. */
258 if (eopt -> format [0] != 'E')
260 /* Otherwise, return the status of the decode function. */
264 int fqdn_universe_decode (struct option_state *options,
265 const unsigned char *buffer,
266 unsigned length, struct universe *u)
269 struct buffer *bp = (struct buffer *)0;
271 /* FQDN options have to be at least four bytes long. */
275 /* Save the contents of the option in a buffer. */
276 if (!buffer_allocate (&bp, length + 4, MDL)) {
277 log_error ("no memory for option buffer.");
280 memcpy (&bp -> data [3], buffer + 1, length - 1);
282 if (buffer [0] & 4) /* encoded */
286 if (!save_option_buffer (&fqdn_universe, options, bp,
288 &fqdn_options [FQDN_ENCODED], 0)) {
290 buffer_dereference (&bp, MDL);
294 if (buffer [0] & 1) /* server-update */
298 if (buffer [0] & 2) /* no-client-update */
303 /* XXX Ideally we should store the name in DNS format, so if the
304 XXX label isn't in DNS format, we convert it to DNS format,
305 XXX rather than converting labels specified in DNS format to
306 XXX the plain ASCII representation. But that's hard, so
309 /* Not encoded using DNS format? */
310 if (!bp -> data [0]) {
313 /* Some broken clients NUL-terminate this option. */
314 if (buffer [length - 1] == 0) {
319 /* Determine the length of the hostname component of the
320 name. If the name contains no '.' character, it
321 represents a non-qualified label. */
322 for (i = 3; i < length && buffer [i] != '.'; i++);
325 /* Note: If the client sends a FQDN, the first '.' will
326 be used as a NUL terminator for the hostname. */
328 if (!save_option_buffer (&fqdn_universe, options, bp,
330 &fqdn_options [FQDN_HOSTNAME],
333 /* Note: If the client sends a single label, the
334 FQDN_DOMAINNAME option won't be set. */
335 if (length > 4 + i &&
336 !save_option_buffer (&fqdn_universe, options, bp,
337 &bp -> data[6 + i], length - 4 - i,
338 &fqdn_options [FQDN_DOMAINNAME], 1))
340 /* Also save the whole name. */
342 if (!save_option_buffer (&fqdn_universe, options, bp,
343 &bp -> data [5], length - 3,
344 &fqdn_options [FQDN_FQDN], 1))
348 unsigned total_len = 0;
349 unsigned first_len = 0;
355 while (s < &bp -> data[0] + length + 2) {
358 log_info ("fancy bits in fqdn option");
365 if (s + len > &bp -> data [0] + length + 3) {
366 log_info ("fqdn tag longer than buffer");
370 if (first_len == 0) {
376 total_len += len + 1;
379 /* We wind up with a length that's one too many because
380 we shouldn't increment for the last label, but there's
381 no way to tell we're at the last label until we exit
387 first_len = total_len;
391 !save_option_buffer (&fqdn_universe, options, bp,
392 &bp -> data[6], first_len,
393 &fqdn_options [FQDN_HOSTNAME], 0))
395 if (total_len > 0 && first_len != total_len) {
396 if (!save_option_buffer
397 (&fqdn_universe, options, bp,
398 &bp -> data[6 + first_len], total_len - first_len,
399 &fqdn_options [FQDN_DOMAINNAME], 1))
403 if (!save_option_buffer (&fqdn_universe, options, bp,
404 &bp -> data [6], total_len,
405 &fqdn_options [FQDN_FQDN], 1))
409 if (!save_option_buffer (&fqdn_universe, options, bp,
411 &fqdn_options [FQDN_NO_CLIENT_UPDATE], 0))
413 if (!save_option_buffer (&fqdn_universe, options, bp,
415 &fqdn_options [FQDN_SERVER_UPDATE], 0))
418 if (!save_option_buffer (&fqdn_universe, options, bp,
420 &fqdn_options [FQDN_RCODE1], 0))
422 if (!save_option_buffer (&fqdn_universe, options, bp,
424 &fqdn_options [FQDN_RCODE2], 0))
427 buffer_dereference (&bp, MDL);
431 /* cons options into a big buffer, and then split them out into the
432 three seperate buffers if needed. This allows us to cons up a set
433 of vendor options using the same routine. */
435 int cons_options (inpacket, outpacket, lease, client_state,
436 mms, in_options, cfg_options,
437 scope, overload, terminate, bootpp, prl, vuname)
438 struct packet *inpacket;
439 struct dhcp_packet *outpacket;
441 struct client_state *client_state;
443 struct option_state *in_options;
444 struct option_state *cfg_options;
445 struct binding_scope **scope;
446 int overload; /* Overload flags that may be set. */
449 struct data_string *prl;
452 #define PRIORITY_COUNT 300
453 unsigned priority_list [PRIORITY_COUNT];
455 unsigned char buffer [4096]; /* Really big buffer... */
456 unsigned main_buffer_size;
457 unsigned mainbufix, bufix, agentix;
458 unsigned option_size;
461 struct option_cache *op;
462 struct data_string ds;
467 memset (&ds, 0, sizeof ds);
469 /* If there's a Maximum Message Size option in the incoming packet
470 and no alternate maximum message size has been specified, take the
471 one in the packet. */
473 if (!mms && inpacket &&
474 (op = lookup_option (&dhcp_universe, inpacket -> options,
475 DHO_DHCP_MAX_MESSAGE_SIZE))) {
476 evaluate_option_cache (&ds, inpacket,
477 lease, client_state, in_options,
478 cfg_options, scope, op, MDL);
479 if (ds.len >= sizeof (u_int16_t))
480 mms = getUShort (ds.data);
481 data_string_forget (&ds, MDL);
484 /* If the client has provided a maximum DHCP message size,
485 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
486 use up to the minimum IP MTU size (576 bytes). */
487 /* XXX if a BOOTP client specifies a max message size, we will
491 main_buffer_size = mms - DHCP_FIXED_LEN;
493 /* Enforce a minimum packet size... */
494 if (main_buffer_size < (576 - DHCP_FIXED_LEN))
495 main_buffer_size = 576 - DHCP_FIXED_LEN;
499 inpacket -> packet_length - DHCP_FIXED_LEN;
500 if (main_buffer_size < 64)
501 main_buffer_size = 64;
503 main_buffer_size = 64;
505 main_buffer_size = 576 - DHCP_FIXED_LEN;
507 /* Set a hard limit at the size of the output buffer. */
508 if (main_buffer_size > sizeof buffer)
509 main_buffer_size = sizeof buffer;
511 /* Preload the option priority list with mandatory options. */
513 priority_list [priority_len++] = DHO_DHCP_MESSAGE_TYPE;
514 priority_list [priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
515 priority_list [priority_len++] = DHO_DHCP_LEASE_TIME;
516 priority_list [priority_len++] = DHO_DHCP_MESSAGE;
517 priority_list [priority_len++] = DHO_DHCP_REQUESTED_ADDRESS;
518 priority_list [priority_len++] = DHO_FQDN;
520 if (prl && prl -> len > 0) {
521 if ((op = lookup_option (&dhcp_universe, cfg_options,
522 DHO_SUBNET_SELECTION))) {
523 if (priority_len < PRIORITY_COUNT)
524 priority_list [priority_len++] =
525 DHO_SUBNET_SELECTION;
528 data_string_truncate (prl, (PRIORITY_COUNT - priority_len));
530 for (i = 0; i < prl -> len; i++) {
531 /* Prevent client from changing order of delivery
532 of relay agent information option. */
533 if (prl -> data [i] != DHO_DHCP_AGENT_OPTIONS)
534 priority_list [priority_len++] =
538 /* First, hardcode some more options that ought to be
540 priority_list [priority_len++] = DHO_SUBNET_MASK;
541 priority_list [priority_len++] = DHO_ROUTERS;
542 priority_list [priority_len++] = DHO_DOMAIN_NAME_SERVERS;
543 priority_list [priority_len++] = DHO_HOST_NAME;
545 /* Append a list of the standard DHCP options from the
546 standard DHCP option space. Actually, if a site
547 option space hasn't been specified, we wind up
548 treating the dhcp option space as the site option
549 space, and the first for loop is skipped, because
550 it's slightly more general to do it this way,
551 taking the 1Q99 DHCP futures work into account. */
552 if (cfg_options -> site_code_min) {
553 for (i = 0; i < OPTION_HASH_SIZE; i++) {
554 hash = cfg_options -> universes [dhcp_universe.index];
556 for (pp = hash [i]; pp; pp = pp -> cdr) {
557 op = (struct option_cache *)(pp -> car);
558 if (op -> option -> code <
559 cfg_options -> site_code_min &&
560 priority_len < PRIORITY_COUNT &&
561 (op -> option -> code !=
562 DHO_DHCP_AGENT_OPTIONS))
563 priority_list [priority_len++] =
564 op -> option -> code;
570 /* Now cycle through the site option space, or if there
571 is no site option space, we'll be cycling through the
572 dhcp option space. */
573 for (i = 0; i < OPTION_HASH_SIZE; i++) {
574 hash = (cfg_options -> universes
575 [cfg_options -> site_universe]);
577 for (pp = hash [i]; pp; pp = pp -> cdr) {
578 op = (struct option_cache *)(pp -> car);
579 if (op -> option -> code >=
580 cfg_options -> site_code_min &&
581 priority_len < PRIORITY_COUNT &&
582 (op -> option -> code !=
583 DHO_DHCP_AGENT_OPTIONS))
584 priority_list [priority_len++] =
585 op -> option -> code;
589 /* Now go through all the universes for which options
590 were set and see if there are encapsulations for
591 them; if there are, put the encapsulation options
592 on the priority list as well. */
593 for (i = 0; i < cfg_options -> universe_count; i++) {
594 if (cfg_options -> universes [i] &&
595 universes [i] -> enc_opt &&
596 priority_len < PRIORITY_COUNT &&
597 universes [i] -> enc_opt -> universe == &dhcp_universe)
599 if (universes [i] -> enc_opt -> code !=
600 DHO_DHCP_AGENT_OPTIONS)
601 priority_list [priority_len++] =
602 universes [i] -> enc_opt -> code;
606 /* The vendor option space can't stand on its own, so always
607 add it to the list. */
608 if (priority_len < PRIORITY_COUNT)
609 priority_list [priority_len++] =
610 DHO_VENDOR_ENCAPSULATED_OPTIONS;
613 /* Copy the options into the big buffer... */
614 option_size = store_options (buffer,
615 (main_buffer_size - 7 +
616 ((overload & 1) ? DHCP_FILE_LEN : 0) +
617 ((overload & 2) ? DHCP_SNAME_LEN : 0)),
618 inpacket, lease, client_state,
619 in_options, cfg_options, scope,
620 priority_list, priority_len,
623 ((overload & 1) ? DHCP_FILE_LEN : 0)),
626 /* Put the cookie up front... */
627 memcpy (outpacket -> options, DHCP_OPTIONS_COOKIE, 4);
630 /* If we're going to have to overload, store the overload
631 option at the beginning. If we can, though, just store the
632 whole thing in the packet's option buffer and leave it at
634 if (option_size <= main_buffer_size - mainbufix) {
635 memcpy (&outpacket -> options [mainbufix],
636 buffer, option_size);
637 mainbufix += option_size;
639 if (mainbufix < main_buffer_size)
641 length = DHCP_FIXED_NON_UDP + mainbufix;
643 outpacket -> options [mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
644 outpacket -> options [mainbufix++] = 1;
645 if (option_size > main_buffer_size - mainbufix + DHCP_FILE_LEN)
646 outpacket -> options [mainbufix++] = 3;
648 outpacket -> options [mainbufix++] = 1;
650 memcpy (&outpacket -> options [mainbufix],
651 buffer, main_buffer_size - mainbufix);
652 length = DHCP_FIXED_NON_UDP + main_buffer_size;
653 agentix = main_buffer_size;
655 bufix = main_buffer_size - mainbufix;
657 if (option_size - bufix <= DHCP_FILE_LEN) {
658 memcpy (outpacket -> file,
659 &buffer [bufix], option_size - bufix);
660 mainbufix = option_size - bufix;
661 if (mainbufix < DHCP_FILE_LEN)
662 outpacket -> file [mainbufix++]
664 while (mainbufix < DHCP_FILE_LEN)
665 outpacket -> file [mainbufix++]
668 memcpy (outpacket -> file,
669 &buffer [bufix], DHCP_FILE_LEN);
670 bufix += DHCP_FILE_LEN;
673 if ((overload & 2) && option_size < bufix) {
674 memcpy (outpacket -> sname,
675 &buffer [bufix], option_size - bufix);
677 mainbufix = option_size - bufix;
678 if (mainbufix < DHCP_SNAME_LEN)
679 outpacket -> file [mainbufix++]
681 while (mainbufix < DHCP_SNAME_LEN)
682 outpacket -> file [mainbufix++]
687 /* Now hack in the agent options if there are any. */
688 priority_list [0] = DHO_DHCP_AGENT_OPTIONS;
691 store_options (&outpacket -> options [agentix],
692 1500 - DHCP_FIXED_LEN - agentix,
693 inpacket, lease, client_state,
694 in_options, cfg_options, scope,
695 priority_list, priority_len,
696 1500 - DHCP_FIXED_LEN - agentix,
697 1500 - DHCP_FIXED_LEN - agentix, 0, (char *)0);
699 /* Tack a DHO_END option onto the packet if we need to. */
700 if (agentix < 1500 - DHCP_FIXED_LEN && need_endopt)
701 outpacket -> options [agentix++] = DHO_END;
703 /* Figure out the length. */
704 length = DHCP_FIXED_NON_UDP + agentix;
708 /* Store all the requested options into the requested buffer. */
710 int store_options (buffer, buflen, packet, lease, client_state,
711 in_options, cfg_options, scope, priority_list, priority_len,
712 first_cutoff, second_cutoff, terminate, vuname)
713 unsigned char *buffer;
715 struct packet *packet;
717 struct client_state *client_state;
718 struct option_state *in_options;
719 struct option_state *cfg_options;
720 struct binding_scope **scope;
721 unsigned *priority_list;
723 unsigned first_cutoff, second_cutoff;
731 struct data_string od;
732 struct option_cache *oc;
736 memset (&od, 0, sizeof od);
738 /* Eliminate duplicate options in the parameter request list.
739 There's got to be some clever knuthian way to do this:
740 Eliminate all but the first occurance of a value in an array
741 of values without otherwise disturbing the order of the array. */
742 for (i = 0; i < priority_len - 1; i++) {
744 for (ix = i + 1; ix < priority_len + tto; ix++) {
746 priority_list [ix - tto] =
748 if (priority_list [i] == priority_list [ix]) {
755 /* Copy out the options in the order that they appear in the
757 for (i = 0; i < priority_len; i++) {
758 /* Number of bytes left to store (some may already
759 have been stored by a previous pass). */
763 int have_encapsulation = 0;
764 struct data_string encapsulation;
766 memset (&encapsulation, 0, sizeof encapsulation);
768 /* Code for next option to try to store. */
769 code = priority_list [i];
771 /* Look up the option in the site option space if the code
772 is above the cutoff, otherwise in the DHCP option space. */
773 if (code >= cfg_options -> site_code_min)
774 u = universes [cfg_options -> site_universe];
778 oc = lookup_option (u, cfg_options, code);
780 /* It's an encapsulation, try to find the universe
781 to be encapsulated first, except that if it's a straight
782 encapsulation and the user has provided a value for the
783 encapsulation option, use the user-provided value. */
784 if (u -> options [code] &&
785 ((u -> options [code] -> format [0] == 'E' && !oc) ||
786 u -> options [code] -> format [0] == 'e')) {
789 struct option_cache *tmp;
790 struct data_string name;
792 s = strchr (u -> options [code] -> format, 'E');
794 t = strchr (++s, '.');
796 memset (&name, 0, sizeof name);
798 /* A zero-length universe name means the vendor
799 option space, if one is defined. */
801 if (vendor_cfg_option) {
802 tmp = lookup_option (vendor_cfg_option -> universe,
804 vendor_cfg_option -> code);
806 evaluate_option_cache (&name, packet, lease,
812 name.data = (unsigned char *)s;
813 name.len = strlen (s);
816 name.data = (unsigned char *)s;
820 /* If we found a universe, and there are options configured
821 for that universe, try to encapsulate it. */
824 (option_space_encapsulate
825 (&encapsulation, packet, lease, client_state,
826 in_options, cfg_options, scope, &name));
827 data_string_forget (&name, MDL);
832 /* In order to avoid memory leaks, we have to get to here
833 with any option cache that we allocated in tmp not being
834 referenced by tmp, and whatever option cache is referenced
835 by oc being an actual reference. lookup_option doesn't
836 generate a reference (this needs to be fixed), so the
837 preceding goop ensures that if we *didn't* generate a new
838 option cache, oc still winds up holding an actual reference. */
840 /* If no data is available for this option, skip it. */
841 if (!oc && !have_encapsulation) {
845 /* Find the value of the option... */
847 evaluate_option_cache (&od, packet,
848 lease, client_state, in_options,
849 cfg_options, scope, oc, MDL);
851 data_string_forget (&encapsulation, MDL);
852 data_string_forget (&od, MDL);
853 have_encapsulation = 0;
858 /* We should now have a constant length for the option. */
860 if (have_encapsulation) {
861 length += encapsulation.len;
863 data_string_copy (&od, &encapsulation, MDL);
864 data_string_forget (&encapsulation, MDL);
866 struct buffer *bp = (struct buffer *)0;
867 if (!buffer_allocate (&bp, length, MDL)) {
868 option_cache_dereference (&oc, MDL);
869 data_string_forget (&od, MDL);
870 data_string_forget (&encapsulation, MDL);
873 memcpy (&bp -> data [0], od.data, od.len);
874 memcpy (&bp -> data [od.len], encapsulation.data,
876 data_string_forget (&od, MDL);
877 data_string_forget (&encapsulation, MDL);
878 od.data = &bp -> data [0];
879 buffer_reference (&od.buffer, bp, MDL);
880 buffer_dereference (&bp, MDL);
886 /* Do we add a NUL? */
887 if (terminate && dhcp_options [code].format [0] == 't') {
894 /* Try to store the option. */
896 /* If the option's length is more than 255, we must store it
897 in multiple hunks. Store 255-byte hunks first. However,
898 in any case, if the option data will cross a buffer
899 boundary, split it across that boundary. */
904 unsigned char incr = length > 255 ? 255 : length;
907 /* If this hunk of the buffer will cross a
908 boundary, only go up to the boundary in this
910 if (bufix < first_cutoff &&
911 bufix + incr > first_cutoff)
912 incr = first_cutoff - bufix;
913 else if (bufix < second_cutoff &&
914 bufix + incr > second_cutoff)
915 incr = second_cutoff - bufix;
917 /* If this option is going to overflow the buffer,
919 if (bufix + 2 + incr > buflen) {
924 /* Everything looks good - copy it in! */
925 buffer [bufix] = code;
926 buffer [bufix + 1] = incr;
927 if (tto && incr == length) {
928 memcpy (buffer + bufix + 2,
929 od.data + ix, (unsigned)(incr - 1));
930 buffer [bufix + 2 + incr - 1] = 0;
932 memcpy (buffer + bufix + 2,
933 od.data + ix, (unsigned)incr);
939 data_string_forget (&od, MDL);
945 /* Format the specified option so that a human can easily read it. */
947 const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
948 struct option *option;
949 const unsigned char *data;
954 static char optbuf [32768]; /* XXX */
961 struct enumeration *enumbuf [32];
964 const unsigned char *dp = data;
974 memset (enumbuf, 0, sizeof enumbuf);
976 /* Figure out the size of the data. */
977 for (l = i = 0; option -> format [i]; i++, l++) {
979 log_error ("%s: Extra codes in format string: %s",
981 &(option -> format [i]));
985 fmtbuf [l] = option -> format [i];
986 switch (option -> format [i]) {
998 /* Skip the universe name. */
999 while (option -> format [i] &&
1000 option -> format [i] != '.')
1003 for (k = 0; k < len; k++) {
1004 if (!isascii (data [k]) ||
1005 !isprint (data [k]))
1008 /* If we found no bogus characters, or the bogus
1009 character we found is a trailing NUL, it's
1010 okay to print this option as text. */
1011 if (k == len || (k + 1 == len && data [k] == 0)) {
1030 while (option -> format [i] &&
1031 option -> format [i] != '.')
1034 find_enumeration (&option -> format [k] + 1,
1063 log_error ("%s: garbage in format string: %s",
1065 &(option -> format [i]));
1070 /* Check for too few bytes... */
1071 if (hunksize - opthunk > len) {
1072 log_error ("%s: expecting at least %d bytes; got %d",
1077 /* Check for too many bytes... */
1078 if (numhunk == -1 && hunksize < len)
1079 log_error ("%s: %d extra bytes",
1083 /* If this is an array, compute its size. */
1085 numhunk = len / hunksize;
1086 /* See if we got an exact number of hunks. */
1087 if (numhunk > 0 && numhunk * hunksize < len)
1088 log_error ("%s: %d extra bytes at end of array\n",
1090 len - numhunk * hunksize);
1092 /* A one-hunk array prints the same as a single hunk. */
1096 /* Cycle through the array (or hunk) printing the data. */
1097 for (i = 0; i < numhunk; i++) {
1098 for (j = 0; j < numelem; j++) {
1099 switch (fmtbuf [j]) {
1103 for (; dp < data + len; dp++) {
1104 if (!isascii (*dp) ||
1106 /* Skip trailing NUL. */
1107 if (dp + 1 != data + len ||
1109 sprintf (op, "\\%03o",
1113 } else if (*dp == '"' ||
1127 /* pretty-printing an array of enums is
1128 going to get ugly. */
1133 if (!enumbuf [j] -> values [i].name)
1135 if (enumbuf [j] -> values [i].value ==
1139 strcpy (op, enumbuf [j] -> values [i].name);
1143 foo.s_addr = htonl (getULong (dp));
1144 strcpy (op, inet_ntoa (foo));
1148 sprintf (op, "%ld", (long)getLong (dp));
1152 tval = getULong (dp);
1154 sprintf (op, "%s", "infinite");
1156 sprintf (op, "%ld", tval);
1160 (unsigned long)getULong (dp));
1164 sprintf (op, "%d", (int)getShort (dp));
1168 sprintf (op, "%d", (unsigned)getUShort (dp));
1172 sprintf (op, "%d", *(const char *)dp++);
1176 sprintf (op, "%d", *dp++);
1179 sprintf (op, "%x", *dp++);
1182 strcpy (op, *dp++ ? "true" : "false");
1185 log_error ("Unexpected format code %c",
1189 if (dp == data + len)
1191 if (j + 1 < numelem && comma != ':')
1194 if (i + 1 < numhunk) {
1197 if (dp == data + len)
1203 int get_option (result, universe, packet, lease, client_state,
1204 in_options, cfg_options, options, scope, code, file, line)
1205 struct data_string *result;
1206 struct universe *universe;
1207 struct packet *packet;
1208 struct lease *lease;
1209 struct client_state *client_state;
1210 struct option_state *in_options;
1211 struct option_state *cfg_options;
1212 struct option_state *options;
1213 struct binding_scope **scope;
1218 struct option_cache *oc;
1220 if (!universe -> lookup_func)
1222 oc = ((*universe -> lookup_func) (universe, options, code));
1225 if (!evaluate_option_cache (result, packet, lease, client_state,
1226 in_options, cfg_options, scope, oc,
1232 void set_option (universe, options, option, op)
1233 struct universe *universe;
1234 struct option_state *options;
1235 struct option_cache *option;
1236 enum statement_op op;
1238 struct option_cache *oc, *noc;
1243 case eval_statement:
1244 case break_statement:
1246 log_error ("bogus statement type in do_option_set.");
1249 case default_option_statement:
1250 oc = lookup_option (universe, options,
1251 option -> option -> code);
1254 save_option (universe, options, option);
1257 case supersede_option_statement:
1258 case send_option_statement:
1259 /* Install the option, replacing any existing version. */
1260 save_option (universe, options, option);
1263 case append_option_statement:
1264 case prepend_option_statement:
1265 oc = lookup_option (universe, options,
1266 option -> option -> code);
1268 save_option (universe, options, option);
1271 /* If it's not an expression, make it into one. */
1272 if (!oc -> expression && oc -> data.len) {
1273 if (!expression_allocate (&oc -> expression, MDL)) {
1274 log_error ("Can't allocate const expression.");
1277 oc -> expression -> op = expr_const_data;
1279 (&oc -> expression -> data.const_data,
1281 data_string_forget (&oc -> data, MDL);
1283 noc = (struct option_cache *)0;
1284 if (!option_cache_allocate (&noc, MDL))
1286 if (op == append_option_statement) {
1287 if (!make_concat (&noc -> expression,
1289 option -> expression)) {
1290 option_cache_dereference (&noc, MDL);
1294 if (!make_concat (&noc -> expression,
1295 option -> expression,
1296 oc -> expression)) {
1297 option_cache_dereference (&noc, MDL);
1301 noc -> option = oc -> option;
1302 save_option (universe, options, noc);
1303 option_cache_dereference (&noc, MDL);
1308 struct option_cache *lookup_option (universe, options, code)
1309 struct universe *universe;
1310 struct option_state *options;
1314 return (struct option_cache *)0;
1315 if (universe -> lookup_func)
1316 return (*universe -> lookup_func) (universe, options, code);
1318 log_error ("can't look up options in %s space.",
1320 return (struct option_cache *)0;
1323 struct option_cache *lookup_hashed_option (universe, options, code)
1324 struct universe *universe;
1325 struct option_state *options;
1332 /* Make sure there's a hash table. */
1333 if (universe -> index >= options -> universe_count ||
1334 !(options -> universes [universe -> index]))
1335 return (struct option_cache *)0;
1337 hash = options -> universes [universe -> index];
1339 hashix = compute_option_hash (code);
1340 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1341 if (((struct option_cache *)(bptr -> car)) -> option -> code ==
1343 return (struct option_cache *)(bptr -> car);
1345 return (struct option_cache *)0;
1348 int save_option_buffer (struct universe *universe,
1349 struct option_state *options,
1351 unsigned char *buffer, unsigned length,
1352 struct option *option, int tp)
1354 struct buffer *lbp = (struct buffer *)0;
1355 struct option_cache *op = (struct option_cache *)0;
1357 if (!option_cache_allocate (&op, MDL)) {
1358 log_error ("No memory for option %s.%s.",
1364 /* If we weren't passed a buffer in which the data are saved and
1365 refcounted, allocate one now. */
1367 if (!buffer_allocate (&lbp, length, MDL)) {
1368 log_error ("no memory for option buffer.");
1370 option_cache_dereference (&op, MDL);
1373 memcpy (lbp -> data, buffer, length + tp);
1375 buffer = &bp -> data [0]; /* Refer to saved buffer. */
1378 /* Reference buffer copy to option cache. */
1379 op -> data.buffer = (struct buffer *)0;
1380 buffer_reference (&op -> data.buffer, bp, MDL);
1382 /* Point option cache into buffer. */
1383 op -> data.data = buffer;
1384 op -> data.len = length;
1387 /* NUL terminate (we can get away with this because we (or
1388 the caller!) allocated one more than the buffer size, and
1389 because the byte following the end of an option is always
1390 the code of the next option, which the caller is getting
1391 out of the *original* buffer. */
1392 buffer [length] = 0;
1393 op -> data.terminated = 1;
1395 op -> data.terminated = 0;
1397 op -> option = option;
1399 /* Now store the option. */
1400 save_option (universe, options, op);
1402 /* And let go of our reference. */
1403 option_cache_dereference (&op, MDL);
1408 void save_option (struct universe *universe,
1409 struct option_state *options, struct option_cache *oc)
1411 if (universe -> save_func)
1412 (*universe -> save_func) (universe, options, oc);
1414 log_error ("can't store options in %s space.",
1418 void save_hashed_option (universe, options, oc)
1419 struct universe *universe;
1420 struct option_state *options;
1421 struct option_cache *oc;
1425 pair *hash = options -> universes [universe -> index];
1427 if (oc -> refcnt == 0)
1430 /* Compute the hash. */
1431 hashix = compute_option_hash (oc -> option -> code);
1433 /* If there's no hash table, make one. */
1435 hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL);
1437 log_error ("no memory to store %s.%s",
1438 universe -> name, oc -> option -> name);
1441 memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash);
1442 options -> universes [universe -> index] = (VOIDPTR)hash;
1444 /* Try to find an existing option matching the new one. */
1445 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1446 if (((struct option_cache *)
1447 (bptr -> car)) -> option -> code ==
1448 oc -> option -> code)
1452 /* If we find one, dereference it and put the new one
1455 option_cache_dereference
1456 ((struct option_cache **)&bptr -> car, MDL);
1457 option_cache_reference
1458 ((struct option_cache **)&bptr -> car,
1464 /* Otherwise, just put the new one at the head of the list. */
1465 bptr = new_pair (MDL);
1467 log_error ("No memory for option_cache reference.");
1470 bptr -> cdr = hash [hashix];
1472 option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL);
1473 hash [hashix] = bptr;
1476 void delete_option (universe, options, code)
1477 struct universe *universe;
1478 struct option_state *options;
1481 if (universe -> delete_func)
1482 (*universe -> delete_func) (universe, options, code);
1484 log_error ("can't delete options from %s space.",
1488 void delete_hashed_option (universe, options, code)
1489 struct universe *universe;
1490 struct option_state *options;
1494 pair bptr, prev = (pair)0;
1495 pair *hash = options -> universes [universe -> index];
1497 /* There may not be any options in this space. */
1501 /* Try to find an existing option matching the new one. */
1502 hashix = compute_option_hash (code);
1503 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
1504 if (((struct option_cache *)(bptr -> car)) -> option -> code
1509 /* If we found one, wipe it out... */
1512 prev -> cdr = bptr -> cdr;
1514 hash [hashix] = bptr -> cdr;
1515 option_cache_dereference
1516 ((struct option_cache **)(&bptr -> car), MDL);
1517 free_pair (bptr, MDL);
1521 extern struct option_cache *free_option_caches; /* XXX */
1523 int option_cache_dereference (ptr, file, line)
1524 struct option_cache **ptr;
1528 if (!ptr || !*ptr) {
1529 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1531 #if defined (POINTER_DEBUG)
1539 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
1540 if (!(*ptr) -> refcnt) {
1541 if ((*ptr) -> data.buffer)
1542 data_string_forget (&(*ptr) -> data, file, line);
1543 if ((*ptr) -> expression)
1544 expression_dereference (&(*ptr) -> expression,
1547 option_cache_dereference (&((*ptr) -> next),
1549 /* Put it back on the free list... */
1550 (*ptr) -> expression = (struct expression *)free_option_caches;
1551 free_option_caches = *ptr;
1552 dmalloc_reuse (free_option_caches, (char *)0, 0, 0);
1554 if ((*ptr) -> refcnt < 0) {
1555 log_error ("%s(%d): negative refcnt!", file, line);
1556 #if defined (DEBUG_RC_HISTORY)
1557 dump_rc_history (*ptr);
1559 #if defined (POINTER_DEBUG)
1562 *ptr = (struct option_cache *)0;
1566 *ptr = (struct option_cache *)0;
1571 int hashed_option_state_dereference (universe, state, file, line)
1572 struct universe *universe;
1573 struct option_state *state;
1581 /* Get the pointer to the array of hash table bucket heads. */
1582 heads = (pair *)(state -> universes [universe -> index]);
1586 /* For each non-null head, loop through all the buckets dereferencing
1587 the attached option cache structures and freeing the buckets. */
1588 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1589 for (cp = heads [i]; cp; cp = next) {
1591 option_cache_dereference
1592 ((struct option_cache **)&cp -> car,
1594 free_pair (cp, file, line);
1598 dfree (heads, file, line);
1599 state -> universes [universe -> index] = (void *)0;
1603 int store_option (result, universe, packet, lease, client_state,
1604 in_options, cfg_options, scope, oc)
1605 struct data_string *result;
1606 struct universe *universe;
1607 struct packet *packet;
1608 struct lease *lease;
1609 struct client_state *client_state;
1610 struct option_state *in_options;
1611 struct option_state *cfg_options;
1612 struct binding_scope **scope;
1613 struct option_cache *oc;
1615 struct data_string d1, d2;
1617 memset (&d1, 0, sizeof d1);
1618 memset (&d2, 0, sizeof d2);
1620 if (evaluate_option_cache (&d2, packet, lease, client_state,
1621 in_options, cfg_options, scope, oc, MDL)) {
1622 if (!buffer_allocate (&d1.buffer,
1624 universe -> length_size +
1625 universe -> tag_size + d2.len), MDL)) {
1626 data_string_forget (result, MDL);
1627 data_string_forget (&d2, MDL);
1630 d1.data = &d1.buffer -> data [0];
1632 memcpy (d1.buffer -> data,
1633 result -> data, result -> len);
1634 d1.len = result -> len;
1635 (*universe -> store_tag) (&d1.buffer -> data [d1.len],
1636 oc -> option -> code);
1637 d1.len += universe -> tag_size;
1638 (*universe -> store_length) (&d1.buffer -> data [d1.len],
1640 d1.len += universe -> length_size;
1641 memcpy (&d1.buffer -> data [d1.len], d2.data, d2.len);
1643 data_string_forget (&d2, MDL);
1644 data_string_forget (result, MDL);
1645 data_string_copy (result, &d1, MDL);
1646 data_string_forget (&d1, MDL);
1652 int option_space_encapsulate (result, packet, lease, client_state,
1653 in_options, cfg_options, scope, name)
1654 struct data_string *result;
1655 struct packet *packet;
1656 struct lease *lease;
1657 struct client_state *client_state;
1658 struct option_state *in_options;
1659 struct option_state *cfg_options;
1660 struct binding_scope **scope;
1661 struct data_string *name;
1665 u = (struct universe *)0;
1666 universe_hash_lookup (&u, universe_hash,
1667 (const char *)name -> data, name -> len, MDL);
1671 if (u -> encapsulate)
1672 return (*u -> encapsulate) (result, packet, lease,
1674 in_options, cfg_options, scope, u);
1675 log_error ("encapsulation requested for %s with no support.",
1680 int hashed_option_space_encapsulate (result, packet, lease, client_state,
1681 in_options, cfg_options, scope, universe)
1682 struct data_string *result;
1683 struct packet *packet;
1684 struct lease *lease;
1685 struct client_state *client_state;
1686 struct option_state *in_options;
1687 struct option_state *cfg_options;
1688 struct binding_scope **scope;
1689 struct universe *universe;
1695 if (universe -> index >= cfg_options -> universe_count)
1698 hash = cfg_options -> universes [universe -> index];
1703 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1704 for (p = hash [i]; p; p = p -> cdr) {
1705 if (store_option (result, universe, packet,
1706 lease, client_state, in_options,
1708 (struct option_cache *)p -> car))
1716 int nwip_option_space_encapsulate (result, packet, lease, client_state,
1717 in_options, cfg_options, scope, universe)
1718 struct data_string *result;
1719 struct packet *packet;
1720 struct lease *lease;
1721 struct client_state *client_state;
1722 struct option_state *in_options;
1723 struct option_state *cfg_options;
1724 struct binding_scope **scope;
1725 struct universe *universe;
1730 static struct option_cache *no_nwip;
1731 struct data_string ds;
1732 struct option_chain_head *head;
1734 if (universe -> index >= cfg_options -> universe_count)
1736 head = ((struct option_chain_head *)
1737 cfg_options -> universes [fqdn_universe.index]);
1742 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
1743 struct option_cache *oc = (struct option_cache *)(ocp -> car);
1744 if (store_option (result, universe, packet,
1745 lease, client_state, in_options,
1747 (struct option_cache *)ocp -> car))
1751 /* If there's no data, the nwip suboption is supposed to contain
1752 a suboption saying there's no data. */
1755 static unsigned char nni [] = { 1, 0 };
1756 memset (&ds, 0, sizeof ds);
1759 if (option_cache_allocate (&no_nwip, MDL))
1760 data_string_copy (&no_nwip -> data, &ds, MDL);
1761 no_nwip -> option = nwip_universe.options [1];
1764 if (store_option (result, universe, packet, lease,
1765 client_state, in_options,
1766 cfg_options, scope, no_nwip))
1770 memset (&ds, 0, sizeof ds);
1772 /* If we have nwip options, the first one has to be the
1773 nwip-exists-in-option-area option. */
1774 if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) {
1775 data_string_forget (result, MDL);
1778 ds.data = &ds.buffer -> data [0];
1779 ds.buffer -> data [0] = 2;
1780 ds.buffer -> data [1] = 0;
1781 memcpy (&ds.buffer -> data [2], result -> data, result -> len);
1782 data_string_forget (result, MDL);
1783 data_string_copy (result, &ds, MDL);
1784 data_string_forget (&ds, MDL);
1790 int fqdn_option_space_encapsulate (result, packet, lease, client_state,
1791 in_options, cfg_options, scope, universe)
1792 struct data_string *result;
1793 struct packet *packet;
1794 struct lease *lease;
1795 struct client_state *client_state;
1796 struct option_state *in_options;
1797 struct option_state *cfg_options;
1798 struct binding_scope **scope;
1799 struct universe *universe;
1802 struct data_string results [FQDN_SUBOPTION_COUNT + 1];
1805 struct buffer *bp = (struct buffer *)0;
1806 struct option_chain_head *head;
1808 /* If there's no FQDN universe, don't encapsulate. */
1809 if (fqdn_universe.index >= cfg_options -> universe_count)
1811 head = ((struct option_chain_head *)
1812 cfg_options -> universes [fqdn_universe.index]);
1816 /* Figure out the values of all the suboptions. */
1817 memset (results, 0, sizeof results);
1818 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
1819 struct option_cache *oc = (struct option_cache *)(ocp -> car);
1820 if (oc -> option -> code > FQDN_SUBOPTION_COUNT)
1822 evaluate_option_cache (&results [oc -> option -> code],
1823 packet, lease, client_state, in_options,
1824 cfg_options, scope, oc, MDL);
1826 len = 4 + results [FQDN_FQDN].len;
1827 /* Save the contents of the option in a buffer. */
1828 if (!buffer_allocate (&bp, len, MDL)) {
1829 log_error ("no memory for option buffer.");
1832 buffer_reference (&result -> buffer, bp, MDL);
1834 result -> data = &bp -> data [0];
1836 memset (&bp -> data [0], 0, len);
1837 if (results [FQDN_NO_CLIENT_UPDATE].len &&
1838 results [FQDN_NO_CLIENT_UPDATE].data [0])
1839 bp -> data [0] |= 2;
1840 if (results [FQDN_SERVER_UPDATE].len &&
1841 results [FQDN_SERVER_UPDATE].data [0])
1842 bp -> data [0] |= 1;
1843 if (results [FQDN_RCODE1].len)
1844 bp -> data [1] = results [FQDN_RCODE1].data [0];
1845 if (results [FQDN_RCODE2].len)
1846 bp -> data [2] = results [FQDN_RCODE2].data [0];
1848 if (results [FQDN_ENCODED].len &&
1849 results [FQDN_ENCODED].data [0]) {
1852 bp -> data [0] |= 4;
1853 out = &bp -> data [3];
1854 if (results [FQDN_FQDN].len) {
1856 while (i < results [FQDN_FQDN].len) {
1859 results [FQDN_FQDN].data [j]) &&
1860 j < results [FQDN_FQDN].len; j++)
1863 memcpy (out, &results [FQDN_FQDN].data [i],
1867 if (results [FQDN_FQDN].data [j] == '.')
1870 if ((results [FQDN_FQDN].data
1871 [results [FQDN_FQDN].len - 1] == '.'))
1873 result -> len = out - result -> data;
1874 result -> terminated = 0;
1877 if (results [FQDN_FQDN].len) {
1878 memcpy (&bp -> data [3], results [FQDN_FQDN].data,
1879 results [FQDN_FQDN].len);
1880 result -> len += results [FQDN_FQDN].len;
1881 result -> terminated = 0;
1884 for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) {
1885 if (results [i].len)
1886 data_string_forget (&results [i], MDL);
1888 buffer_dereference (&bp, MDL);
1892 void option_space_foreach (struct packet *packet, struct lease *lease,
1893 struct client_state *client_state,
1894 struct option_state *in_options,
1895 struct option_state *cfg_options,
1896 struct binding_scope **scope,
1897 struct universe *u, void *stuff,
1898 void (*func) (struct option_cache *,
1900 struct lease *, struct client_state *,
1901 struct option_state *,
1902 struct option_state *,
1903 struct binding_scope **,
1904 struct universe *, void *))
1907 (*u -> foreach) (packet, lease, client_state, in_options,
1908 cfg_options, scope, u, stuff, func);
1911 void suboption_foreach (struct packet *packet, struct lease *lease,
1912 struct client_state *client_state,
1913 struct option_state *in_options,
1914 struct option_state *cfg_options,
1915 struct binding_scope **scope,
1916 struct universe *u, void *stuff,
1917 void (*func) (struct option_cache *,
1919 struct lease *, struct client_state *,
1920 struct option_state *,
1921 struct option_state *,
1922 struct binding_scope **,
1923 struct universe *, void *),
1924 struct option_cache *oc,
1927 struct universe *universe = find_option_universe (oc -> option,
1931 if (universe -> foreach)
1932 (*universe -> foreach) (packet, lease, client_state,
1933 in_options, cfg_options,
1934 scope, universe, stuff, func);
1937 void hashed_option_space_foreach (struct packet *packet, struct lease *lease,
1938 struct client_state *client_state,
1939 struct option_state *in_options,
1940 struct option_state *cfg_options,
1941 struct binding_scope **scope,
1942 struct universe *u, void *stuff,
1943 void (*func) (struct option_cache *,
1946 struct client_state *,
1947 struct option_state *,
1948 struct option_state *,
1949 struct binding_scope **,
1950 struct universe *, void *))
1954 struct option_cache *oc;
1956 if (cfg_options -> universe_count <= u -> index)
1959 hash = cfg_options -> universes [u -> index];
1962 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1964 /* XXX save _all_ options! XXX */
1965 for (p = hash [i]; p; p = p -> cdr) {
1966 oc = (struct option_cache *)p -> car;
1967 (*func) (oc, packet, lease, client_state,
1968 in_options, cfg_options, scope, u, stuff);
1973 void save_linked_option (universe, options, oc)
1974 struct universe *universe;
1975 struct option_state *options;
1976 struct option_cache *oc;
1980 struct option_chain_head *head;
1982 if (universe -> index >= options -> universe_count)
1984 head = ((struct option_chain_head *)
1985 options -> universes [universe -> index]);
1987 if (!option_chain_head_allocate (((struct option_chain_head **)
1988 &options -> universes
1989 [universe -> index]), MDL))
1991 head = ((struct option_chain_head *)
1992 options -> universes [universe -> index]);
1995 /* Find the tail of the list. */
1996 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
1998 ((struct option_cache *)((*tail) -> car)) -> option) {
1999 option_cache_dereference ((struct option_cache **)
2000 (&(*tail) -> car), MDL);
2001 option_cache_reference ((struct option_cache **)
2002 (&(*tail) -> car), oc, MDL);
2007 *tail = cons (0, 0);
2009 option_cache_reference ((struct option_cache **)
2010 (&(*tail) -> car), oc, MDL);
2014 int linked_option_space_encapsulate (result, packet, lease, client_state,
2015 in_options, cfg_options, scope, universe)
2016 struct data_string *result;
2017 struct packet *packet;
2018 struct lease *lease;
2019 struct client_state *client_state;
2020 struct option_state *in_options;
2021 struct option_state *cfg_options;
2022 struct binding_scope **scope;
2023 struct universe *universe;
2027 struct option_chain_head *head;
2029 if (universe -> index >= cfg_options -> universe_count)
2031 head = ((struct option_chain_head *)
2032 cfg_options -> universes [universe -> index]);
2037 for (oc = head -> first; oc; oc = oc -> cdr) {
2038 if (store_option (result, universe, packet,
2039 lease, client_state, in_options, cfg_options,
2040 scope, (struct option_cache *)(oc -> car)))
2047 void delete_linked_option (universe, options, code)
2048 struct universe *universe;
2049 struct option_state *options;
2052 pair *tail, tmp = (pair)0;
2053 struct option_chain_head *head;
2055 if (universe -> index >= options -> universe_count)
2057 head = ((struct option_chain_head *)
2058 options -> universes [universe -> index]);
2062 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
2064 ((struct option_cache *)(*tail) -> car) -> option -> code)
2066 tmp = (*tail) -> cdr;
2067 option_cache_dereference ((struct option_cache **)
2068 (&(*tail) -> car), MDL);
2076 struct option_cache *lookup_linked_option (universe, options, code)
2077 struct universe *universe;
2078 struct option_state *options;
2082 struct option_chain_head *head;
2084 if (universe -> index >= options -> universe_count)
2086 head = ((struct option_chain_head *)
2087 options -> universes [universe -> index]);
2091 for (oc = head -> first; oc; oc = oc -> cdr) {
2093 ((struct option_cache *)(oc -> car)) -> option -> code) {
2094 return (struct option_cache *)(oc -> car);
2098 return (struct option_cache *)0;
2101 int linked_option_state_dereference (universe, state, file, line)
2102 struct universe *universe;
2103 struct option_state *state;
2107 return (option_chain_head_dereference
2108 ((struct option_chain_head **)
2109 (&state -> universes [universe -> index]), MDL));
2112 void linked_option_space_foreach (struct packet *packet, struct lease *lease,
2113 struct client_state *client_state,
2114 struct option_state *in_options,
2115 struct option_state *cfg_options,
2116 struct binding_scope **scope,
2117 struct universe *u, void *stuff,
2118 void (*func) (struct option_cache *,
2121 struct client_state *,
2122 struct option_state *,
2123 struct option_state *,
2124 struct binding_scope **,
2125 struct universe *, void *))
2128 struct option_chain_head *head;
2130 if (u -> index >= cfg_options -> universe_count)
2132 head = ((struct option_chain_head *)
2133 cfg_options -> universes [u -> index]);
2136 for (car = head -> first; car; car = car -> cdr) {
2137 (*func) ((struct option_cache *)(car -> car),
2138 packet, lease, client_state,
2139 in_options, cfg_options, scope, u, stuff);
2143 void do_packet (interface, packet, len, from_port, from, hfrom)
2144 struct interface_info *interface;
2145 struct dhcp_packet *packet;
2147 unsigned int from_port;
2149 struct hardware *hfrom;
2152 struct option_cache *op;
2153 struct packet *decoded_packet;
2154 #if defined (DEBUG_MEMORY_LEAKAGE)
2155 unsigned long previous_outstanding = dmalloc_outstanding;
2158 #if defined (TRACING)
2159 trace_inpacket_stash (interface, packet, len, from_port, from, hfrom);
2162 decoded_packet = (struct packet *)0;
2163 if (!packet_allocate (&decoded_packet, MDL)) {
2164 log_error ("do_packet: no memory for incoming packet!");
2167 decoded_packet -> raw = packet;
2168 decoded_packet -> packet_length = len;
2169 decoded_packet -> client_port = from_port;
2170 decoded_packet -> client_addr = from;
2171 interface_reference (&decoded_packet -> interface, interface, MDL);
2172 decoded_packet -> haddr = hfrom;
2174 if (packet -> hlen > sizeof packet -> chaddr) {
2175 packet_dereference (&decoded_packet, MDL);
2176 log_info ("Discarding packet with bogus hlen.");
2180 /* If there's an option buffer, try to parse it. */
2181 if (decoded_packet -> packet_length >= DHCP_FIXED_NON_UDP + 4) {
2182 if (!parse_options (decoded_packet)) {
2183 if (decoded_packet -> options)
2184 option_state_dereference
2185 (&decoded_packet -> options, MDL);
2186 packet_dereference (&decoded_packet, MDL);
2190 if (decoded_packet -> options_valid &&
2191 (op = lookup_option (&dhcp_universe,
2192 decoded_packet -> options,
2193 DHO_DHCP_MESSAGE_TYPE))) {
2194 struct data_string dp;
2195 memset (&dp, 0, sizeof dp);
2196 evaluate_option_cache (&dp, decoded_packet,
2198 (struct client_state *)0,
2199 decoded_packet -> options,
2200 (struct option_state *)0,
2201 (struct binding_scope **)0,
2204 decoded_packet -> packet_type = dp.data [0];
2206 decoded_packet -> packet_type = 0;
2207 data_string_forget (&dp, MDL);
2211 if (decoded_packet -> packet_type)
2212 dhcp (decoded_packet);
2214 bootp (decoded_packet);
2216 /* If the caller kept the packet, they'll have upped the refcnt. */
2217 packet_dereference (&decoded_packet, MDL);
2219 #if defined (DEBUG_MEMORY_LEAKAGE)
2220 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2222 dmalloc_outstanding - previous_outstanding,
2223 dmalloc_outstanding, dmalloc_longterm);
2225 #if defined (DEBUG_MEMORY_LEAKAGE)
2226 dmalloc_dump_outstanding ();
2228 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2229 dump_rc_history (0);