3 DHCP options parsing and reassembly. */
6 * Copyright (c) 2004-2006 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: options.c,v 1.89 2006/02/24 23:16:28 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
40 #define DHCP_OPTION_DATA
42 #include <omapip/omapip_p.h>
44 struct option
*vendor_cfg_option
;
46 static void do_option_set
PROTO ((pair
*,
47 struct option_cache
*,
50 /* Parse all available options out of the specified packet. */
52 int parse_options (packet
)
53 struct packet
*packet
;
56 struct option_cache
*op
= (struct option_cache
*)0;
58 /* Allocate a new option state. */
59 if (!option_state_allocate (&packet
-> options
, MDL
)) {
60 packet
-> options_valid
= 0;
64 /* If we don't see the magic cookie, there's nothing to parse. */
65 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
66 packet
-> options_valid
= 0;
70 /* Go through the options field, up to the end of the packet
72 if (!parse_option_buffer (packet
-> options
,
73 &packet
-> raw
-> options
[4],
74 (packet
-> packet_length
-
75 DHCP_FIXED_NON_UDP
- 4),
78 /* STSN servers have a bug where they send a mangled
79 domain-name option, and whatever is beyond that in
80 the packet is junk. Microsoft clients accept this,
81 which is probably why whoever implemented the STSN
82 server isn't aware of the problem yet. To work around
83 this, we will accept corrupt packets from the server if
84 they contain a valid DHCP_MESSAGE_TYPE option, but
85 will not accept any corrupt client packets (the ISC DHCP
86 server is sufficiently widely used that it is probably
87 beneficial for it to be picky) and will not accept
88 packets whose type can't be determined. */
90 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
91 DHO_DHCP_MESSAGE_TYPE
))) {
92 if (!op
-> data
.data
||
93 (op
-> data
.data
[0] != DHCPOFFER
&&
94 op
-> data
.data
[0] != DHCPACK
&&
95 op
-> data
.data
[0] != DHCPNAK
))
101 /* If we parsed a DHCP Option Overload option, parse more
102 options out of the buffer(s) containing them. */
103 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
104 DHO_DHCP_OPTION_OVERLOAD
))) {
105 if (op
-> data
.data
[0] & 1) {
106 if (!parse_option_buffer
108 (unsigned char *)packet
-> raw
-> file
,
109 sizeof packet
-> raw
-> file
,
113 if (op
-> data
.data
[0] & 2) {
114 if (!parse_option_buffer
116 (unsigned char *)packet
-> raw
-> sname
,
117 sizeof packet
-> raw
-> sname
,
122 packet
-> options_valid
= 1;
126 /* Parse options out of the specified buffer, storing addresses of option
127 values in packet -> options and setting packet -> options_valid if no
128 errors are encountered. */
130 int parse_option_buffer (options
, buffer
, length
, universe
)
131 struct option_state
*options
;
132 const unsigned char *buffer
;
134 struct universe
*universe
;
137 const unsigned char *end
= buffer
+ length
;
138 unsigned len
, offset
;
140 struct option_cache
*op
= (struct option_cache
*)0;
141 struct buffer
*bp
= (struct buffer
*)0;
143 if (!buffer_allocate (&bp
, length
, MDL
)) {
144 log_error ("no memory for option buffer.");
147 memcpy (bp
-> data
, buffer
, length
);
149 for (offset
= 0; buffer
[offset
] != DHO_END
&& offset
< length
; ) {
150 code
= buffer
[offset
];
151 /* Pad options don't have a length - just skip them. */
152 if (code
== DHO_PAD
) {
157 /* Don't look for length if the buffer isn't that big. */
158 if (offset
+ 2 > length
) {
163 /* All other fields (except end, see above) have a
165 len
= buffer
[offset
+ 1];
167 /* If the length is outrageous, the options are bad. */
168 if (offset
+ len
+ 2 > length
) {
170 log_error ("parse_option_buffer: option %s (%d) %s.",
171 dhcp_options
[code
].name
, len
,
172 "larger than buffer");
173 buffer_dereference (&bp
, MDL
);
177 /* If the option contains an encapsulation, parse it. If
178 the parse fails, or the option isn't an encapsulation (by
179 far the most common case), or the option isn't entirely
180 an encapsulation, keep the raw data as well. */
181 if (universe
-> options
[code
] &&
182 !((universe
-> options
[code
] -> format
[0] == 'e' ||
183 universe
-> options
[code
] -> format
[0] == 'E') &&
184 (parse_encapsulated_suboptions
185 (options
, universe
-> options
[code
],
186 buffer
+ offset
+ 2, len
,
187 universe
, (const char *)0)))) {
188 op
= lookup_option (universe
, options
, code
);
190 struct data_string
new;
191 memset (&new, 0, sizeof new);
192 if (!buffer_allocate (&new.buffer
, op
-> data
.len
+ len
,
194 log_error ("parse_option_buffer: No memory.");
197 memcpy (new.buffer
-> data
, op
-> data
.data
,
199 memcpy (&new.buffer
-> data
[op
-> data
.len
],
200 &bp
-> data
[offset
+ 2], len
);
201 new.len
= op
-> data
.len
+ len
;
202 new.data
= new.buffer
-> data
;
203 data_string_forget (&op
-> data
, MDL
);
204 data_string_copy (&op
-> data
, &new, MDL
);
205 data_string_forget (&new, MDL
);
207 save_option_buffer (universe
, options
, bp
,
208 &bp
-> data
[offset
+ 2], len
,
209 universe
-> options
[code
], 1);
214 buffer_dereference (&bp
, MDL
);
218 /* If an option in an option buffer turns out to be an encapsulation,
219 figure out what to do. If we don't know how to de-encapsulate it,
220 or it's not well-formed, return zero; otherwise, return 1, indicating
221 that we succeeded in de-encapsulating it. */
223 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
227 struct universe
*universe
= (struct universe
*)0;
229 /* Look for the E option in the option format. */
230 s
= strchr (eopt
-> format
, 'E');
232 log_error ("internal encapsulation format error 1.");
235 /* Look for the universe name in the option format. */
236 t
= strchr (++s
, '.');
237 /* If there was no trailing '.', or there's something after the
238 trailing '.', the option is bogus and we can't use it. */
240 log_error ("internal encapsulation format error 2.");
243 if (t
== s
&& uname
) {
244 for (i
= 0; i
< universe_count
; i
++) {
245 if (!strcmp (universes
[i
] -> name
, uname
)) {
246 universe
= universes
[i
];
251 for (i
= 0; i
< universe_count
; i
++) {
252 if (strlen (universes
[i
] -> name
) == t
- s
&&
253 !memcmp (universes
[i
] -> name
,
254 s
, (unsigned)(t
- s
))) {
255 universe
= universes
[i
];
263 /* If an option in an option buffer turns out to be an encapsulation,
264 figure out what to do. If we don't know how to de-encapsulate it,
265 or it's not well-formed, return zero; otherwise, return 1, indicating
266 that we succeeded in de-encapsulating it. */
268 int parse_encapsulated_suboptions (struct option_state
*options
,
270 const unsigned char *buffer
,
271 unsigned len
, struct universe
*eu
,
275 struct universe
*universe
= find_option_universe (eopt
, uname
);
277 /* If we didn't find the universe, we can't do anything with it
278 right now (e.g., we can't decode vendor options until we've
279 decoded the packet and executed the scopes that it matches). */
283 /* If we don't have a decoding function for it, we can't decode
285 if (!universe
-> decode
)
288 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
290 /* If there is stuff before the suboptions, we have to keep it. */
291 if (eopt
-> format
[0] != 'E')
293 /* Otherwise, return the status of the decode function. */
297 int fqdn_universe_decode (struct option_state
*options
,
298 const unsigned char *buffer
,
299 unsigned length
, struct universe
*u
)
302 struct buffer
*bp
= (struct buffer
*)0;
304 /* FQDN options have to be at least four bytes long. */
308 /* Save the contents of the option in a buffer. */
309 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
310 log_error ("no memory for option buffer.");
313 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
315 if (buffer
[0] & 4) /* encoded */
319 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
321 &fqdn_options
[FQDN_ENCODED
], 0)) {
323 buffer_dereference (&bp
, MDL
);
327 if (buffer
[0] & 1) /* server-update */
331 if (buffer
[0] & 2) /* no-client-update */
336 /* XXX Ideally we should store the name in DNS format, so if the
337 XXX label isn't in DNS format, we convert it to DNS format,
338 XXX rather than converting labels specified in DNS format to
339 XXX the plain ASCII representation. But that's hard, so
342 /* Not encoded using DNS format? */
343 if (!bp
-> data
[0]) {
346 /* Some broken clients NUL-terminate this option. */
347 if (buffer
[length
- 1] == 0) {
352 /* Determine the length of the hostname component of the
353 name. If the name contains no '.' character, it
354 represents a non-qualified label. */
355 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
358 /* Note: If the client sends a FQDN, the first '.' will
359 be used as a NUL terminator for the hostname. */
361 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
363 &fqdn_options
[FQDN_HOSTNAME
],
366 /* Note: If the client sends a single label, the
367 FQDN_DOMAINNAME option won't be set. */
368 if (length
> 4 + i
&&
369 !save_option_buffer (&fqdn_universe
, options
, bp
,
370 &bp
-> data
[6 + i
], length
- 4 - i
,
371 &fqdn_options
[FQDN_DOMAINNAME
], 1))
373 /* Also save the whole name. */
375 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
376 &bp
-> data
[5], length
- 3,
377 &fqdn_options
[FQDN_FQDN
], 1))
381 unsigned total_len
= 0;
382 unsigned first_len
= 0;
388 while (s
< &bp
-> data
[0] + length
+ 2) {
391 log_info ("fancy bits in fqdn option");
398 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
399 log_info ("fqdn tag longer than buffer");
403 if (first_len
== 0) {
409 total_len
+= len
+ 1;
412 /* We wind up with a length that's one too many because
413 we shouldn't increment for the last label, but there's
414 no way to tell we're at the last label until we exit
420 first_len
= total_len
;
424 !save_option_buffer (&fqdn_universe
, options
, bp
,
425 &bp
-> data
[6], first_len
,
426 &fqdn_options
[FQDN_HOSTNAME
], 0))
428 if (total_len
> 0 && first_len
!= total_len
) {
429 if (!save_option_buffer
430 (&fqdn_universe
, options
, bp
,
431 &bp
-> data
[6 + first_len
], total_len
- first_len
,
432 &fqdn_options
[FQDN_DOMAINNAME
], 1))
436 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
437 &bp
-> data
[6], total_len
,
438 &fqdn_options
[FQDN_FQDN
], 1))
442 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
444 &fqdn_options
[FQDN_NO_CLIENT_UPDATE
], 0))
446 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
448 &fqdn_options
[FQDN_SERVER_UPDATE
], 0))
451 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
453 &fqdn_options
[FQDN_RCODE1
], 0))
455 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
457 &fqdn_options
[FQDN_RCODE2
], 0))
460 buffer_dereference (&bp
, MDL
);
464 /* cons options into a big buffer, and then split them out into the
465 three seperate buffers if needed. This allows us to cons up a set
466 of vendor options using the same routine. */
468 int cons_options (inpacket
, outpacket
, lease
, client_state
,
469 mms
, in_options
, cfg_options
,
470 scope
, overload
, terminate
, bootpp
, prl
, vuname
)
471 struct packet
*inpacket
;
472 struct dhcp_packet
*outpacket
;
474 struct client_state
*client_state
;
476 struct option_state
*in_options
;
477 struct option_state
*cfg_options
;
478 struct binding_scope
**scope
;
479 int overload
; /* Overload flags that may be set. */
482 struct data_string
*prl
;
485 #define PRIORITY_COUNT 300
486 unsigned priority_list
[PRIORITY_COUNT
];
488 unsigned char buffer
[4096]; /* Really big buffer... */
489 unsigned main_buffer_size
, mb_max
;
490 unsigned mainbufix
, bufix
, agentix
;
493 unsigned option_size
;
496 struct option_cache
*op
;
497 struct data_string ds
;
502 int ofbuf1
=0, ofbuf2
=0;
504 memset (&ds
, 0, sizeof ds
);
506 /* If there's a Maximum Message Size option in the incoming packet
507 and no alternate maximum message size has been specified, take the
508 one in the packet. */
511 (op
= lookup_option (&dhcp_universe
, inpacket
-> options
,
512 DHO_DHCP_MAX_MESSAGE_SIZE
))) {
513 evaluate_option_cache (&ds
, inpacket
,
514 lease
, client_state
, in_options
,
515 cfg_options
, scope
, op
, MDL
);
516 if (ds
.len
>= sizeof (u_int16_t
)) {
517 i
= getUShort (ds
.data
);
519 if(!mms
|| (i
< mms
))
522 data_string_forget (&ds
, MDL
);
525 /* If the client has provided a maximum DHCP message size,
526 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
527 use up to the minimum IP MTU size (576 bytes). */
528 /* XXX if a BOOTP client specifies a max message size, we will
532 main_buffer_size
= mms
- DHCP_FIXED_LEN
;
534 /* Enforce a minimum packet size... */
535 if (main_buffer_size
< (576 - DHCP_FIXED_LEN
))
536 main_buffer_size
= 576 - DHCP_FIXED_LEN
;
540 inpacket
-> packet_length
- DHCP_FIXED_LEN
;
541 if (main_buffer_size
< 64)
542 main_buffer_size
= 64;
544 main_buffer_size
= 64;
546 main_buffer_size
= 576 - DHCP_FIXED_LEN
;
548 /* Set a hard limit at the size of the output buffer. */
549 mb_max
= sizeof(buffer
) - (((overload
& 1) ? DHCP_FILE_LEN
: 0) +
550 ((overload
& 2) ? DHCP_SNAME_LEN
: 0));
551 if (main_buffer_size
> mb_max
)
552 main_buffer_size
= mb_max
;
554 /* Preload the option priority list with mandatory options. */
556 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
557 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
558 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
559 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
560 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
561 priority_list
[priority_len
++] = DHO_FQDN
;
563 if (prl
&& prl
-> len
> 0) {
564 if ((op
= lookup_option (&dhcp_universe
, cfg_options
,
565 DHO_SUBNET_SELECTION
))) {
566 if (priority_len
< PRIORITY_COUNT
)
567 priority_list
[priority_len
++] =
568 DHO_SUBNET_SELECTION
;
571 data_string_truncate (prl
, (PRIORITY_COUNT
- priority_len
));
573 for (i
= 0; i
< prl
-> len
; i
++) {
574 /* Prevent client from changing order of delivery
575 of relay agent information option. */
576 if (prl
-> data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
577 priority_list
[priority_len
++] =
581 /* First, hardcode some more options that ought to be
583 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
584 priority_list
[priority_len
++] = DHO_ROUTERS
;
585 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
586 priority_list
[priority_len
++] = DHO_HOST_NAME
;
588 /* Append a list of the standard DHCP options from the
589 standard DHCP option space. Actually, if a site
590 option space hasn't been specified, we wind up
591 treating the dhcp option space as the site option
592 space, and the first for loop is skipped, because
593 it's slightly more general to do it this way,
594 taking the 1Q99 DHCP futures work into account. */
595 if (cfg_options
-> site_code_min
) {
596 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
597 hash
= cfg_options
-> universes
[dhcp_universe
.index
];
599 for (pp
= hash
[i
]; pp
; pp
= pp
-> cdr
) {
600 op
= (struct option_cache
*)(pp
-> car
);
601 if (op
-> option
-> code
<
602 cfg_options
-> site_code_min
&&
603 priority_len
< PRIORITY_COUNT
&&
604 (op
-> option
-> code
!=
605 DHO_DHCP_AGENT_OPTIONS
))
606 priority_list
[priority_len
++] =
607 op
-> option
-> code
;
613 /* Now cycle through the site option space, or if there
614 is no site option space, we'll be cycling through the
615 dhcp option space. */
616 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
617 hash
= (cfg_options
-> universes
618 [cfg_options
-> site_universe
]);
620 for (pp
= hash
[i
]; pp
; pp
= pp
-> cdr
) {
621 op
= (struct option_cache
*)(pp
-> car
);
622 if (op
-> option
-> code
>=
623 cfg_options
-> site_code_min
&&
624 priority_len
< PRIORITY_COUNT
&&
625 (op
-> option
-> code
!=
626 DHO_DHCP_AGENT_OPTIONS
))
627 priority_list
[priority_len
++] =
628 op
-> option
-> code
;
632 /* Now go through all the universes for which options
633 were set and see if there are encapsulations for
634 them; if there are, put the encapsulation options
635 on the priority list as well. */
636 for (i
= 0; i
< cfg_options
-> universe_count
; i
++) {
637 if (cfg_options
-> universes
[i
] &&
638 universes
[i
] -> enc_opt
&&
639 priority_len
< PRIORITY_COUNT
&&
640 universes
[i
] -> enc_opt
-> universe
== &dhcp_universe
)
642 if (universes
[i
] -> enc_opt
-> code
!=
643 DHO_DHCP_AGENT_OPTIONS
)
644 priority_list
[priority_len
++] =
645 universes
[i
] -> enc_opt
-> code
;
649 /* The vendor option space can't stand on its own, so always
650 add it to the list. */
651 if (priority_len
< PRIORITY_COUNT
)
652 priority_list
[priority_len
++] =
653 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
656 /* Figure out the overload buffer offset(s). */
658 ofbuf1
= main_buffer_size
- 4;
660 ofbuf2
= main_buffer_size
- 4 + DHCP_FILE_LEN
;
663 /* Copy the options into the big buffer... */
664 option_size
= store_options (&ocount
, buffer
,
665 (main_buffer_size
- 4 +
666 ((overload
& 1) ? DHCP_FILE_LEN
: 0) +
667 ((overload
& 2) ? DHCP_SNAME_LEN
: 0)),
668 inpacket
, lease
, client_state
,
669 in_options
, cfg_options
, scope
,
670 priority_list
, priority_len
,
671 ofbuf1
, ofbuf2
, terminate
, vuname
);
672 /* If store_options failed. */
673 if (option_size
== 0)
676 if (ocount
== 1 && (overload
& 1))
678 else if (ocount
== 1 && (overload
& 2))
680 else if (ocount
== 3)
686 /* Put the cookie up front... */
687 memcpy (outpacket
-> options
, DHCP_OPTIONS_COOKIE
, 4);
690 /* If we're going to have to overload, store the overload
691 option at the beginning. If we can, though, just store the
692 whole thing in the packet's option buffer and leave it at
694 memcpy (&outpacket
-> options
[mainbufix
],
695 buffer
, option_size
);
696 mainbufix
+= option_size
;
698 outpacket
-> options
[mainbufix
++] = DHO_DHCP_OPTION_OVERLOAD
;
699 outpacket
-> options
[mainbufix
++] = 1;
700 outpacket
-> options
[mainbufix
++] = overload
;
703 memcpy (outpacket
-> file
,
704 &buffer
[ofbuf1
], DHCP_FILE_LEN
);
708 memcpy (outpacket
-> sname
, &buffer
[ofbuf2
],
711 memcpy (outpacket
-> sname
, &buffer
[ofbuf1
],
717 if (mainbufix
< main_buffer_size
)
719 length
= DHCP_FIXED_NON_UDP
+ mainbufix
;
721 /* Now hack in the agent options if there are any. */
722 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
725 store_options (0, &outpacket
-> options
[agentix
],
726 DHCP_OPTION_LEN
- agentix
,
727 inpacket
, lease
, client_state
,
728 in_options
, cfg_options
, scope
,
729 priority_list
, priority_len
,
732 /* Tack a DHO_END option onto the packet if we need to. */
733 if (agentix
< DHCP_OPTION_LEN
&& need_endopt
)
734 outpacket
-> options
[agentix
++] = DHO_END
;
736 /* Figure out the length. */
737 length
= DHCP_FIXED_NON_UDP
+ agentix
;
741 /* Store all the requested options into the requested buffer. */
743 int store_options (ocount
, buffer
, buflen
, packet
, lease
, client_state
,
744 in_options
, cfg_options
, scope
, priority_list
, priority_len
,
745 first_cutoff
, second_cutoff
, terminate
, vuname
)
747 unsigned char *buffer
;
749 struct packet
*packet
;
751 struct client_state
*client_state
;
752 struct option_state
*in_options
;
753 struct option_state
*cfg_options
;
754 struct binding_scope
**scope
;
755 unsigned *priority_list
;
757 unsigned first_cutoff
, second_cutoff
;
761 int bufix
= 0, six
= 0, tix
= 0;
766 struct data_string od
;
767 struct option_cache
*oc
;
771 if (first_cutoff
>= buflen
)
772 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
774 bufend
= first_cutoff
;
779 if (second_cutoff
>= buflen
)
780 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
782 sbufend
= second_cutoff
;
786 memset (&od
, 0, sizeof od
);
788 /* Eliminate duplicate options in the parameter request list.
789 There's got to be some clever knuthian way to do this:
790 Eliminate all but the first occurance of a value in an array
791 of values without otherwise disturbing the order of the array. */
792 for (i
= 0; i
< priority_len
- 1; i
++) {
794 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
796 priority_list
[ix
- tto
] =
798 if (priority_list
[i
] == priority_list
[ix
]) {
805 /* Copy out the options in the order that they appear in the
807 for (i
= 0; i
< priority_len
; i
++) {
808 /* Number of bytes left to store (some may already
809 have been stored by a previous pass). */
811 int optstart
, soptstart
, toptstart
;
813 int have_encapsulation
= 0;
814 struct data_string encapsulation
;
817 memset (&encapsulation
, 0, sizeof encapsulation
);
819 /* Code for next option to try to store. */
820 code
= priority_list
[i
];
822 /* Look up the option in the site option space if the code
823 is above the cutoff, otherwise in the DHCP option space. */
824 if (code
>= cfg_options
-> site_code_min
)
825 u
= universes
[cfg_options
-> site_universe
];
829 oc
= lookup_option (u
, cfg_options
, code
);
831 /* It's an encapsulation, try to find the universe
832 to be encapsulated first, except that if it's a straight
833 encapsulation and the user has provided a value for the
834 encapsulation option, use the user-provided value. */
835 if (u
-> options
[code
] &&
836 ((u
-> options
[code
] -> format
[0] == 'E' && !oc
) ||
837 u
-> options
[code
] -> format
[0] == 'e')) {
840 struct option_cache
*tmp
;
841 struct data_string name
;
843 s
= strchr (u
-> options
[code
] -> format
, 'E');
845 t
= strchr (++s
, '.');
847 memset (&name
, 0, sizeof name
);
849 /* A zero-length universe name means the vendor
850 option space, if one is defined. */
852 if (vendor_cfg_option
) {
853 tmp
= lookup_option (vendor_cfg_option
-> universe
,
855 vendor_cfg_option
-> code
);
857 evaluate_option_cache (&name
, packet
, lease
,
863 name
.data
= (unsigned char *)s
;
864 name
.len
= strlen (s
);
867 name
.data
= (unsigned char *)s
;
871 /* If we found a universe, and there are options configured
872 for that universe, try to encapsulate it. */
875 (option_space_encapsulate
876 (&encapsulation
, packet
, lease
, client_state
,
877 in_options
, cfg_options
, scope
, &name
));
878 data_string_forget (&name
, MDL
);
883 /* In order to avoid memory leaks, we have to get to here
884 with any option cache that we allocated in tmp not being
885 referenced by tmp, and whatever option cache is referenced
886 by oc being an actual reference. lookup_option doesn't
887 generate a reference (this needs to be fixed), so the
888 preceding goop ensures that if we *didn't* generate a new
889 option cache, oc still winds up holding an actual reference. */
891 /* If no data is available for this option, skip it. */
892 if (!oc
&& !have_encapsulation
) {
896 /* Find the value of the option... */
898 evaluate_option_cache (&od
, packet
,
899 lease
, client_state
, in_options
,
900 cfg_options
, scope
, oc
, MDL
);
902 data_string_forget (&encapsulation
, MDL
);
903 data_string_forget (&od
, MDL
);
904 have_encapsulation
= 0;
909 /* We should now have a constant length for the option. */
911 if (have_encapsulation
) {
912 length
+= encapsulation
.len
;
914 data_string_copy (&od
, &encapsulation
, MDL
);
915 data_string_forget (&encapsulation
, MDL
);
917 struct buffer
*bp
= (struct buffer
*)0;
918 if (!buffer_allocate (&bp
, length
, MDL
)) {
919 option_cache_dereference (&oc
, MDL
);
920 data_string_forget (&od
, MDL
);
921 data_string_forget (&encapsulation
, MDL
);
924 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
925 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
927 data_string_forget (&od
, MDL
);
928 data_string_forget (&encapsulation
, MDL
);
929 od
.data
= &bp
-> data
[0];
930 buffer_reference (&od
.buffer
, bp
, MDL
);
931 buffer_dereference (&bp
, MDL
);
937 /* Do we add a NUL? */
938 if (terminate
&& dhcp_options
[code
].format
[0] == 't') {
945 /* Try to store the option. */
947 /* If the option's length is more than 255, we must store it
948 in multiple hunks. Store 255-byte hunks first. However,
949 in any case, if the option data will cross a buffer
950 boundary, split it across that boundary. */
963 unsigned incr
= length
;
968 /* Try to fit it in the options buffer. */
970 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
971 (bufix
+ 2 + length
< bufend
)) ||
972 (bufix
+ 5 + length
< bufend
))) {
975 /* Try to fit it in the second buffer. */
976 } else if (!splitup
&& first_cutoff
&&
977 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
978 base
= &buffer
[first_cutoff
];
980 /* Try to fit it in the third buffer. */
981 } else if (!splitup
&& second_cutoff
&&
982 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
983 base
= &buffer
[second_cutoff
];
985 /* Split the option up into the remaining space. */
989 /* Use any remaining options space. */
990 if (bufix
+ 6 < bufend
) {
991 incr
= bufend
- bufix
- 5;
994 /* Use any remaining first_cutoff space. */
995 } else if (first_cutoff
&&
996 (first_cutoff
+ six
+ 4 < sbufend
)) {
997 incr
= sbufend
- (first_cutoff
+ six
) - 3;
998 base
= &buffer
[first_cutoff
];
1000 /* Use any remaining second_cutoff space. */
1001 } else if (second_cutoff
&&
1002 (second_cutoff
+ tix
+ 4 < buflen
)) {
1003 incr
= buflen
- (second_cutoff
+ tix
) - 3;
1004 base
= &buffer
[second_cutoff
];
1006 /* Give up, roll back this option. */
1020 /* Everything looks good - copy it in! */
1022 base
[*pix
+ 1] = (unsigned char)incr
;
1023 if (tto
&& incr
== length
) {
1025 memcpy (base
+ *pix
+ 2,
1026 od
.data
+ ix
, (unsigned)(incr
- 1));
1027 base
[*pix
+ 2 + incr
- 1] = 0;
1029 memcpy (base
+ *pix
+ 2,
1030 od
.data
+ ix
, (unsigned)incr
);
1036 data_string_forget (&od
, MDL
);
1039 /* If we can overload, and we have, then PAD and END those spaces. */
1040 if (first_cutoff
&& six
) {
1041 if ((first_cutoff
+ six
+ 1) < sbufend
)
1042 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1043 sbufend
- (first_cutoff
+ six
+ 1));
1044 else if (first_cutoff
+ six
>= sbufend
)
1045 log_fatal("Second buffer overflow in overloaded options.");
1047 buffer
[first_cutoff
+ six
] = DHO_END
;
1048 *ocount
|= 1; /* So that caller knows there's data there. */
1051 if (second_cutoff
&& tix
) {
1052 if (second_cutoff
+ tix
+ 1 < buflen
) {
1053 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1054 buflen
- (second_cutoff
+ tix
+ 1));
1055 } else if (second_cutoff
+ tix
>= buflen
)
1056 log_fatal("Third buffer overflow in overloaded options.");
1058 buffer
[second_cutoff
+ tix
] = DHO_END
;
1059 *ocount
|= 2; /* So that caller knows there's data there. */
1062 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1063 log_fatal("Not enough space for option overload option.");
1068 /* Return true if the format string has a variable length text option
1069 * ("t"), return false otherwise.
1073 format_has_text(format
)
1080 while (*p
!= '\0') {
1086 /* These symbols are arbitrary, not fixed or
1087 * determinable length...text options with them is
1096 /* 'E' is variable length, but not arbitrary...you
1097 * can find its length if you can find an END option.
1098 * N is one-byte in length but trails a name of a
1099 * space defining the enumeration values. So treat
1100 * both the same - valid, fixed-length fields.
1104 /* Consume the space name. */
1105 while ((*p
!= '\0') && (*p
++ != '.'))
1117 /* Determine the minimum length of a DHCP option prior to any variable
1118 * or inconsistent length formats, according to its configured format
1119 * variable (and possibly from supplied option cache contents for variable
1120 * length format symbols).
1124 format_min_length(format
, oc
)
1126 struct option_cache
*oc
;
1133 while (*p
!= '\0') {
1135 case 'I': /* IPv4 Address */
1136 case 'l': /* int32_t */
1137 case 'L': /* uint32_t */
1138 case 'T': /* Lease Time, uint32_t equivalent */
1143 case 's': /* int16_t */
1144 case 'S': /* uint16_t */
1149 case 'N': /* Enumeration in 1-byte values. */
1150 /* Consume space name. */
1151 while ((*p
!= '\0') && (*p
++ != '.'))
1154 /* Fall Through to handle as one-byte field */
1156 case 'b': /* int8_t */
1157 case 'B': /* uint8_t */
1158 case 'F': /* Flag that is always true. */
1159 case 'f': /* Flag */
1164 case 'o': /* Last argument is optional. */
1165 min_len
-= last_size
;
1166 case 'e': /* Encapsulation hint (there is an 'E' later). */
1170 case 'E': /* Encapsulated options. */
1171 /* Consume space name. */
1172 while ((*p
!= '\0') && (*p
++ != '.'))
1175 /* Find an end option, or find that the encaps options
1176 * go all the way to the end (or beyond) of the data
1177 * portion of the option.
1180 while (min_len
< oc
->data
.len
) {
1181 if (oc
->data
.data
[min_len
] == DHO_END
) {
1185 } else if (oc
->data
.data
[min_len
] == DHO_PAD
) {
1188 } else if ((min_len
+ 1) < oc
->data
.len
) {
1189 min_len
+= oc
->data
.data
[min_len
+1]+2;
1190 last_size
+= oc
->data
.data
[min_len
+1]+2;
1192 /* Suboption length is out of bounds,
1193 * advance beyond the code/length pair
1194 * to trigger below error conditonal.
1202 if (min_len
> oc
->data
.len
) {
1203 log_error("format_min_length(%s): "
1204 "Encapsulated options exceed "
1205 "supplied buffer.", format
);
1211 case 'd': /* "Domain name" */
1212 case 't': /* "ASCII Text" */
1213 case 'X': /* "ASCII or Hex Conditional */
1214 case 'x': /* "Hex" */
1215 case 'A': /* Array of all that precedes. */
1216 case 'a': /* Array of preceding symbol. */
1220 /* No safe value is known. */
1221 log_error("format_min_length(%s): No safe value "
1222 "for unknown format symbols.", format
);
1231 /* Format the specified option so that a human can easily read it. */
1233 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1234 struct option
*option
;
1235 const unsigned char *data
;
1240 static char optbuf
[32768]; /* XXX */
1247 struct enumeration
*enumbuf
[32];
1250 const unsigned char *dp
= data
;
1260 memset (enumbuf
, 0, sizeof enumbuf
);
1262 /* Figure out the size of the data. */
1263 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1265 log_error ("%s: Extra codes in format string: %s",
1267 &(option
-> format
[i
]));
1271 fmtbuf
[l
] = option
-> format
[i
];
1272 switch (option
-> format
[i
]) {
1284 /* Skip the universe name. */
1285 while (option
-> format
[i
] &&
1286 option
-> format
[i
] != '.')
1289 for (k
= 0; k
< len
; k
++) {
1290 if (!isascii (data
[k
]) ||
1291 !isprint (data
[k
]))
1294 /* If we found no bogus characters, or the bogus
1295 character we found is a trailing NUL, it's
1296 okay to print this option as text. */
1297 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1316 while (option
-> format
[i
] &&
1317 option
-> format
[i
] != '.')
1320 find_enumeration (&option
-> format
[k
] + 1,
1349 log_error ("%s: garbage in format string: %s",
1351 &(option
-> format
[i
]));
1356 /* Check for too few bytes... */
1357 if (hunksize
- opthunk
> len
) {
1358 log_error ("%s: expecting at least %d bytes; got %d",
1363 /* Check for too many bytes... */
1364 if (numhunk
== -1 && hunksize
< len
)
1365 log_error ("%s: %d extra bytes",
1369 /* If this is an array, compute its size. */
1371 numhunk
= len
/ hunksize
;
1372 /* See if we got an exact number of hunks. */
1373 if (numhunk
> 0 && numhunk
* hunksize
< len
)
1374 log_error ("%s: %d extra bytes at end of array\n",
1376 len
- numhunk
* hunksize
);
1378 /* A one-hunk array prints the same as a single hunk. */
1382 /* Cycle through the array (or hunk) printing the data. */
1383 for (i
= 0; i
< numhunk
; i
++) {
1384 for (j
= 0; j
< numelem
; j
++) {
1385 switch (fmtbuf
[j
]) {
1389 for (; dp
< data
+ len
; dp
++) {
1390 if (!isascii (*dp
) ||
1392 /* Skip trailing NUL. */
1393 if (dp
+ 1 != data
+ len
||
1395 sprintf (op
, "\\%03o",
1399 } else if (*dp
== '"' ||
1413 /* pretty-printing an array of enums is
1414 going to get ugly. */
1419 if (!enumbuf
[j
] -> values
[i
].name
)
1421 if (enumbuf
[j
] -> values
[i
].value
==
1425 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
1429 foo
.s_addr
= htonl (getULong (dp
));
1430 strcpy (op
, inet_ntoa (foo
));
1434 sprintf (op
, "%ld", (long)getLong (dp
));
1438 tval
= getULong (dp
);
1440 sprintf (op
, "%s", "infinite");
1442 sprintf (op
, "%ld", tval
);
1446 (unsigned long)getULong (dp
));
1450 sprintf (op
, "%d", (int)getShort (dp
));
1454 sprintf (op
, "%d", (unsigned)getUShort (dp
));
1458 sprintf (op
, "%d", *(const char *)dp
++);
1462 sprintf (op
, "%d", *dp
++);
1465 sprintf (op
, "%x", *dp
++);
1468 strcpy (op
, *dp
++ ? "true" : "false");
1471 log_error ("Unexpected format code %c",
1475 if (dp
== data
+ len
)
1477 if (j
+ 1 < numelem
&& comma
!= ':')
1480 if (i
+ 1 < numhunk
) {
1483 if (dp
== data
+ len
)
1489 int get_option (result
, universe
, packet
, lease
, client_state
,
1490 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
1491 struct data_string
*result
;
1492 struct universe
*universe
;
1493 struct packet
*packet
;
1494 struct lease
*lease
;
1495 struct client_state
*client_state
;
1496 struct option_state
*in_options
;
1497 struct option_state
*cfg_options
;
1498 struct option_state
*options
;
1499 struct binding_scope
**scope
;
1504 struct option_cache
*oc
;
1506 if (!universe
-> lookup_func
)
1508 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
1511 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
1512 in_options
, cfg_options
, scope
, oc
,
1518 void set_option (universe
, options
, option
, op
)
1519 struct universe
*universe
;
1520 struct option_state
*options
;
1521 struct option_cache
*option
;
1522 enum statement_op op
;
1524 struct option_cache
*oc
, *noc
;
1529 case eval_statement
:
1530 case break_statement
:
1532 log_error ("bogus statement type in do_option_set.");
1535 case default_option_statement
:
1536 oc
= lookup_option (universe
, options
,
1537 option
-> option
-> code
);
1540 save_option (universe
, options
, option
);
1543 case supersede_option_statement
:
1544 case send_option_statement
:
1545 /* Install the option, replacing any existing version. */
1546 save_option (universe
, options
, option
);
1549 case append_option_statement
:
1550 case prepend_option_statement
:
1551 oc
= lookup_option (universe
, options
,
1552 option
-> option
-> code
);
1554 save_option (universe
, options
, option
);
1557 /* If it's not an expression, make it into one. */
1558 if (!oc
-> expression
&& oc
-> data
.len
) {
1559 if (!expression_allocate (&oc
-> expression
, MDL
)) {
1560 log_error ("Can't allocate const expression.");
1563 oc
-> expression
-> op
= expr_const_data
;
1565 (&oc
-> expression
-> data
.const_data
,
1567 data_string_forget (&oc
-> data
, MDL
);
1569 noc
= (struct option_cache
*)0;
1570 if (!option_cache_allocate (&noc
, MDL
))
1572 if (op
== append_option_statement
) {
1573 if (!make_concat (&noc
-> expression
,
1575 option
-> expression
)) {
1576 option_cache_dereference (&noc
, MDL
);
1580 if (!make_concat (&noc
-> expression
,
1581 option
-> expression
,
1582 oc
-> expression
)) {
1583 option_cache_dereference (&noc
, MDL
);
1587 noc
-> option
= oc
-> option
;
1588 save_option (universe
, options
, noc
);
1589 option_cache_dereference (&noc
, MDL
);
1594 struct option_cache
*lookup_option (universe
, options
, code
)
1595 struct universe
*universe
;
1596 struct option_state
*options
;
1600 return (struct option_cache
*)0;
1601 if (universe
-> lookup_func
)
1602 return (*universe
-> lookup_func
) (universe
, options
, code
);
1604 log_error ("can't look up options in %s space.",
1606 return (struct option_cache
*)0;
1609 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
1610 struct universe
*universe
;
1611 struct option_state
*options
;
1618 /* Make sure there's a hash table. */
1619 if (universe
-> index
>= options
-> universe_count
||
1620 !(options
-> universes
[universe
-> index
]))
1621 return (struct option_cache
*)0;
1623 hash
= options
-> universes
[universe
-> index
];
1625 hashix
= compute_option_hash (code
);
1626 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1627 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
1629 return (struct option_cache
*)(bptr
-> car
);
1631 return (struct option_cache
*)0;
1634 int save_option_buffer (struct universe
*universe
,
1635 struct option_state
*options
,
1637 unsigned char *buffer
, unsigned length
,
1638 struct option
*option
, int tp
)
1640 struct buffer
*lbp
= (struct buffer
*)0;
1641 struct option_cache
*op
= (struct option_cache
*)0;
1643 if (!option_cache_allocate (&op
, MDL
)) {
1644 log_error ("No memory for option %s.%s.",
1650 /* If we weren't passed a buffer in which the data are saved and
1651 refcounted, allocate one now. */
1653 if (!buffer_allocate (&lbp
, length
, MDL
)) {
1654 log_error ("no memory for option buffer.");
1656 option_cache_dereference (&op
, MDL
);
1659 memcpy (lbp
-> data
, buffer
, length
+ tp
);
1661 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
1664 /* Reference buffer copy to option cache. */
1665 op
-> data
.buffer
= (struct buffer
*)0;
1666 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
1668 /* Point option cache into buffer. */
1669 op
-> data
.data
= buffer
;
1670 op
-> data
.len
= length
;
1673 /* NUL terminate (we can get away with this because we (or
1674 the caller!) allocated one more than the buffer size, and
1675 because the byte following the end of an option is always
1676 the code of the next option, which the caller is getting
1677 out of the *original* buffer. */
1678 buffer
[length
] = 0;
1679 op
-> data
.terminated
= 1;
1681 op
-> data
.terminated
= 0;
1683 op
-> option
= option
;
1685 /* If this option is ultimately a text option, null determinate to
1686 * comply with RFC2132 section 2. Mark a flag so this can be sensed
1687 * later to echo NULLs back to clients that supplied them (they
1688 * probably expect them).
1690 if (format_has_text(option
->format
)) {
1691 int min_len
= format_min_length(option
->format
, op
);
1693 while ((op
->data
.len
> min_len
) &&
1694 (op
->data
.data
[op
->data
.len
-1] == '\0')) {
1696 op
->flags
|= OPTION_HAD_NULLS
;
1700 /* Now store the option. */
1701 save_option (universe
, options
, op
);
1703 /* And let go of our reference. */
1704 option_cache_dereference (&op
, MDL
);
1709 void save_option (struct universe
*universe
,
1710 struct option_state
*options
, struct option_cache
*oc
)
1712 if (universe
-> save_func
)
1713 (*universe
-> save_func
) (universe
, options
, oc
);
1715 log_error ("can't store options in %s space.",
1719 void save_hashed_option (universe
, options
, oc
)
1720 struct universe
*universe
;
1721 struct option_state
*options
;
1722 struct option_cache
*oc
;
1726 pair
*hash
= options
-> universes
[universe
-> index
];
1728 if (oc
-> refcnt
== 0)
1731 /* Compute the hash. */
1732 hashix
= compute_option_hash (oc
-> option
-> code
);
1734 /* If there's no hash table, make one. */
1736 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
1738 log_error ("no memory to store %s.%s",
1739 universe
-> name
, oc
-> option
-> name
);
1742 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
1743 options
-> universes
[universe
-> index
] = (VOIDPTR
)hash
;
1745 /* Try to find an existing option matching the new one. */
1746 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1747 if (((struct option_cache
*)
1748 (bptr
-> car
)) -> option
-> code
==
1749 oc
-> option
-> code
)
1753 /* If we find one, dereference it and put the new one
1756 option_cache_dereference
1757 ((struct option_cache
**)&bptr
-> car
, MDL
);
1758 option_cache_reference
1759 ((struct option_cache
**)&bptr
-> car
,
1765 /* Otherwise, just put the new one at the head of the list. */
1766 bptr
= new_pair (MDL
);
1768 log_error ("No memory for option_cache reference.");
1771 bptr
-> cdr
= hash
[hashix
];
1773 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
1774 hash
[hashix
] = bptr
;
1777 void delete_option (universe
, options
, code
)
1778 struct universe
*universe
;
1779 struct option_state
*options
;
1782 if (universe
-> delete_func
)
1783 (*universe
-> delete_func
) (universe
, options
, code
);
1785 log_error ("can't delete options from %s space.",
1789 void delete_hashed_option (universe
, options
, code
)
1790 struct universe
*universe
;
1791 struct option_state
*options
;
1795 pair bptr
, prev
= (pair
)0;
1796 pair
*hash
= options
-> universes
[universe
-> index
];
1798 /* There may not be any options in this space. */
1802 /* Try to find an existing option matching the new one. */
1803 hashix
= compute_option_hash (code
);
1804 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1805 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
1810 /* If we found one, wipe it out... */
1813 prev
-> cdr
= bptr
-> cdr
;
1815 hash
[hashix
] = bptr
-> cdr
;
1816 option_cache_dereference
1817 ((struct option_cache
**)(&bptr
-> car
), MDL
);
1818 free_pair (bptr
, MDL
);
1822 extern struct option_cache
*free_option_caches
; /* XXX */
1824 int option_cache_dereference (ptr
, file
, line
)
1825 struct option_cache
**ptr
;
1829 if (!ptr
|| !*ptr
) {
1830 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1832 #if defined (POINTER_DEBUG)
1840 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
1841 if (!(*ptr
) -> refcnt
) {
1842 if ((*ptr
) -> data
.buffer
)
1843 data_string_forget (&(*ptr
) -> data
, file
, line
);
1844 if ((*ptr
) -> expression
)
1845 expression_dereference (&(*ptr
) -> expression
,
1848 option_cache_dereference (&((*ptr
) -> next
),
1850 /* Put it back on the free list... */
1851 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
1852 free_option_caches
= *ptr
;
1853 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
1855 if ((*ptr
) -> refcnt
< 0) {
1856 log_error ("%s(%d): negative refcnt!", file
, line
);
1857 #if defined (DEBUG_RC_HISTORY)
1858 dump_rc_history (*ptr
);
1860 #if defined (POINTER_DEBUG)
1863 *ptr
= (struct option_cache
*)0;
1867 *ptr
= (struct option_cache
*)0;
1872 int hashed_option_state_dereference (universe
, state
, file
, line
)
1873 struct universe
*universe
;
1874 struct option_state
*state
;
1882 /* Get the pointer to the array of hash table bucket heads. */
1883 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
1887 /* For each non-null head, loop through all the buckets dereferencing
1888 the attached option cache structures and freeing the buckets. */
1889 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
1890 for (cp
= heads
[i
]; cp
; cp
= next
) {
1892 option_cache_dereference
1893 ((struct option_cache
**)&cp
-> car
,
1895 free_pair (cp
, file
, line
);
1899 dfree (heads
, file
, line
);
1900 state
-> universes
[universe
-> index
] = (void *)0;
1904 int store_option (result
, universe
, packet
, lease
, client_state
,
1905 in_options
, cfg_options
, scope
, oc
)
1906 struct data_string
*result
;
1907 struct universe
*universe
;
1908 struct packet
*packet
;
1909 struct lease
*lease
;
1910 struct client_state
*client_state
;
1911 struct option_state
*in_options
;
1912 struct option_state
*cfg_options
;
1913 struct binding_scope
**scope
;
1914 struct option_cache
*oc
;
1916 struct data_string d1
, d2
;
1918 memset (&d1
, 0, sizeof d1
);
1919 memset (&d2
, 0, sizeof d2
);
1921 if (evaluate_option_cache (&d2
, packet
, lease
, client_state
,
1922 in_options
, cfg_options
, scope
, oc
, MDL
)) {
1923 if (!buffer_allocate (&d1
.buffer
,
1925 universe
-> length_size
+
1926 universe
-> tag_size
+ d2
.len
), MDL
)) {
1927 data_string_forget (result
, MDL
);
1928 data_string_forget (&d2
, MDL
);
1931 d1
.data
= &d1
.buffer
-> data
[0];
1933 memcpy (d1
.buffer
-> data
,
1934 result
-> data
, result
-> len
);
1935 d1
.len
= result
-> len
;
1936 (*universe
-> store_tag
) (&d1
.buffer
-> data
[d1
.len
],
1937 oc
-> option
-> code
);
1938 d1
.len
+= universe
-> tag_size
;
1939 (*universe
-> store_length
) (&d1
.buffer
-> data
[d1
.len
],
1941 d1
.len
+= universe
-> length_size
;
1942 memcpy (&d1
.buffer
-> data
[d1
.len
], d2
.data
, d2
.len
);
1944 data_string_forget (&d2
, MDL
);
1945 data_string_forget (result
, MDL
);
1946 data_string_copy (result
, &d1
, MDL
);
1947 data_string_forget (&d1
, MDL
);
1953 int option_space_encapsulate (result
, packet
, lease
, client_state
,
1954 in_options
, cfg_options
, scope
, name
)
1955 struct data_string
*result
;
1956 struct packet
*packet
;
1957 struct lease
*lease
;
1958 struct client_state
*client_state
;
1959 struct option_state
*in_options
;
1960 struct option_state
*cfg_options
;
1961 struct binding_scope
**scope
;
1962 struct data_string
*name
;
1966 u
= (struct universe
*)0;
1967 universe_hash_lookup (&u
, universe_hash
,
1968 (const char *)name
-> data
, name
-> len
, MDL
);
1972 if (u
-> encapsulate
)
1973 return (*u
-> encapsulate
) (result
, packet
, lease
,
1975 in_options
, cfg_options
, scope
, u
);
1976 log_error ("encapsulation requested for %s with no support.",
1981 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
1982 in_options
, cfg_options
, scope
, universe
)
1983 struct data_string
*result
;
1984 struct packet
*packet
;
1985 struct lease
*lease
;
1986 struct client_state
*client_state
;
1987 struct option_state
*in_options
;
1988 struct option_state
*cfg_options
;
1989 struct binding_scope
**scope
;
1990 struct universe
*universe
;
1996 if (universe
-> index
>= cfg_options
-> universe_count
)
1999 hash
= cfg_options
-> universes
[universe
-> index
];
2004 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2005 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2006 if (store_option (result
, universe
, packet
,
2007 lease
, client_state
, in_options
,
2009 (struct option_cache
*)p
-> car
))
2017 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
2018 in_options
, cfg_options
, scope
, universe
)
2019 struct data_string
*result
;
2020 struct packet
*packet
;
2021 struct lease
*lease
;
2022 struct client_state
*client_state
;
2023 struct option_state
*in_options
;
2024 struct option_state
*cfg_options
;
2025 struct binding_scope
**scope
;
2026 struct universe
*universe
;
2031 static struct option_cache
*no_nwip
;
2032 struct data_string ds
;
2033 struct option_chain_head
*head
;
2035 if (universe
-> index
>= cfg_options
-> universe_count
)
2037 head
= ((struct option_chain_head
*)
2038 cfg_options
-> universes
[fqdn_universe
.index
]);
2043 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
2044 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
2045 if (store_option (result
, universe
, packet
,
2046 lease
, client_state
, in_options
,
2048 (struct option_cache
*)ocp
-> car
))
2052 /* If there's no data, the nwip suboption is supposed to contain
2053 a suboption saying there's no data. */
2056 static unsigned char nni
[] = { 1, 0 };
2057 memset (&ds
, 0, sizeof ds
);
2060 if (option_cache_allocate (&no_nwip
, MDL
))
2061 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
2062 no_nwip
-> option
= nwip_universe
.options
[1];
2065 if (store_option (result
, universe
, packet
, lease
,
2066 client_state
, in_options
,
2067 cfg_options
, scope
, no_nwip
))
2071 memset (&ds
, 0, sizeof ds
);
2073 /* If we have nwip options, the first one has to be the
2074 nwip-exists-in-option-area option. */
2075 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
2076 data_string_forget (result
, MDL
);
2079 ds
.data
= &ds
.buffer
-> data
[0];
2080 ds
.buffer
-> data
[0] = 2;
2081 ds
.buffer
-> data
[1] = 0;
2082 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
2083 data_string_forget (result
, MDL
);
2084 data_string_copy (result
, &ds
, MDL
);
2085 data_string_forget (&ds
, MDL
);
2091 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
2092 in_options
, cfg_options
, scope
, universe
)
2093 struct data_string
*result
;
2094 struct packet
*packet
;
2095 struct lease
*lease
;
2096 struct client_state
*client_state
;
2097 struct option_state
*in_options
;
2098 struct option_state
*cfg_options
;
2099 struct binding_scope
**scope
;
2100 struct universe
*universe
;
2103 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
2106 struct buffer
*bp
= (struct buffer
*)0;
2107 struct option_chain_head
*head
;
2109 /* If there's no FQDN universe, don't encapsulate. */
2110 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
2112 head
= ((struct option_chain_head
*)
2113 cfg_options
-> universes
[fqdn_universe
.index
]);
2117 /* Figure out the values of all the suboptions. */
2118 memset (results
, 0, sizeof results
);
2119 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
2120 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
2121 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
2123 evaluate_option_cache (&results
[oc
-> option
-> code
],
2124 packet
, lease
, client_state
, in_options
,
2125 cfg_options
, scope
, oc
, MDL
);
2127 len
= 4 + results
[FQDN_FQDN
].len
;
2128 /* Save the contents of the option in a buffer. */
2129 if (!buffer_allocate (&bp
, len
, MDL
)) {
2130 log_error ("no memory for option buffer.");
2133 buffer_reference (&result
-> buffer
, bp
, MDL
);
2135 result
-> data
= &bp
-> data
[0];
2137 memset (&bp
-> data
[0], 0, len
);
2138 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
2139 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
2140 bp
-> data
[0] |= 2;
2141 if (results
[FQDN_SERVER_UPDATE
].len
&&
2142 results
[FQDN_SERVER_UPDATE
].data
[0])
2143 bp
-> data
[0] |= 1;
2144 if (results
[FQDN_RCODE1
].len
)
2145 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
2146 if (results
[FQDN_RCODE2
].len
)
2147 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
2149 if (results
[FQDN_ENCODED
].len
&&
2150 results
[FQDN_ENCODED
].data
[0]) {
2153 bp
-> data
[0] |= 4;
2154 out
= &bp
-> data
[3];
2155 if (results
[FQDN_FQDN
].len
) {
2157 while (i
< results
[FQDN_FQDN
].len
) {
2160 results
[FQDN_FQDN
].data
[j
]) &&
2161 j
< results
[FQDN_FQDN
].len
; j
++)
2164 memcpy (out
, &results
[FQDN_FQDN
].data
[i
],
2168 if (results
[FQDN_FQDN
].data
[j
] == '.')
2171 if ((results
[FQDN_FQDN
].data
2172 [results
[FQDN_FQDN
].len
- 1] == '.'))
2174 result
-> len
= out
- result
-> data
;
2175 result
-> terminated
= 0;
2178 if (results
[FQDN_FQDN
].len
) {
2179 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
2180 results
[FQDN_FQDN
].len
);
2181 result
-> len
+= results
[FQDN_FQDN
].len
;
2182 result
-> terminated
= 0;
2185 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
2186 if (results
[i
].len
)
2187 data_string_forget (&results
[i
], MDL
);
2189 buffer_dereference (&bp
, MDL
);
2193 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2194 struct client_state
*client_state
,
2195 struct option_state
*in_options
,
2196 struct option_state
*cfg_options
,
2197 struct binding_scope
**scope
,
2198 struct universe
*u
, void *stuff
,
2199 void (*func
) (struct option_cache
*,
2201 struct lease
*, struct client_state
*,
2202 struct option_state
*,
2203 struct option_state
*,
2204 struct binding_scope
**,
2205 struct universe
*, void *))
2208 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
2209 cfg_options
, scope
, u
, stuff
, func
);
2212 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
2213 struct client_state
*client_state
,
2214 struct option_state
*in_options
,
2215 struct option_state
*cfg_options
,
2216 struct binding_scope
**scope
,
2217 struct universe
*u
, void *stuff
,
2218 void (*func
) (struct option_cache
*,
2220 struct lease
*, struct client_state
*,
2221 struct option_state
*,
2222 struct option_state
*,
2223 struct binding_scope
**,
2224 struct universe
*, void *),
2225 struct option_cache
*oc
,
2228 struct universe
*universe
= find_option_universe (oc
-> option
,
2232 if (universe
-> foreach
)
2233 (*universe
-> foreach
) (packet
, lease
, client_state
,
2234 in_options
, cfg_options
,
2235 scope
, universe
, stuff
, func
);
2238 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2239 struct client_state
*client_state
,
2240 struct option_state
*in_options
,
2241 struct option_state
*cfg_options
,
2242 struct binding_scope
**scope
,
2243 struct universe
*u
, void *stuff
,
2244 void (*func
) (struct option_cache
*,
2247 struct client_state
*,
2248 struct option_state
*,
2249 struct option_state
*,
2250 struct binding_scope
**,
2251 struct universe
*, void *))
2255 struct option_cache
*oc
;
2257 if (cfg_options
-> universe_count
<= u
-> index
)
2260 hash
= cfg_options
-> universes
[u
-> index
];
2263 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2265 /* XXX save _all_ options! XXX */
2266 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2267 oc
= (struct option_cache
*)p
-> car
;
2268 (*func
) (oc
, packet
, lease
, client_state
,
2269 in_options
, cfg_options
, scope
, u
, stuff
);
2274 void save_linked_option (universe
, options
, oc
)
2275 struct universe
*universe
;
2276 struct option_state
*options
;
2277 struct option_cache
*oc
;
2281 struct option_chain_head
*head
;
2283 if (universe
-> index
>= options
-> universe_count
)
2285 head
= ((struct option_chain_head
*)
2286 options
-> universes
[universe
-> index
]);
2288 if (!option_chain_head_allocate (((struct option_chain_head
**)
2289 &options
-> universes
2290 [universe
-> index
]), MDL
))
2292 head
= ((struct option_chain_head
*)
2293 options
-> universes
[universe
-> index
]);
2296 /* Find the tail of the list. */
2297 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
2299 ((struct option_cache
*)((*tail
) -> car
)) -> option
) {
2300 option_cache_dereference ((struct option_cache
**)
2301 (&(*tail
) -> car
), MDL
);
2302 option_cache_reference ((struct option_cache
**)
2303 (&(*tail
) -> car
), oc
, MDL
);
2308 *tail
= cons (0, 0);
2310 option_cache_reference ((struct option_cache
**)
2311 (&(*tail
) -> car
), oc
, MDL
);
2315 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
2316 in_options
, cfg_options
, scope
, universe
)
2317 struct data_string
*result
;
2318 struct packet
*packet
;
2319 struct lease
*lease
;
2320 struct client_state
*client_state
;
2321 struct option_state
*in_options
;
2322 struct option_state
*cfg_options
;
2323 struct binding_scope
**scope
;
2324 struct universe
*universe
;
2328 struct option_chain_head
*head
;
2330 if (universe
-> index
>= cfg_options
-> universe_count
)
2332 head
= ((struct option_chain_head
*)
2333 cfg_options
-> universes
[universe
-> index
]);
2338 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
2339 if (store_option (result
, universe
, packet
,
2340 lease
, client_state
, in_options
, cfg_options
,
2341 scope
, (struct option_cache
*)(oc
-> car
)))
2348 void delete_linked_option (universe
, options
, code
)
2349 struct universe
*universe
;
2350 struct option_state
*options
;
2353 pair
*tail
, tmp
= (pair
)0;
2354 struct option_chain_head
*head
;
2356 if (universe
-> index
>= options
-> universe_count
)
2358 head
= ((struct option_chain_head
*)
2359 options
-> universes
[universe
-> index
]);
2363 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
2365 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
2367 tmp
= (*tail
) -> cdr
;
2368 option_cache_dereference ((struct option_cache
**)
2369 (&(*tail
) -> car
), MDL
);
2377 struct option_cache
*lookup_linked_option (universe
, options
, code
)
2378 struct universe
*universe
;
2379 struct option_state
*options
;
2383 struct option_chain_head
*head
;
2385 if (universe
-> index
>= options
-> universe_count
)
2387 head
= ((struct option_chain_head
*)
2388 options
-> universes
[universe
-> index
]);
2392 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
2394 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
2395 return (struct option_cache
*)(oc
-> car
);
2399 return (struct option_cache
*)0;
2402 int linked_option_state_dereference (universe
, state
, file
, line
)
2403 struct universe
*universe
;
2404 struct option_state
*state
;
2408 return (option_chain_head_dereference
2409 ((struct option_chain_head
**)
2410 (&state
-> universes
[universe
-> index
]), MDL
));
2413 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2414 struct client_state
*client_state
,
2415 struct option_state
*in_options
,
2416 struct option_state
*cfg_options
,
2417 struct binding_scope
**scope
,
2418 struct universe
*u
, void *stuff
,
2419 void (*func
) (struct option_cache
*,
2422 struct client_state
*,
2423 struct option_state
*,
2424 struct option_state
*,
2425 struct binding_scope
**,
2426 struct universe
*, void *))
2429 struct option_chain_head
*head
;
2431 if (u
-> index
>= cfg_options
-> universe_count
)
2433 head
= ((struct option_chain_head
*)
2434 cfg_options
-> universes
[u
-> index
]);
2437 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
2438 (*func
) ((struct option_cache
*)(car
-> car
),
2439 packet
, lease
, client_state
,
2440 in_options
, cfg_options
, scope
, u
, stuff
);
2444 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
2445 struct interface_info
*interface
;
2446 struct dhcp_packet
*packet
;
2448 unsigned int from_port
;
2450 struct hardware
*hfrom
;
2453 struct option_cache
*op
;
2454 struct packet
*decoded_packet
;
2455 #if defined (DEBUG_MEMORY_LEAKAGE)
2456 unsigned long previous_outstanding
= dmalloc_outstanding
;
2459 #if defined (TRACING)
2460 trace_inpacket_stash (interface
, packet
, len
, from_port
, from
, hfrom
);
2463 decoded_packet
= (struct packet
*)0;
2464 if (!packet_allocate (&decoded_packet
, MDL
)) {
2465 log_error ("do_packet: no memory for incoming packet!");
2468 decoded_packet
-> raw
= packet
;
2469 decoded_packet
-> packet_length
= len
;
2470 decoded_packet
-> client_port
= from_port
;
2471 decoded_packet
-> client_addr
= from
;
2472 interface_reference (&decoded_packet
-> interface
, interface
, MDL
);
2473 decoded_packet
-> haddr
= hfrom
;
2475 if (packet
-> hlen
> sizeof packet
-> chaddr
) {
2476 packet_dereference (&decoded_packet
, MDL
);
2477 log_info ("Discarding packet with bogus hlen.");
2481 /* If there's an option buffer, try to parse it. */
2482 if (decoded_packet
-> packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
2483 if (!parse_options (decoded_packet
)) {
2484 if (decoded_packet
-> options
)
2485 option_state_dereference
2486 (&decoded_packet
-> options
, MDL
);
2487 packet_dereference (&decoded_packet
, MDL
);
2491 if (decoded_packet
-> options_valid
&&
2492 (op
= lookup_option (&dhcp_universe
,
2493 decoded_packet
-> options
,
2494 DHO_DHCP_MESSAGE_TYPE
))) {
2495 struct data_string dp
;
2496 memset (&dp
, 0, sizeof dp
);
2497 evaluate_option_cache (&dp
, decoded_packet
,
2499 (struct client_state
*)0,
2500 decoded_packet
-> options
,
2501 (struct option_state
*)0,
2502 (struct binding_scope
**)0,
2505 decoded_packet
-> packet_type
= dp
.data
[0];
2507 decoded_packet
-> packet_type
= 0;
2508 data_string_forget (&dp
, MDL
);
2512 if (decoded_packet
-> packet_type
)
2513 dhcp (decoded_packet
);
2515 bootp (decoded_packet
);
2517 /* If the caller kept the packet, they'll have upped the refcnt. */
2518 packet_dereference (&decoded_packet
, MDL
);
2520 #if defined (DEBUG_MEMORY_LEAKAGE)
2521 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2523 dmalloc_outstanding
- previous_outstanding
,
2524 dmalloc_outstanding
, dmalloc_longterm
);
2526 #if defined (DEBUG_MEMORY_LEAKAGE)
2527 dmalloc_dump_outstanding ();
2529 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2530 dump_rc_history (0);