3 DHCP options parsing and reassembly. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
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.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
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''.
36 static char copyright
[] =
37 "$Id$ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
40 #define DHCP_OPTION_DATA
42 #include <omapip/omapip_p.h>
44 struct option
*vendor_cfg_option
;
47 static void do_option_set
PROTO ((pair
*,
48 struct option_cache
*,
52 /* Parse all available options out of the specified packet. */
54 int parse_options (packet
)
55 struct packet
*packet
;
58 struct option_cache
*op
= (struct option_cache
*)0;
60 /* Allocate a new option state. */
61 if (!option_state_allocate (&packet
-> options
, MDL
)) {
62 packet
-> options_valid
= 0;
66 /* If we don't see the magic cookie, there's nothing to parse. */
67 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
68 packet
-> options_valid
= 0;
72 /* Go through the options field, up to the end of the packet
74 if (!parse_option_buffer (packet
-> options
,
75 &packet
-> raw
-> options
[4],
76 (packet
-> packet_length
-
77 DHCP_FIXED_NON_UDP
- 4),
81 /* If we parsed a DHCP Option Overload option, parse more
82 options out of the buffer(s) containing them. */
83 if (packet
-> options_valid
&&
84 (op
= lookup_option (&dhcp_universe
, packet
-> options
,
85 DHO_DHCP_OPTION_OVERLOAD
))) {
86 if (op
-> data
.data
[0] & 1) {
87 if (!parse_option_buffer
89 (unsigned char *)packet
-> raw
-> file
,
90 sizeof packet
-> raw
-> file
,
94 if (op
-> data
.data
[0] & 2) {
95 if (!parse_option_buffer
97 (unsigned char *)packet
-> raw
-> sname
,
98 sizeof packet
-> raw
-> sname
,
103 packet
-> options_valid
= 1;
107 /* Parse options out of the specified buffer, storing addresses of option
108 values in packet -> options and setting packet -> options_valid if no
109 errors are encountered. */
111 int parse_option_buffer (options
, buffer
, length
, universe
)
112 struct option_state
*options
;
113 const unsigned char *buffer
;
115 struct universe
*universe
;
118 // const unsigned char *end = buffer + length;
119 unsigned len
, offset
;
121 struct option_cache
*op
= (struct option_cache
*)0;
122 struct buffer
*bp
= (struct buffer
*)0;
124 if (!buffer_allocate (&bp
, length
, MDL
)) {
125 log_error ("no memory for option buffer.");
128 memcpy (bp
-> data
, buffer
, length
);
130 for (offset
= 0; buffer
[offset
] != DHO_END
&& offset
< length
; ) {
131 code
= buffer
[offset
];
132 /* Pad options don't have a length - just skip them. */
133 if (code
== DHO_PAD
) {
138 /* Don't look for length if the buffer isn't that big. */
139 if (offset
+ 2 > length
) {
144 /* All other fields (except end, see above) have a
146 len
= buffer
[offset
+ 1];
148 /* If the length is outrageous, the options are bad. */
149 if (offset
+ len
+ 2 > length
) {
151 log_error ("parse_option_buffer: option %s (%d) %s.",
152 dhcp_options
[code
].name
, len
,
153 "larger than buffer");
154 buffer_dereference (&bp
, MDL
);
158 /* If the option contains an encapsulation, parse it. If
159 the parse fails, or the option isn't an encapsulation (by
160 far the most common case), or the option isn't entirely
161 an encapsulation, keep the raw data as well. */
162 if (universe
-> options
[code
] &&
163 !((universe
-> options
[code
] -> format
[0] == 'e' ||
164 universe
-> options
[code
] -> format
[0] == 'E') &&
165 (parse_encapsulated_suboptions
166 (options
, universe
-> options
[code
],
167 buffer
+ offset
+ 2, len
,
168 universe
, (const char *)0)))) {
169 op
= lookup_option (universe
, options
, code
);
171 struct data_string
new;
172 memset (&new, 0, sizeof new);
173 if (!buffer_allocate (&new.buffer
, op
-> data
.len
+ len
,
175 log_error ("parse_option_buffer: No memory.");
178 memcpy (new.buffer
-> data
, op
-> data
.data
,
180 memcpy (&new.buffer
-> data
[op
-> data
.len
],
181 &bp
-> data
[offset
+ 2], len
);
182 new.len
= op
-> data
.len
+ len
;
183 new.data
= new.buffer
-> data
;
184 data_string_forget (&op
-> data
, MDL
);
185 data_string_copy (&op
-> data
, &new, MDL
);
186 data_string_forget (&new, MDL
);
188 save_option_buffer (universe
, options
, bp
,
189 &bp
-> data
[offset
+ 2], len
,
190 universe
-> options
[code
], 1);
195 buffer_dereference (&bp
, MDL
);
199 /* If an option in an option buffer turns out to be an encapsulation,
200 figure out what to do. If we don't know how to de-encapsulate it,
201 or it's not well-formed, return zero; otherwise, return 1, indicating
202 that we succeeded in de-encapsulating it. */
204 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
208 struct universe
*universe
= (struct universe
*)0;
210 /* Look for the E option in the option format. */
211 s
= strchr (eopt
-> format
, 'E');
213 log_error ("internal encapsulation format error 1.");
216 /* Look for the universe name in the option format. */
217 t
= strchr (++s
, '.');
218 /* If there was no trailing '.', or there's something after the
219 trailing '.', the option is bogus and we can't use it. */
221 log_error ("internal encapsulation format error 2.");
224 if (t
== s
&& uname
) {
225 for (i
= 0; i
< universe_count
; i
++) {
226 if (!strcmp (universes
[i
] -> name
, uname
)) {
227 universe
= universes
[i
];
232 for (i
= 0; i
< universe_count
; i
++) {
233 if (strlen (universes
[i
] -> name
) == t
- s
&&
234 !memcmp (universes
[i
] -> name
,
235 s
, (unsigned)(t
- s
))) {
236 universe
= universes
[i
];
244 /* If an option in an option buffer turns out to be an encapsulation,
245 figure out what to do. If we don't know how to de-encapsulate it,
246 or it's not well-formed, return zero; otherwise, return 1, indicating
247 that we succeeded in de-encapsulating it. */
249 int parse_encapsulated_suboptions (struct option_state
*options
,
251 const unsigned char *buffer
,
252 unsigned len
, struct universe
*eu
,
256 struct universe
*universe
= find_option_universe (eopt
, uname
);
258 /* If we didn't find the universe, we can't do anything with it
259 right now (e.g., we can't decode vendor options until we've
260 decoded the packet and executed the scopes that it matches). */
264 /* If we don't have a decoding function for it, we can't decode
266 if (!universe
-> decode
)
269 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
271 /* If there is stuff before the suboptions, we have to keep it. */
272 if (eopt
-> format
[0] != 'E')
274 /* Otherwise, return the status of the decode function. */
278 int fqdn_universe_decode (struct option_state
*options
,
279 const unsigned char *buffer
,
280 unsigned length
, struct universe
*u
)
283 struct buffer
*bp
= (struct buffer
*)0;
285 /* FQDN options have to be at least four bytes long. */
289 /* Save the contents of the option in a buffer. */
290 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
291 log_error ("no memory for option buffer.");
294 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
296 if (buffer
[0] & 4) /* encoded */
300 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
302 &fqdn_options
[FQDN_ENCODED
], 0)) {
304 buffer_dereference (&bp
, MDL
);
308 if (buffer
[0] & 1) /* server-update */
312 if (buffer
[0] & 2) /* no-client-update */
317 /* XXX Ideally we should store the name in DNS format, so if the
318 XXX label isn't in DNS format, we convert it to DNS format,
319 XXX rather than converting labels specified in DNS format to
320 XXX the plain ASCII representation. But that's hard, so
323 /* Not encoded using DNS format? */
324 if (!bp
-> data
[0]) {
327 /* Some broken clients NUL-terminate this option. */
328 if (buffer
[length
- 1] == 0) {
333 /* Determine the length of the hostname component of the
334 name. If the name contains no '.' character, it
335 represents a non-qualified label. */
336 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
339 /* Note: If the client sends a FQDN, the first '.' will
340 be used as a NUL terminator for the hostname. */
342 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
344 &fqdn_options
[FQDN_HOSTNAME
],
347 /* Note: If the client sends a single label, the
348 FQDN_DOMAINNAME option won't be set. */
349 if (length
> 4 + i
&&
350 !save_option_buffer (&fqdn_universe
, options
, bp
,
351 &bp
-> data
[6 + i
], length
- 4 - i
,
352 &fqdn_options
[FQDN_DOMAINNAME
], 1))
354 /* Also save the whole name. */
356 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
357 &bp
-> data
[5], length
- 3,
358 &fqdn_options
[FQDN_FQDN
], 1))
362 unsigned total_len
= 0;
363 unsigned first_len
= 0;
369 while (s
< &bp
-> data
[0] + length
+ 2) {
372 log_info ("fancy bits in fqdn option");
379 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
380 log_info ("fqdn tag longer than buffer");
384 if (first_len
== 0) {
390 total_len
+= len
+ 1;
393 /* We wind up with a length that's one too many because
394 we shouldn't increment for the last label, but there's
395 no way to tell we're at the last label until we exit
401 first_len
= total_len
;
405 !save_option_buffer (&fqdn_universe
, options
, bp
,
406 &bp
-> data
[6], first_len
,
407 &fqdn_options
[FQDN_HOSTNAME
], 0))
409 if (total_len
> 0 && first_len
!= total_len
) {
410 if (!save_option_buffer
411 (&fqdn_universe
, options
, bp
,
412 &bp
-> data
[6 + first_len
], total_len
- first_len
,
413 &fqdn_options
[FQDN_DOMAINNAME
], 1))
417 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
418 &bp
-> data
[6], total_len
,
419 &fqdn_options
[FQDN_FQDN
], 1))
423 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
425 &fqdn_options
[FQDN_NO_CLIENT_UPDATE
], 0))
427 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
429 &fqdn_options
[FQDN_SERVER_UPDATE
], 0))
432 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
434 &fqdn_options
[FQDN_RCODE1
], 0))
436 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
438 &fqdn_options
[FQDN_RCODE2
], 0))
441 buffer_dereference (&bp
, MDL
);
445 /* cons options into a big buffer, and then split them out into the
446 three seperate buffers if needed. This allows us to cons up a set
447 of vendor options using the same routine. */
449 int cons_options (inpacket
, outpacket
, lease
, client_state
,
450 mms
, in_options
, cfg_options
,
451 scope
, overload
, terminate
, bootpp
, prl
, vuname
)
452 struct packet
*inpacket
;
453 struct dhcp_packet
*outpacket
;
455 struct client_state
*client_state
;
457 struct option_state
*in_options
;
458 struct option_state
*cfg_options
;
459 struct binding_scope
**scope
;
460 int overload
; /* Overload flags that may be set. */
463 struct data_string
*prl
;
466 #define PRIORITY_COUNT 300
467 unsigned priority_list
[PRIORITY_COUNT
];
469 unsigned char buffer
[4096]; /* Really big buffer... */
470 unsigned main_buffer_size
;
471 unsigned mainbufix
, agentix
;
475 unsigned option_size
;
478 struct option_cache
*op
;
479 struct data_string ds
;
484 int ofbuf1
=0, ofbuf2
=0;
486 memset (&ds
, 0, sizeof ds
);
488 /* If there's a Maximum Message Size option in the incoming packet
489 and no alternate maximum message size has been specified, take the
490 one in the packet. */
493 (op
= lookup_option (&dhcp_universe
, inpacket
-> options
,
494 DHO_DHCP_MAX_MESSAGE_SIZE
))) {
495 evaluate_option_cache (&ds
, inpacket
,
496 lease
, client_state
, in_options
,
497 cfg_options
, scope
, op
, MDL
);
498 if (ds
.len
>= sizeof (u_int16_t
)) {
499 i
= getUShort (ds
.data
);
501 if(!mms
|| (i
< mms
))
504 data_string_forget (&ds
, MDL
);
507 /* If the client has provided a maximum DHCP message size,
508 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
509 use up to the minimum IP MTU size (576 bytes). */
510 /* XXX if a BOOTP client specifies a max message size, we will
514 main_buffer_size
= mms
- DHCP_FIXED_LEN
;
516 /* Enforce a minimum packet size... */
517 if (main_buffer_size
< (576 - DHCP_FIXED_LEN
))
518 main_buffer_size
= 576 - DHCP_FIXED_LEN
;
522 inpacket
-> packet_length
- DHCP_FIXED_LEN
;
523 if (main_buffer_size
< 64)
524 main_buffer_size
= 64;
526 main_buffer_size
= 64;
528 main_buffer_size
= 576 - DHCP_FIXED_LEN
;
530 /* Set a hard limit at the size of the output buffer. */
531 if (main_buffer_size
> sizeof buffer
)
532 main_buffer_size
= sizeof buffer
;
534 /* Preload the option priority list with mandatory options. */
536 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
537 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
538 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
539 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
540 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
541 priority_list
[priority_len
++] = DHO_FQDN
;
543 if (prl
&& prl
-> len
> 0) {
544 if ((op
= lookup_option (&dhcp_universe
, cfg_options
,
545 DHO_SUBNET_SELECTION
))) {
546 if (priority_len
< PRIORITY_COUNT
)
547 priority_list
[priority_len
++] =
548 DHO_SUBNET_SELECTION
;
551 data_string_truncate (prl
, (PRIORITY_COUNT
- priority_len
));
553 for (i
= 0; i
< prl
-> len
; i
++) {
554 /* Prevent client from changing order of delivery
555 of relay agent information option. */
556 if (prl
-> data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
557 priority_list
[priority_len
++] =
561 /* First, hardcode some more options that ought to be
563 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
564 priority_list
[priority_len
++] = DHO_ROUTERS
;
565 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
566 priority_list
[priority_len
++] = DHO_HOST_NAME
;
568 /* Append a list of the standard DHCP options from the
569 standard DHCP option space. Actually, if a site
570 option space hasn't been specified, we wind up
571 treating the dhcp option space as the site option
572 space, and the first for loop is skipped, because
573 it's slightly more general to do it this way,
574 taking the 1Q99 DHCP futures work into account. */
575 if (cfg_options
-> site_code_min
) {
576 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
577 hash
= cfg_options
-> universes
[dhcp_universe
.index
];
579 for (pp
= hash
[i
]; pp
; pp
= pp
-> cdr
) {
580 op
= (struct option_cache
*)(pp
-> car
);
581 if (op
-> option
-> code
<
582 cfg_options
-> site_code_min
&&
583 priority_len
< PRIORITY_COUNT
&&
584 (op
-> option
-> code
!=
585 DHO_DHCP_AGENT_OPTIONS
))
586 priority_list
[priority_len
++] =
587 op
-> option
-> code
;
593 /* Now cycle through the site option space, or if there
594 is no site option space, we'll be cycling through the
595 dhcp option space. */
596 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
597 hash
= (cfg_options
-> universes
598 [cfg_options
-> site_universe
]);
600 for (pp
= hash
[i
]; pp
; pp
= pp
-> cdr
) {
601 op
= (struct option_cache
*)(pp
-> car
);
602 if (op
-> option
-> code
>=
603 cfg_options
-> site_code_min
&&
604 priority_len
< PRIORITY_COUNT
&&
605 (op
-> option
-> code
!=
606 DHO_DHCP_AGENT_OPTIONS
))
607 priority_list
[priority_len
++] =
608 op
-> option
-> code
;
612 /* Now go through all the universes for which options
613 were set and see if there are encapsulations for
614 them; if there are, put the encapsulation options
615 on the priority list as well. */
616 for (i
= 0; i
< cfg_options
-> universe_count
; i
++) {
617 if (cfg_options
-> universes
[i
] &&
618 universes
[i
] -> enc_opt
&&
619 priority_len
< PRIORITY_COUNT
&&
620 universes
[i
] -> enc_opt
-> universe
== &dhcp_universe
)
622 if (universes
[i
] -> enc_opt
-> code
!=
623 DHO_DHCP_AGENT_OPTIONS
)
624 priority_list
[priority_len
++] =
625 universes
[i
] -> enc_opt
-> code
;
629 /* The vendor option space can't stand on its own, so always
630 add it to the list. */
631 if (priority_len
< PRIORITY_COUNT
)
632 priority_list
[priority_len
++] =
633 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
636 /* Figure out the overload buffer offset(s). */
638 ofbuf1
= main_buffer_size
- 4;
640 ofbuf2
= main_buffer_size
- 4 + DHCP_FILE_LEN
;
643 /* Copy the options into the big buffer... */
644 option_size
= store_options (&ocount
, buffer
,
645 (main_buffer_size
- 4 +
646 ((overload
& 1) ? DHCP_FILE_LEN
: 0) +
647 ((overload
& 2) ? DHCP_SNAME_LEN
: 0)),
648 inpacket
, lease
, client_state
,
649 in_options
, cfg_options
, scope
,
650 priority_list
, priority_len
,
651 ofbuf1
, ofbuf2
, terminate
, vuname
);
652 /* If store_options failed. */
653 if (option_size
== 0)
656 if (ocount
== 1 && (overload
& 1))
658 else if (ocount
== 1 && (overload
& 2))
660 else if (ocount
== 3)
666 /* Put the cookie up front... */
667 memcpy (outpacket
-> options
, DHCP_OPTIONS_COOKIE
, 4);
670 /* If we're going to have to overload, store the overload
671 option at the beginning. If we can, though, just store the
672 whole thing in the packet's option buffer and leave it at
674 memcpy (&outpacket
-> options
[mainbufix
],
675 buffer
, option_size
);
676 mainbufix
+= option_size
;
678 outpacket
-> options
[mainbufix
++] = DHO_DHCP_OPTION_OVERLOAD
;
679 outpacket
-> options
[mainbufix
++] = 1;
680 outpacket
-> options
[mainbufix
++] = overload
;
683 memcpy (outpacket
-> file
,
684 &buffer
[ofbuf1
], DHCP_FILE_LEN
);
688 memcpy (outpacket
-> sname
, &buffer
[ofbuf2
],
691 memcpy (outpacket
-> sname
, &buffer
[ofbuf1
],
697 if (mainbufix
< main_buffer_size
)
699 length
= DHCP_FIXED_NON_UDP
+ mainbufix
;
701 /* Now hack in the agent options if there are any. */
702 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
705 store_options (0, &outpacket
-> options
[agentix
],
706 1500 - DHCP_FIXED_LEN
- agentix
,
707 inpacket
, lease
, client_state
,
708 in_options
, cfg_options
, scope
,
709 priority_list
, priority_len
,
712 /* Tack a DHO_END option onto the packet if we need to. */
713 if (agentix
< 1500 - DHCP_FIXED_LEN
&& need_endopt
)
714 outpacket
-> options
[agentix
++] = DHO_END
;
716 /* Figure out the length. */
717 length
= DHCP_FIXED_NON_UDP
+ agentix
;
721 /* Store all the requested options into the requested buffer. */
723 int store_options (ocount
, buffer
, buflen
, packet
, lease
, client_state
,
724 in_options
, cfg_options
, scope
, priority_list
, priority_len
,
725 first_cutoff
, second_cutoff
, terminate
, vuname
)
727 unsigned char *buffer
;
729 struct packet
*packet
;
731 struct client_state
*client_state
;
732 struct option_state
*in_options
;
733 struct option_state
*cfg_options
;
734 struct binding_scope
**scope
;
735 unsigned *priority_list
;
737 unsigned first_cutoff
, second_cutoff
;
741 int bufix
= 0, six
= 0, tix
= 0;
746 struct data_string od
;
747 struct option_cache
*oc
;
751 if (first_cutoff
>= buflen
)
752 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
754 bufend
= first_cutoff
;
759 if (second_cutoff
>= buflen
)
760 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
762 sbufend
= second_cutoff
;
766 memset (&od
, 0, sizeof od
);
768 /* Eliminate duplicate options in the parameter request list.
769 There's got to be some clever knuthian way to do this:
770 Eliminate all but the first occurance of a value in an array
771 of values without otherwise disturbing the order of the array. */
772 for (i
= 0; i
< priority_len
- 1; i
++) {
774 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
776 priority_list
[ix
- tto
] =
778 if (priority_list
[i
] == priority_list
[ix
]) {
785 /* Copy out the options in the order that they appear in the
787 for (i
= 0; i
< priority_len
; i
++) {
788 /* Number of bytes left to store (some may already
789 have been stored by a previous pass). */
791 int optstart
, soptstart
, toptstart
;
793 int have_encapsulation
= 0;
794 struct data_string encapsulation
;
797 memset (&encapsulation
, 0, sizeof encapsulation
);
799 /* Code for next option to try to store. */
800 code
= priority_list
[i
];
802 /* Look up the option in the site option space if the code
803 is above the cutoff, otherwise in the DHCP option space. */
804 if (code
>= cfg_options
-> site_code_min
)
805 u
= universes
[cfg_options
-> site_universe
];
809 oc
= lookup_option (u
, cfg_options
, code
);
811 /* It's an encapsulation, try to find the universe
812 to be encapsulated first, except that if it's a straight
813 encapsulation and the user has provided a value for the
814 encapsulation option, use the user-provided value. */
815 if (u
-> options
[code
] &&
816 ((u
-> options
[code
] -> format
[0] == 'E' && !oc
) ||
817 u
-> options
[code
] -> format
[0] == 'e')) {
820 struct option_cache
*tmp
;
821 struct data_string name
;
823 s
= strchr (u
-> options
[code
] -> format
, 'E');
825 t
= strchr (++s
, '.');
827 memset (&name
, 0, sizeof name
);
829 /* A zero-length universe name means the vendor
830 option space, if one is defined. */
832 if (vendor_cfg_option
) {
833 tmp
= lookup_option (vendor_cfg_option
-> universe
,
835 vendor_cfg_option
-> code
);
837 evaluate_option_cache (&name
, packet
, lease
,
843 name
.data
= (unsigned char *)s
;
844 name
.len
= strlen (s
);
847 name
.data
= (unsigned char *)s
;
851 /* If we found a universe, and there are options configured
852 for that universe, try to encapsulate it. */
855 (option_space_encapsulate
856 (&encapsulation
, packet
, lease
, client_state
,
857 in_options
, cfg_options
, scope
, &name
));
858 data_string_forget (&name
, MDL
);
863 /* In order to avoid memory leaks, we have to get to here
864 with any option cache that we allocated in tmp not being
865 referenced by tmp, and whatever option cache is referenced
866 by oc being an actual reference. lookup_option doesn't
867 generate a reference (this needs to be fixed), so the
868 preceding goop ensures that if we *didn't* generate a new
869 option cache, oc still winds up holding an actual reference. */
871 /* If no data is available for this option, skip it. */
872 if (!oc
&& !have_encapsulation
) {
876 /* Find the value of the option... */
878 evaluate_option_cache (&od
, packet
,
879 lease
, client_state
, in_options
,
880 cfg_options
, scope
, oc
, MDL
);
882 data_string_forget (&encapsulation
, MDL
);
883 data_string_forget (&od
, MDL
);
884 have_encapsulation
= 0;
889 /* We should now have a constant length for the option. */
891 if (have_encapsulation
) {
892 length
+= encapsulation
.len
;
894 data_string_copy (&od
, &encapsulation
, MDL
);
895 data_string_forget (&encapsulation
, MDL
);
897 struct buffer
*bp
= (struct buffer
*)0;
898 if (!buffer_allocate (&bp
, length
, MDL
)) {
899 option_cache_dereference (&oc
, MDL
);
900 data_string_forget (&od
, MDL
);
901 data_string_forget (&encapsulation
, MDL
);
904 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
905 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
907 data_string_forget (&od
, MDL
);
908 data_string_forget (&encapsulation
, MDL
);
909 od
.data
= &bp
-> data
[0];
910 buffer_reference (&od
.buffer
, bp
, MDL
);
911 buffer_dereference (&bp
, MDL
);
917 /* Do we add a NUL? */
918 if (terminate
&& dhcp_options
[code
].format
[0] == 't') {
925 /* Try to store the option. */
927 /* If the option's length is more than 255, we must store it
928 in multiple hunks. Store 255-byte hunks first. However,
929 in any case, if the option data will cross a buffer
930 boundary, split it across that boundary. */
943 unsigned incr
= length
;
948 /* Try to fit it in the options buffer. */
950 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
951 (bufix
+ 2 + length
< bufend
)) ||
952 (bufix
+ 5 + length
< bufend
))) {
955 /* Try to fit it in the second buffer. */
956 } else if (!splitup
&& first_cutoff
&&
957 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
958 base
= &buffer
[first_cutoff
];
960 /* Try to fit it in the third buffer. */
961 } else if (!splitup
&& second_cutoff
&&
962 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
963 base
= &buffer
[second_cutoff
];
965 /* Split the option up into the remaining space. */
969 /* Use any remaining options space. */
970 if (bufix
+ 6 < bufend
) {
971 incr
= bufend
- bufix
- 5;
974 /* Use any remaining first_cutoff space. */
975 } else if (first_cutoff
&&
976 (first_cutoff
+ six
+ 4 < sbufend
)) {
977 incr
= sbufend
- (first_cutoff
+ six
) - 3;
978 base
= &buffer
[first_cutoff
];
980 /* Use any remaining second_cutoff space. */
981 } else if (second_cutoff
&&
982 (second_cutoff
+ tix
+ 4 < buflen
)) {
983 incr
= buflen
- (second_cutoff
+ tix
) - 3;
984 base
= &buffer
[second_cutoff
];
986 /* Give up, roll back this option. */
1000 /* Everything looks good - copy it in! */
1002 base
[*pix
+ 1] = (unsigned char)incr
;
1003 if (tto
&& incr
== length
) {
1005 memcpy (base
+ *pix
+ 2,
1006 od
.data
+ ix
, (unsigned)(incr
- 1));
1007 base
[*pix
+ 2 + incr
- 1] = 0;
1009 memcpy (base
+ *pix
+ 2,
1010 od
.data
+ ix
, (unsigned)incr
);
1016 data_string_forget (&od
, MDL
);
1019 /* If we can overload, and we have, then PAD and END those spaces. */
1020 if (first_cutoff
&& six
) {
1021 if ((first_cutoff
+ six
+ 1) < sbufend
)
1022 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1023 sbufend
- (first_cutoff
+ six
+ 1));
1024 else if (first_cutoff
+ six
>= sbufend
)
1025 log_fatal("Second buffer overflow in overloaded options.");
1027 buffer
[first_cutoff
+ six
] = DHO_END
;
1028 *ocount
|= 1; /* So that caller knows there's data there. */
1031 if (second_cutoff
&& tix
) {
1032 if (second_cutoff
+ tix
+ 1 < buflen
) {
1033 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1034 buflen
- (second_cutoff
+ tix
+ 1));
1035 } else if (second_cutoff
+ tix
>= buflen
)
1036 log_fatal("Third buffer overflow in overloaded options.");
1038 buffer
[second_cutoff
+ tix
] = DHO_END
;
1039 *ocount
|= 2; /* So that caller knows there's data there. */
1042 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1043 log_fatal("Not enough space for option overload option.");
1048 /* Format the specified option so that a human can easily read it. */
1050 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1051 struct option
*option
;
1052 const unsigned char *data
;
1057 static char optbuf
[32768]; /* XXX */
1064 struct enumeration
*enumbuf
[32];
1067 const unsigned char *dp
= data
;
1077 memset (enumbuf
, 0, sizeof enumbuf
);
1079 /* Figure out the size of the data. */
1080 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1082 log_error ("%s: Extra codes in format string: %s",
1084 &(option
-> format
[i
]));
1088 fmtbuf
[l
] = option
-> format
[i
];
1089 switch (option
-> format
[i
]) {
1101 /* Skip the universe name. */
1102 while (option
-> format
[i
] &&
1103 option
-> format
[i
] != '.')
1106 for (k
= 0; k
< len
; k
++) {
1107 if (!isascii (data
[k
]) ||
1108 !isprint (data
[k
]))
1111 /* If we found no bogus characters, or the bogus
1112 character we found is a trailing NUL, it's
1113 okay to print this option as text. */
1114 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1133 while (option
-> format
[i
] &&
1134 option
-> format
[i
] != '.')
1137 find_enumeration (&option
-> format
[k
] + 1,
1166 log_error ("%s: garbage in format string: %s",
1168 &(option
-> format
[i
]));
1173 /* Check for too few bytes... */
1174 if (hunksize
- opthunk
> len
) {
1175 log_error ("%s: expecting at least %d bytes; got %d",
1180 /* Check for too many bytes... */
1181 if (numhunk
== -1 && hunksize
< len
)
1182 log_error ("%s: %d extra bytes",
1186 /* If this is an array, compute its size. */
1188 numhunk
= len
/ hunksize
;
1189 /* See if we got an exact number of hunks. */
1190 if (numhunk
> 0 && numhunk
* hunksize
< len
)
1191 log_error ("%s: %d extra bytes at end of array\n",
1193 len
- numhunk
* hunksize
);
1195 /* A one-hunk array prints the same as a single hunk. */
1199 /* Cycle through the array (or hunk) printing the data. */
1200 for (i
= 0; i
< numhunk
; i
++) {
1201 for (j
= 0; j
< numelem
; j
++) {
1202 switch (fmtbuf
[j
]) {
1206 for (; dp
< data
+ len
; dp
++) {
1207 if (!isascii (*dp
) ||
1209 /* Skip trailing NUL. */
1210 if (dp
+ 1 != data
+ len
||
1212 sprintf (op
, "\\%03o",
1216 } else if (*dp
== '"' ||
1230 /* pretty-printing an array of enums is
1231 going to get ugly. */
1236 if (!enumbuf
[j
] -> values
[i
].name
)
1238 if (enumbuf
[j
] -> values
[i
].value
==
1242 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
1246 foo
.s_addr
= htonl (getULong (dp
));
1247 strcpy (op
, inet_ntoa (foo
));
1251 sprintf (op
, "%ld", (long)getLong (dp
));
1255 tval
= getULong (dp
);
1257 sprintf (op
, "%s", "infinite");
1259 sprintf (op
, "%ld", tval
);
1263 (unsigned long)getULong (dp
));
1267 sprintf (op
, "%d", (int)getShort (dp
));
1271 sprintf (op
, "%d", (unsigned)getUShort (dp
));
1275 sprintf (op
, "%d", *(const char *)dp
++);
1279 sprintf (op
, "%d", *dp
++);
1282 sprintf (op
, "%x", *dp
++);
1285 strcpy (op
, *dp
++ ? "true" : "false");
1288 log_error ("Unexpected format code %c",
1292 if (dp
== data
+ len
)
1294 if (j
+ 1 < numelem
&& comma
!= ':')
1297 if (i
+ 1 < numhunk
) {
1300 if (dp
== data
+ len
)
1306 int get_option (result
, universe
, packet
, lease
, client_state
,
1307 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
1308 struct data_string
*result
;
1309 struct universe
*universe
;
1310 struct packet
*packet
;
1311 struct lease
*lease
;
1312 struct client_state
*client_state
;
1313 struct option_state
*in_options
;
1314 struct option_state
*cfg_options
;
1315 struct option_state
*options
;
1316 struct binding_scope
**scope
;
1321 struct option_cache
*oc
;
1323 if (!universe
-> lookup_func
)
1325 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
1328 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
1329 in_options
, cfg_options
, scope
, oc
,
1335 void set_option (universe
, options
, option
, op
)
1336 struct universe
*universe
;
1337 struct option_state
*options
;
1338 struct option_cache
*option
;
1339 enum statement_op op
;
1341 struct option_cache
*oc
, *noc
;
1346 case eval_statement
:
1347 case break_statement
:
1349 log_error ("bogus statement type in do_option_set.");
1352 case default_option_statement
:
1353 oc
= lookup_option (universe
, options
,
1354 option
-> option
-> code
);
1357 save_option (universe
, options
, option
);
1360 case supersede_option_statement
:
1361 case send_option_statement
:
1362 /* Install the option, replacing any existing version. */
1363 save_option (universe
, options
, option
);
1366 case append_option_statement
:
1367 case prepend_option_statement
:
1368 oc
= lookup_option (universe
, options
,
1369 option
-> option
-> code
);
1371 save_option (universe
, options
, option
);
1374 /* If it's not an expression, make it into one. */
1375 if (!oc
-> expression
&& oc
-> data
.len
) {
1376 if (!expression_allocate (&oc
-> expression
, MDL
)) {
1377 log_error ("Can't allocate const expression.");
1380 oc
-> expression
-> op
= expr_const_data
;
1382 (&oc
-> expression
-> data
.const_data
,
1384 data_string_forget (&oc
-> data
, MDL
);
1386 noc
= (struct option_cache
*)0;
1387 if (!option_cache_allocate (&noc
, MDL
))
1389 if (op
== append_option_statement
) {
1390 if (!make_concat (&noc
-> expression
,
1392 option
-> expression
)) {
1393 option_cache_dereference (&noc
, MDL
);
1397 if (!make_concat (&noc
-> expression
,
1398 option
-> expression
,
1399 oc
-> expression
)) {
1400 option_cache_dereference (&noc
, MDL
);
1404 noc
-> option
= oc
-> option
;
1405 save_option (universe
, options
, noc
);
1406 option_cache_dereference (&noc
, MDL
);
1411 struct option_cache
*lookup_option (universe
, options
, code
)
1412 struct universe
*universe
;
1413 struct option_state
*options
;
1417 return (struct option_cache
*)0;
1418 if (universe
-> lookup_func
)
1419 return (*universe
-> lookup_func
) (universe
, options
, code
);
1421 log_error ("can't look up options in %s space.",
1423 return (struct option_cache
*)0;
1426 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
1427 struct universe
*universe
;
1428 struct option_state
*options
;
1435 /* Make sure there's a hash table. */
1436 if (universe
-> index
>= options
-> universe_count
||
1437 !(options
-> universes
[universe
-> index
]))
1438 return (struct option_cache
*)0;
1440 hash
= options
-> universes
[universe
-> index
];
1442 hashix
= compute_option_hash (code
);
1443 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1444 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
1446 return (struct option_cache
*)(bptr
-> car
);
1448 return (struct option_cache
*)0;
1451 int save_option_buffer (struct universe
*universe
,
1452 struct option_state
*options
,
1454 unsigned char *buffer
, unsigned length
,
1455 struct option
*option
, int tp
)
1457 struct buffer
*lbp
= (struct buffer
*)0;
1458 struct option_cache
*op
= (struct option_cache
*)0;
1460 if (!option_cache_allocate (&op
, MDL
)) {
1461 log_error ("No memory for option %s.%s.",
1467 /* If we weren't passed a buffer in which the data are saved and
1468 refcounted, allocate one now. */
1470 if (!buffer_allocate (&lbp
, length
, MDL
)) {
1471 log_error ("no memory for option buffer.");
1473 option_cache_dereference (&op
, MDL
);
1476 memcpy (lbp
-> data
, buffer
, length
+ tp
);
1478 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
1481 /* Reference buffer copy to option cache. */
1482 op
-> data
.buffer
= (struct buffer
*)0;
1483 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
1485 /* Point option cache into buffer. */
1486 op
-> data
.data
= buffer
;
1487 op
-> data
.len
= length
;
1490 /* NUL terminate (we can get away with this because we (or
1491 the caller!) allocated one more than the buffer size, and
1492 because the byte following the end of an option is always
1493 the code of the next option, which the caller is getting
1494 out of the *original* buffer. */
1495 buffer
[length
] = 0;
1496 op
-> data
.terminated
= 1;
1498 op
-> data
.terminated
= 0;
1500 op
-> option
= option
;
1502 /* Now store the option. */
1503 save_option (universe
, options
, op
);
1505 /* And let go of our reference. */
1506 option_cache_dereference (&op
, MDL
);
1511 void save_option (struct universe
*universe
,
1512 struct option_state
*options
, struct option_cache
*oc
)
1514 if (universe
-> save_func
)
1515 (*universe
-> save_func
) (universe
, options
, oc
);
1517 log_error ("can't store options in %s space.",
1521 void save_hashed_option (universe
, options
, oc
)
1522 struct universe
*universe
;
1523 struct option_state
*options
;
1524 struct option_cache
*oc
;
1528 pair
*hash
= options
-> universes
[universe
-> index
];
1530 if (oc
-> refcnt
== 0)
1533 /* Compute the hash. */
1534 hashix
= compute_option_hash (oc
-> option
-> code
);
1536 /* If there's no hash table, make one. */
1538 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
1540 log_error ("no memory to store %s.%s",
1541 universe
-> name
, oc
-> option
-> name
);
1544 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
1545 options
-> universes
[universe
-> index
] = (VOIDPTR
)hash
;
1547 /* Try to find an existing option matching the new one. */
1548 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1549 if (((struct option_cache
*)
1550 (bptr
-> car
)) -> option
-> code
==
1551 oc
-> option
-> code
)
1555 /* If we find one, dereference it and put the new one
1558 option_cache_dereference
1559 ((struct option_cache
**)&bptr
-> car
, MDL
);
1560 option_cache_reference
1561 ((struct option_cache
**)&bptr
-> car
,
1567 /* Otherwise, just put the new one at the head of the list. */
1568 bptr
= new_pair (MDL
);
1570 log_error ("No memory for option_cache reference.");
1573 bptr
-> cdr
= hash
[hashix
];
1575 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
1576 hash
[hashix
] = bptr
;
1579 void delete_option (universe
, options
, code
)
1580 struct universe
*universe
;
1581 struct option_state
*options
;
1584 if (universe
-> delete_func
)
1585 (*universe
-> delete_func
) (universe
, options
, code
);
1587 log_error ("can't delete options from %s space.",
1591 void delete_hashed_option (universe
, options
, code
)
1592 struct universe
*universe
;
1593 struct option_state
*options
;
1597 pair bptr
, prev
= (pair
)0;
1598 pair
*hash
= options
-> universes
[universe
-> index
];
1600 /* There may not be any options in this space. */
1604 /* Try to find an existing option matching the new one. */
1605 hashix
= compute_option_hash (code
);
1606 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1607 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
1612 /* If we found one, wipe it out... */
1615 prev
-> cdr
= bptr
-> cdr
;
1617 hash
[hashix
] = bptr
-> cdr
;
1618 option_cache_dereference
1619 ((struct option_cache
**)(&bptr
-> car
), MDL
);
1620 free_pair (bptr
, MDL
);
1624 extern struct option_cache
*free_option_caches
; /* XXX */
1626 int option_cache_dereference (ptr
, file
, line
)
1627 struct option_cache
**ptr
;
1631 if (!ptr
|| !*ptr
) {
1632 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1634 #if defined (POINTER_DEBUG)
1642 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
1643 if (!(*ptr
) -> refcnt
) {
1644 if ((*ptr
) -> data
.buffer
)
1645 data_string_forget (&(*ptr
) -> data
, file
, line
);
1646 if ((*ptr
) -> expression
)
1647 expression_dereference (&(*ptr
) -> expression
,
1650 option_cache_dereference (&((*ptr
) -> next
),
1652 /* Put it back on the free list... */
1653 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
1654 free_option_caches
= *ptr
;
1655 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
1657 if ((*ptr
) -> refcnt
< 0) {
1658 log_error ("%s(%d): negative refcnt!", file
, line
);
1659 #if defined (DEBUG_RC_HISTORY)
1660 dump_rc_history (*ptr
);
1662 #if defined (POINTER_DEBUG)
1665 *ptr
= (struct option_cache
*)0;
1669 *ptr
= (struct option_cache
*)0;
1674 int hashed_option_state_dereference (universe
, state
, file
, line
)
1675 struct universe
*universe
;
1676 struct option_state
*state
;
1684 /* Get the pointer to the array of hash table bucket heads. */
1685 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
1689 /* For each non-null head, loop through all the buckets dereferencing
1690 the attached option cache structures and freeing the buckets. */
1691 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
1692 for (cp
= heads
[i
]; cp
; cp
= next
) {
1694 option_cache_dereference
1695 ((struct option_cache
**)&cp
-> car
,
1697 free_pair (cp
, file
, line
);
1701 dfree (heads
, file
, line
);
1702 state
-> universes
[universe
-> index
] = (void *)0;
1706 int store_option (result
, universe
, packet
, lease
, client_state
,
1707 in_options
, cfg_options
, scope
, oc
)
1708 struct data_string
*result
;
1709 struct universe
*universe
;
1710 struct packet
*packet
;
1711 struct lease
*lease
;
1712 struct client_state
*client_state
;
1713 struct option_state
*in_options
;
1714 struct option_state
*cfg_options
;
1715 struct binding_scope
**scope
;
1716 struct option_cache
*oc
;
1718 struct data_string d1
, d2
;
1720 memset (&d1
, 0, sizeof d1
);
1721 memset (&d2
, 0, sizeof d2
);
1723 if (evaluate_option_cache (&d2
, packet
, lease
, client_state
,
1724 in_options
, cfg_options
, scope
, oc
, MDL
)) {
1725 if (!buffer_allocate (&d1
.buffer
,
1727 universe
-> length_size
+
1728 universe
-> tag_size
+ d2
.len
), MDL
)) {
1729 data_string_forget (result
, MDL
);
1730 data_string_forget (&d2
, MDL
);
1733 d1
.data
= &d1
.buffer
-> data
[0];
1735 memcpy (d1
.buffer
-> data
,
1736 result
-> data
, result
-> len
);
1737 d1
.len
= result
-> len
;
1738 (*universe
-> store_tag
) (&d1
.buffer
-> data
[d1
.len
],
1739 oc
-> option
-> code
);
1740 d1
.len
+= universe
-> tag_size
;
1741 (*universe
-> store_length
) (&d1
.buffer
-> data
[d1
.len
],
1743 d1
.len
+= universe
-> length_size
;
1744 memcpy (&d1
.buffer
-> data
[d1
.len
], d2
.data
, d2
.len
);
1746 data_string_forget (&d2
, MDL
);
1747 data_string_forget (result
, MDL
);
1748 data_string_copy (result
, &d1
, MDL
);
1749 data_string_forget (&d1
, MDL
);
1755 int option_space_encapsulate (result
, packet
, lease
, client_state
,
1756 in_options
, cfg_options
, scope
, name
)
1757 struct data_string
*result
;
1758 struct packet
*packet
;
1759 struct lease
*lease
;
1760 struct client_state
*client_state
;
1761 struct option_state
*in_options
;
1762 struct option_state
*cfg_options
;
1763 struct binding_scope
**scope
;
1764 struct data_string
*name
;
1768 u
= (struct universe
*)0;
1769 universe_hash_lookup (&u
, universe_hash
,
1770 (const char *)name
-> data
, name
-> len
, MDL
);
1774 if (u
-> encapsulate
)
1775 return (*u
-> encapsulate
) (result
, packet
, lease
,
1777 in_options
, cfg_options
, scope
, u
);
1778 log_error ("encapsulation requested for %s with no support.",
1783 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
1784 in_options
, cfg_options
, scope
, universe
)
1785 struct data_string
*result
;
1786 struct packet
*packet
;
1787 struct lease
*lease
;
1788 struct client_state
*client_state
;
1789 struct option_state
*in_options
;
1790 struct option_state
*cfg_options
;
1791 struct binding_scope
**scope
;
1792 struct universe
*universe
;
1798 if (universe
-> index
>= cfg_options
-> universe_count
)
1801 hash
= cfg_options
-> universes
[universe
-> index
];
1806 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
1807 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
1808 if (store_option (result
, universe
, packet
,
1809 lease
, client_state
, in_options
,
1811 (struct option_cache
*)p
-> car
))
1819 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
1820 in_options
, cfg_options
, scope
, universe
)
1821 struct data_string
*result
;
1822 struct packet
*packet
;
1823 struct lease
*lease
;
1824 struct client_state
*client_state
;
1825 struct option_state
*in_options
;
1826 struct option_state
*cfg_options
;
1827 struct binding_scope
**scope
;
1828 struct universe
*universe
;
1833 static struct option_cache
*no_nwip
;
1834 struct data_string ds
;
1835 struct option_chain_head
*head
;
1837 if (universe
-> index
>= cfg_options
-> universe_count
)
1839 head
= ((struct option_chain_head
*)
1840 cfg_options
-> universes
[fqdn_universe
.index
]);
1845 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
1846 // struct option_cache *oc = (struct option_cache *)(ocp -> car);
1847 if (store_option (result
, universe
, packet
,
1848 lease
, client_state
, in_options
,
1850 (struct option_cache
*)ocp
-> car
))
1854 /* If there's no data, the nwip suboption is supposed to contain
1855 a suboption saying there's no data. */
1858 static unsigned char nni
[] = { 1, 0 };
1859 memset (&ds
, 0, sizeof ds
);
1862 if (option_cache_allocate (&no_nwip
, MDL
))
1863 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
1864 no_nwip
-> option
= nwip_universe
.options
[1];
1867 if (store_option (result
, universe
, packet
, lease
,
1868 client_state
, in_options
,
1869 cfg_options
, scope
, no_nwip
))
1873 memset (&ds
, 0, sizeof ds
);
1875 /* If we have nwip options, the first one has to be the
1876 nwip-exists-in-option-area option. */
1877 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
1878 data_string_forget (result
, MDL
);
1881 ds
.data
= &ds
.buffer
-> data
[0];
1882 ds
.buffer
-> data
[0] = 2;
1883 ds
.buffer
-> data
[1] = 0;
1884 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
1885 data_string_forget (result
, MDL
);
1886 data_string_copy (result
, &ds
, MDL
);
1887 data_string_forget (&ds
, MDL
);
1893 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
1894 in_options
, cfg_options
, scope
, universe
)
1895 struct data_string
*result
;
1896 struct packet
*packet
;
1897 struct lease
*lease
;
1898 struct client_state
*client_state
;
1899 struct option_state
*in_options
;
1900 struct option_state
*cfg_options
;
1901 struct binding_scope
**scope
;
1902 struct universe
*universe
;
1905 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
1908 struct buffer
*bp
= (struct buffer
*)0;
1909 struct option_chain_head
*head
;
1911 /* If there's no FQDN universe, don't encapsulate. */
1912 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
1914 head
= ((struct option_chain_head
*)
1915 cfg_options
-> universes
[fqdn_universe
.index
]);
1919 /* Figure out the values of all the suboptions. */
1920 memset (results
, 0, sizeof results
);
1921 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
1922 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
1923 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
1925 evaluate_option_cache (&results
[oc
-> option
-> code
],
1926 packet
, lease
, client_state
, in_options
,
1927 cfg_options
, scope
, oc
, MDL
);
1929 len
= 4 + results
[FQDN_FQDN
].len
;
1930 /* Save the contents of the option in a buffer. */
1931 if (!buffer_allocate (&bp
, len
, MDL
)) {
1932 log_error ("no memory for option buffer.");
1935 buffer_reference (&result
-> buffer
, bp
, MDL
);
1937 result
-> data
= &bp
-> data
[0];
1939 memset (&bp
-> data
[0], 0, len
);
1940 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
1941 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
1942 bp
-> data
[0] |= 2;
1943 if (results
[FQDN_SERVER_UPDATE
].len
&&
1944 results
[FQDN_SERVER_UPDATE
].data
[0])
1945 bp
-> data
[0] |= 1;
1946 if (results
[FQDN_RCODE1
].len
)
1947 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
1948 if (results
[FQDN_RCODE2
].len
)
1949 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
1951 if (results
[FQDN_ENCODED
].len
&&
1952 results
[FQDN_ENCODED
].data
[0]) {
1955 bp
-> data
[0] |= 4;
1956 out
= &bp
-> data
[3];
1957 if (results
[FQDN_FQDN
].len
) {
1959 while (i
< results
[FQDN_FQDN
].len
) {
1962 results
[FQDN_FQDN
].data
[j
]) &&
1963 j
< results
[FQDN_FQDN
].len
; j
++)
1966 memcpy (out
, &results
[FQDN_FQDN
].data
[i
],
1970 if (results
[FQDN_FQDN
].data
[j
] == '.')
1973 if ((results
[FQDN_FQDN
].data
1974 [results
[FQDN_FQDN
].len
- 1] == '.'))
1976 result
-> len
= out
- result
-> data
;
1977 result
-> terminated
= 0;
1980 if (results
[FQDN_FQDN
].len
) {
1981 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
1982 results
[FQDN_FQDN
].len
);
1983 result
-> len
+= results
[FQDN_FQDN
].len
;
1984 result
-> terminated
= 0;
1987 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
1988 if (results
[i
].len
)
1989 data_string_forget (&results
[i
], MDL
);
1991 buffer_dereference (&bp
, MDL
);
1995 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
1996 struct client_state
*client_state
,
1997 struct option_state
*in_options
,
1998 struct option_state
*cfg_options
,
1999 struct binding_scope
**scope
,
2000 struct universe
*u
, void *stuff
,
2001 void (*func
) (struct option_cache
*,
2003 struct lease
*, struct client_state
*,
2004 struct option_state
*,
2005 struct option_state
*,
2006 struct binding_scope
**,
2007 struct universe
*, void *))
2010 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
2011 cfg_options
, scope
, u
, stuff
, func
);
2014 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
2015 struct client_state
*client_state
,
2016 struct option_state
*in_options
,
2017 struct option_state
*cfg_options
,
2018 struct binding_scope
**scope
,
2019 struct universe
*u
, void *stuff
,
2020 void (*func
) (struct option_cache
*,
2022 struct lease
*, struct client_state
*,
2023 struct option_state
*,
2024 struct option_state
*,
2025 struct binding_scope
**,
2026 struct universe
*, void *),
2027 struct option_cache
*oc
,
2030 struct universe
*universe
= find_option_universe (oc
-> option
,
2034 if (universe
-> foreach
)
2035 (*universe
-> foreach
) (packet
, lease
, client_state
,
2036 in_options
, cfg_options
,
2037 scope
, universe
, stuff
, func
);
2040 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2041 struct client_state
*client_state
,
2042 struct option_state
*in_options
,
2043 struct option_state
*cfg_options
,
2044 struct binding_scope
**scope
,
2045 struct universe
*u
, void *stuff
,
2046 void (*func
) (struct option_cache
*,
2049 struct client_state
*,
2050 struct option_state
*,
2051 struct option_state
*,
2052 struct binding_scope
**,
2053 struct universe
*, void *))
2057 struct option_cache
*oc
;
2059 if (cfg_options
-> universe_count
<= u
-> index
)
2062 hash
= cfg_options
-> universes
[u
-> index
];
2065 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2067 /* XXX save _all_ options! XXX */
2068 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2069 oc
= (struct option_cache
*)p
-> car
;
2070 (*func
) (oc
, packet
, lease
, client_state
,
2071 in_options
, cfg_options
, scope
, u
, stuff
);
2076 void save_linked_option (universe
, options
, oc
)
2077 struct universe
*universe
;
2078 struct option_state
*options
;
2079 struct option_cache
*oc
;
2082 // pair np = (pair )0;
2083 struct option_chain_head
*head
;
2085 if (universe
-> index
>= options
-> universe_count
)
2087 head
= ((struct option_chain_head
*)
2088 options
-> universes
[universe
-> index
]);
2090 if (!option_chain_head_allocate (((struct option_chain_head
**)
2091 &options
-> universes
2092 [universe
-> index
]), MDL
))
2094 head
= ((struct option_chain_head
*)
2095 options
-> universes
[universe
-> index
]);
2098 /* Find the tail of the list. */
2099 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
2101 ((struct option_cache
*)((*tail
) -> car
)) -> option
) {
2102 option_cache_dereference ((struct option_cache
**)
2103 (&(*tail
) -> car
), MDL
);
2104 option_cache_reference ((struct option_cache
**)
2105 (&(*tail
) -> car
), oc
, MDL
);
2110 *tail
= cons (0, 0);
2112 option_cache_reference ((struct option_cache
**)
2113 (&(*tail
) -> car
), oc
, MDL
);
2117 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
2118 in_options
, cfg_options
, scope
, universe
)
2119 struct data_string
*result
;
2120 struct packet
*packet
;
2121 struct lease
*lease
;
2122 struct client_state
*client_state
;
2123 struct option_state
*in_options
;
2124 struct option_state
*cfg_options
;
2125 struct binding_scope
**scope
;
2126 struct universe
*universe
;
2130 struct option_chain_head
*head
;
2132 if (universe
-> index
>= cfg_options
-> universe_count
)
2134 head
= ((struct option_chain_head
*)
2135 cfg_options
-> universes
[universe
-> index
]);
2140 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
2141 if (store_option (result
, universe
, packet
,
2142 lease
, client_state
, in_options
, cfg_options
,
2143 scope
, (struct option_cache
*)(oc
-> car
)))
2150 void delete_linked_option (universe
, options
, code
)
2151 struct universe
*universe
;
2152 struct option_state
*options
;
2155 pair
*tail
, tmp
= (pair
)0;
2156 struct option_chain_head
*head
;
2158 if (universe
-> index
>= options
-> universe_count
)
2160 head
= ((struct option_chain_head
*)
2161 options
-> universes
[universe
-> index
]);
2165 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
2167 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
2169 tmp
= (*tail
) -> cdr
;
2170 option_cache_dereference ((struct option_cache
**)
2171 (&(*tail
) -> car
), MDL
);
2179 struct option_cache
*lookup_linked_option (universe
, options
, code
)
2180 struct universe
*universe
;
2181 struct option_state
*options
;
2185 struct option_chain_head
*head
;
2187 if (universe
-> index
>= options
-> universe_count
)
2189 head
= ((struct option_chain_head
*)
2190 options
-> universes
[universe
-> index
]);
2194 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
2196 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
2197 return (struct option_cache
*)(oc
-> car
);
2201 return (struct option_cache
*)0;
2204 int linked_option_state_dereference (universe
, state
, file
, line
)
2205 struct universe
*universe
;
2206 struct option_state
*state
;
2210 return (option_chain_head_dereference
2211 ((struct option_chain_head
**)
2212 (&state
-> universes
[universe
-> index
]), MDL
));
2215 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2216 struct client_state
*client_state
,
2217 struct option_state
*in_options
,
2218 struct option_state
*cfg_options
,
2219 struct binding_scope
**scope
,
2220 struct universe
*u
, void *stuff
,
2221 void (*func
) (struct option_cache
*,
2224 struct client_state
*,
2225 struct option_state
*,
2226 struct option_state
*,
2227 struct binding_scope
**,
2228 struct universe
*, void *))
2231 struct option_chain_head
*head
;
2233 if (u
-> index
>= cfg_options
-> universe_count
)
2235 head
= ((struct option_chain_head
*)
2236 cfg_options
-> universes
[u
-> index
]);
2239 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
2240 (*func
) ((struct option_cache
*)(car
-> car
),
2241 packet
, lease
, client_state
,
2242 in_options
, cfg_options
, scope
, u
, stuff
);
2246 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
2247 struct interface_info
*interface
;
2248 struct dhcp_packet
*packet
;
2250 unsigned int from_port
;
2252 struct hardware
*hfrom
;
2255 struct option_cache
*op
;
2256 struct packet
*decoded_packet
;
2257 #if defined (DEBUG_MEMORY_LEAKAGE)
2258 unsigned long previous_outstanding
= dmalloc_outstanding
;
2261 #if defined (TRACING)
2262 trace_inpacket_stash (interface
, packet
, len
, from_port
, from
, hfrom
);
2265 decoded_packet
= (struct packet
*)0;
2266 if (!packet_allocate (&decoded_packet
, MDL
)) {
2267 log_error ("do_packet: no memory for incoming packet!");
2270 decoded_packet
-> raw
= packet
;
2271 decoded_packet
-> packet_length
= len
;
2272 decoded_packet
-> client_port
= from_port
;
2273 decoded_packet
-> client_addr
= from
;
2274 interface_reference (&decoded_packet
-> interface
, interface
, MDL
);
2275 decoded_packet
-> haddr
= hfrom
;
2277 if (packet
-> hlen
> sizeof packet
-> chaddr
) {
2278 packet_dereference (&decoded_packet
, MDL
);
2279 log_info ("Discarding packet with bogus hlen.");
2283 /* If there's an option buffer, try to parse it. */
2284 if (decoded_packet
-> packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
2285 if (!parse_options (decoded_packet
)) {
2286 if (decoded_packet
-> options
)
2287 option_state_dereference
2288 (&decoded_packet
-> options
, MDL
);
2289 packet_dereference (&decoded_packet
, MDL
);
2293 if (decoded_packet
-> options_valid
&&
2294 (op
= lookup_option (&dhcp_universe
,
2295 decoded_packet
-> options
,
2296 DHO_DHCP_MESSAGE_TYPE
))) {
2297 struct data_string dp
;
2298 memset (&dp
, 0, sizeof dp
);
2299 evaluate_option_cache (&dp
, decoded_packet
,
2301 (struct client_state
*)0,
2302 decoded_packet
-> options
,
2303 (struct option_state
*)0,
2304 (struct binding_scope
**)0,
2307 decoded_packet
-> packet_type
= dp
.data
[0];
2309 decoded_packet
-> packet_type
= 0;
2310 data_string_forget (&dp
, MDL
);
2314 if (decoded_packet
-> packet_type
)
2315 dhcp (decoded_packet
);
2317 bootp (decoded_packet
);
2319 /* If the caller kept the packet, they'll have upped the refcnt. */
2320 packet_dereference (&decoded_packet
, MDL
);
2322 #if defined (DEBUG_MEMORY_LEAKAGE)
2323 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2325 dmalloc_outstanding
- previous_outstanding
,
2326 dmalloc_outstanding
, dmalloc_longterm
);
2328 #if defined (DEBUG_MEMORY_LEAKAGE)
2329 dmalloc_dump_outstanding ();
2331 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2332 dump_rc_history (0);