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: options.c,v 1.6 2006/05/11 09:29:39 mrg Exp $ 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
;
46 /* Parse all available options out of the specified packet. */
48 int parse_options (packet
)
49 struct packet
*packet
;
51 struct option_cache
*op
= (struct option_cache
*)0;
53 /* Allocate a new option state. */
54 if (!option_state_allocate (&packet
-> options
, MDL
)) {
55 packet
-> options_valid
= 0;
59 /* If we don't see the magic cookie, there's nothing to parse. */
60 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
61 packet
-> options_valid
= 0;
65 /* Go through the options field, up to the end of the packet
67 if (!parse_option_buffer (packet
-> options
,
68 &packet
-> raw
-> options
[4],
69 (packet
-> packet_length
-
70 DHCP_FIXED_NON_UDP
- 4),
74 /* If we parsed a DHCP Option Overload option, parse more
75 options out of the buffer(s) containing them. */
76 if (packet
-> options_valid
&&
77 (op
= lookup_option (&dhcp_universe
, packet
-> options
,
78 DHO_DHCP_OPTION_OVERLOAD
))) {
79 if (op
-> data
.data
[0] & 1) {
80 if (!parse_option_buffer
82 (unsigned char *)packet
-> raw
-> file
,
83 sizeof packet
-> raw
-> file
,
87 if (op
-> data
.data
[0] & 2) {
88 if (!parse_option_buffer
90 (unsigned char *)packet
-> raw
-> sname
,
91 sizeof packet
-> raw
-> sname
,
96 packet
-> options_valid
= 1;
100 /* Parse options out of the specified buffer, storing addresses of option
101 values in packet -> options and setting packet -> options_valid if no
102 errors are encountered. */
104 int parse_option_buffer (options
, buffer
, length
, universe
)
105 struct option_state
*options
;
106 const unsigned char *buffer
;
108 struct universe
*universe
;
110 unsigned len
, offset
;
112 struct option_cache
*op
= (struct option_cache
*)0;
113 struct buffer
*bp
= (struct buffer
*)0;
115 if (!buffer_allocate (&bp
, length
, MDL
)) {
116 log_error ("no memory for option buffer.");
119 memcpy (bp
-> data
, buffer
, length
);
121 for (offset
= 0; buffer
[offset
] != DHO_END
&& offset
< length
; ) {
122 code
= buffer
[offset
];
123 /* Pad options don't have a length - just skip them. */
124 if (code
== DHO_PAD
) {
129 /* Don't look for length if the buffer isn't that big. */
130 if (offset
+ 2 > length
) {
135 /* All other fields (except end, see above) have a
137 len
= buffer
[offset
+ 1];
139 /* If the length is outrageous, the options are bad. */
140 if (offset
+ len
+ 2 > length
) {
142 log_error ("parse_option_buffer: option %s (%d) %s.",
143 dhcp_options
[code
].name
, len
,
144 "larger than buffer");
145 buffer_dereference (&bp
, MDL
);
149 /* If the option contains an encapsulation, parse it. If
150 the parse fails, or the option isn't an encapsulation (by
151 far the most common case), or the option isn't entirely
152 an encapsulation, keep the raw data as well. */
153 if (universe
-> options
[code
] &&
154 !((universe
-> options
[code
] -> format
[0] == 'e' ||
155 universe
-> options
[code
] -> format
[0] == 'E') &&
156 (parse_encapsulated_suboptions
157 (options
, universe
-> options
[code
],
158 buffer
+ offset
+ 2, len
,
159 universe
, (const char *)0)))) {
160 op
= lookup_option (universe
, options
, code
);
162 struct data_string
new;
163 memset (&new, 0, sizeof new);
164 if (!buffer_allocate (&new.buffer
, op
-> data
.len
+ len
,
166 log_error ("parse_option_buffer: No memory.");
169 memcpy (new.buffer
-> data
, op
-> data
.data
,
171 memcpy (&new.buffer
-> data
[op
-> data
.len
],
172 &bp
-> data
[offset
+ 2], len
);
173 new.len
= op
-> data
.len
+ len
;
174 new.data
= new.buffer
-> data
;
175 data_string_forget (&op
-> data
, MDL
);
176 data_string_copy (&op
-> data
, &new, MDL
);
177 data_string_forget (&new, MDL
);
179 save_option_buffer (universe
, options
, bp
,
180 &bp
-> data
[offset
+ 2], len
,
181 universe
-> options
[code
], 1);
186 buffer_dereference (&bp
, MDL
);
190 /* If an option in an option buffer turns out to be an encapsulation,
191 figure out what to do. If we don't know how to de-encapsulate it,
192 or it's not well-formed, return zero; otherwise, return 1, indicating
193 that we succeeded in de-encapsulating it. */
195 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
199 struct universe
*universe
= (struct universe
*)0;
201 /* Look for the E option in the option format. */
202 s
= strchr (eopt
-> format
, 'E');
204 log_error ("internal encapsulation format error 1.");
207 /* Look for the universe name in the option format. */
208 t
= strchr (++s
, '.');
209 /* If there was no trailing '.', or there's something after the
210 trailing '.', the option is bogus and we can't use it. */
212 log_error ("internal encapsulation format error 2.");
215 if (t
== s
&& uname
) {
216 for (i
= 0; i
< universe_count
; i
++) {
217 if (!strcmp (universes
[i
] -> name
, uname
)) {
218 universe
= universes
[i
];
223 for (i
= 0; i
< universe_count
; i
++) {
224 if (strlen (universes
[i
] -> name
) == t
- s
&&
225 !memcmp (universes
[i
] -> name
,
226 s
, (unsigned)(t
- s
))) {
227 universe
= universes
[i
];
235 /* If an option in an option buffer turns out to be an encapsulation,
236 figure out what to do. If we don't know how to de-encapsulate it,
237 or it's not well-formed, return zero; otherwise, return 1, indicating
238 that we succeeded in de-encapsulating it. */
240 int parse_encapsulated_suboptions (struct option_state
*options
,
242 const unsigned char *buffer
,
243 unsigned len
, struct universe
*eu
,
247 struct universe
*universe
= find_option_universe (eopt
, uname
);
249 /* If we didn't find the universe, we can't do anything with it
250 right now (e.g., we can't decode vendor options until we've
251 decoded the packet and executed the scopes that it matches). */
255 /* If we don't have a decoding function for it, we can't decode
257 if (!universe
-> decode
)
260 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
262 /* If there is stuff before the suboptions, we have to keep it. */
263 if (eopt
-> format
[0] != 'E')
265 /* Otherwise, return the status of the decode function. */
269 int fqdn_universe_decode (struct option_state
*options
,
270 const unsigned char *buffer
,
271 unsigned length
, struct universe
*u
)
273 struct buffer
*bp
= (struct buffer
*)0;
275 /* FQDN options have to be at least four bytes long. */
279 /* Save the contents of the option in a buffer. */
280 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
281 log_error ("no memory for option buffer.");
284 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
286 if (buffer
[0] & 4) /* encoded */
290 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
292 &fqdn_options
[FQDN_ENCODED
], 0)) {
294 buffer_dereference (&bp
, MDL
);
298 if (buffer
[0] & 1) /* server-update */
302 if (buffer
[0] & 2) /* no-client-update */
307 /* XXX Ideally we should store the name in DNS format, so if the
308 XXX label isn't in DNS format, we convert it to DNS format,
309 XXX rather than converting labels specified in DNS format to
310 XXX the plain ASCII representation. But that's hard, so
313 /* Not encoded using DNS format? */
314 if (!bp
-> data
[0]) {
317 /* Some broken clients NUL-terminate this option. */
318 if (buffer
[length
- 1] == 0) {
323 /* Determine the length of the hostname component of the
324 name. If the name contains no '.' character, it
325 represents a non-qualified label. */
326 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
329 /* Note: If the client sends a FQDN, the first '.' will
330 be used as a NUL terminator for the hostname. */
332 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
334 &fqdn_options
[FQDN_HOSTNAME
],
337 /* Note: If the client sends a single label, the
338 FQDN_DOMAINNAME option won't be set. */
339 if (length
> 4 + i
&&
340 !save_option_buffer (&fqdn_universe
, options
, bp
,
341 &bp
-> data
[6 + i
], length
- 4 - i
,
342 &fqdn_options
[FQDN_DOMAINNAME
], 1))
344 /* Also save the whole name. */
346 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
347 &bp
-> data
[5], length
- 3,
348 &fqdn_options
[FQDN_FQDN
], 1))
352 unsigned total_len
= 0;
353 unsigned first_len
= 0;
359 while (s
< &bp
-> data
[0] + length
+ 2) {
362 log_info ("fancy bits in fqdn option");
369 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
370 log_info ("fqdn tag longer than buffer");
374 if (first_len
== 0) {
380 total_len
+= len
+ 1;
383 /* We wind up with a length that's one too many because
384 we shouldn't increment for the last label, but there's
385 no way to tell we're at the last label until we exit
391 first_len
= total_len
;
395 !save_option_buffer (&fqdn_universe
, options
, bp
,
396 &bp
-> data
[6], first_len
,
397 &fqdn_options
[FQDN_HOSTNAME
], 0))
399 if (total_len
> 0 && first_len
!= total_len
) {
400 if (!save_option_buffer
401 (&fqdn_universe
, options
, bp
,
402 &bp
-> data
[6 + first_len
], total_len
- first_len
,
403 &fqdn_options
[FQDN_DOMAINNAME
], 1))
407 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
408 &bp
-> data
[6], total_len
,
409 &fqdn_options
[FQDN_FQDN
], 1))
413 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
415 &fqdn_options
[FQDN_NO_CLIENT_UPDATE
], 0))
417 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
419 &fqdn_options
[FQDN_SERVER_UPDATE
], 0))
422 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
424 &fqdn_options
[FQDN_RCODE1
], 0))
426 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
428 &fqdn_options
[FQDN_RCODE2
], 0))
431 buffer_dereference (&bp
, MDL
);
435 /* cons options into a big buffer, and then split them out into the
436 three seperate buffers if needed. This allows us to cons up a set
437 of vendor options using the same routine. */
439 int cons_options (inpacket
, outpacket
, lease
, client_state
,
440 mms
, in_options
, cfg_options
,
441 scope
, overload
, terminate
, bootpp
, prl
, vuname
)
442 struct packet
*inpacket
;
443 struct dhcp_packet
*outpacket
;
445 struct client_state
*client_state
;
447 struct option_state
*in_options
;
448 struct option_state
*cfg_options
;
449 struct binding_scope
**scope
;
450 int overload
; /* Overload flags that may be set. */
453 struct data_string
*prl
;
456 #define PRIORITY_COUNT 300
457 unsigned priority_list
[PRIORITY_COUNT
];
459 unsigned char buffer
[4096]; /* Really big buffer... */
460 unsigned main_buffer_size
;
461 unsigned mainbufix
, bufix
, agentix
;
464 unsigned option_size
;
467 struct option_cache
*op
;
468 struct data_string ds
;
472 int ofbuf1
=0, ofbuf2
=0;
474 memset (&ds
, 0, sizeof ds
);
476 /* If there's a Maximum Message Size option in the incoming packet
477 and no alternate maximum message size has been specified, take the
478 one in the packet. */
481 (op
= lookup_option (&dhcp_universe
, inpacket
-> options
,
482 DHO_DHCP_MAX_MESSAGE_SIZE
))) {
483 evaluate_option_cache (&ds
, inpacket
,
484 lease
, client_state
, in_options
,
485 cfg_options
, scope
, op
, MDL
);
486 if (ds
.len
>= sizeof (u_int16_t
)) {
487 i
= getUShort (ds
.data
);
489 if(!mms
|| (i
< mms
))
492 data_string_forget (&ds
, MDL
);
495 /* If the client has provided a maximum DHCP message size,
496 use that; otherwise, if it's BOOTP, only 64 bytes; otherwise
497 use up to the minimum IP MTU size (576 bytes). */
498 /* XXX if a BOOTP client specifies a max message size, we will
502 main_buffer_size
= mms
- DHCP_FIXED_LEN
;
504 /* Enforce a minimum packet size... */
505 if (main_buffer_size
< (576 - DHCP_FIXED_LEN
))
506 main_buffer_size
= 576 - DHCP_FIXED_LEN
;
510 inpacket
-> packet_length
- DHCP_FIXED_LEN
;
511 if (main_buffer_size
< 64)
512 main_buffer_size
= 64;
514 main_buffer_size
= 64;
516 main_buffer_size
= 576 - DHCP_FIXED_LEN
;
518 /* Set a hard limit at the size of the output buffer. */
519 if (main_buffer_size
> sizeof buffer
)
520 main_buffer_size
= sizeof buffer
;
522 /* Preload the option priority list with mandatory options. */
524 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
525 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
526 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
527 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
528 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
529 priority_list
[priority_len
++] = DHO_FQDN
;
531 if (prl
&& prl
-> len
> 0) {
532 if ((op
= lookup_option (&dhcp_universe
, cfg_options
,
533 DHO_SUBNET_SELECTION
))) {
534 if (priority_len
< PRIORITY_COUNT
)
535 priority_list
[priority_len
++] =
536 DHO_SUBNET_SELECTION
;
539 data_string_truncate (prl
, (PRIORITY_COUNT
- priority_len
));
541 for (i
= 0; i
< prl
-> len
; i
++) {
542 /* Prevent client from changing order of delivery
543 of relay agent information option. */
544 if (prl
-> data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
545 priority_list
[priority_len
++] =
549 /* First, hardcode some more options that ought to be
551 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
552 priority_list
[priority_len
++] = DHO_ROUTERS
;
553 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
554 priority_list
[priority_len
++] = DHO_HOST_NAME
;
556 /* Append a list of the standard DHCP options from the
557 standard DHCP option space. Actually, if a site
558 option space hasn't been specified, we wind up
559 treating the dhcp option space as the site option
560 space, and the first for loop is skipped, because
561 it's slightly more general to do it this way,
562 taking the 1Q99 DHCP futures work into account. */
563 if (cfg_options
-> site_code_min
) {
564 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
565 hash
= cfg_options
-> universes
[dhcp_universe
.index
];
567 for (pp
= hash
[i
]; pp
; pp
= pp
-> cdr
) {
568 op
= (struct option_cache
*)(pp
-> car
);
569 if (op
-> option
-> code
<
570 cfg_options
-> site_code_min
&&
571 priority_len
< PRIORITY_COUNT
&&
572 (op
-> option
-> code
!=
573 DHO_DHCP_AGENT_OPTIONS
))
574 priority_list
[priority_len
++] =
575 op
-> option
-> code
;
581 /* Now cycle through the site option space, or if there
582 is no site option space, we'll be cycling through the
583 dhcp option space. */
584 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
585 hash
= (cfg_options
-> universes
586 [cfg_options
-> site_universe
]);
588 for (pp
= hash
[i
]; pp
; pp
= pp
-> cdr
) {
589 op
= (struct option_cache
*)(pp
-> car
);
590 if (op
-> option
-> code
>=
591 cfg_options
-> site_code_min
&&
592 priority_len
< PRIORITY_COUNT
&&
593 (op
-> option
-> code
!=
594 DHO_DHCP_AGENT_OPTIONS
))
595 priority_list
[priority_len
++] =
596 op
-> option
-> code
;
600 /* Now go through all the universes for which options
601 were set and see if there are encapsulations for
602 them; if there are, put the encapsulation options
603 on the priority list as well. */
604 for (i
= 0; i
< cfg_options
-> universe_count
; i
++) {
605 if (cfg_options
-> universes
[i
] &&
606 universes
[i
] -> enc_opt
&&
607 priority_len
< PRIORITY_COUNT
&&
608 universes
[i
] -> enc_opt
-> universe
== &dhcp_universe
)
610 if (universes
[i
] -> enc_opt
-> code
!=
611 DHO_DHCP_AGENT_OPTIONS
)
612 priority_list
[priority_len
++] =
613 universes
[i
] -> enc_opt
-> code
;
617 /* The vendor option space can't stand on its own, so always
618 add it to the list. */
619 if (priority_len
< PRIORITY_COUNT
)
620 priority_list
[priority_len
++] =
621 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
624 /* Figure out the overload buffer offset(s). */
626 ofbuf1
= main_buffer_size
- 4;
628 ofbuf2
= main_buffer_size
- 4 + DHCP_FILE_LEN
;
631 /* Copy the options into the big buffer... */
632 option_size
= store_options (&ocount
, buffer
,
633 (main_buffer_size
- 4 +
634 ((overload
& 1) ? DHCP_FILE_LEN
: 0) +
635 ((overload
& 2) ? DHCP_SNAME_LEN
: 0)),
636 inpacket
, lease
, client_state
,
637 in_options
, cfg_options
, scope
,
638 priority_list
, priority_len
,
639 ofbuf1
, ofbuf2
, terminate
, vuname
);
640 /* If store_options failed. */
641 if (option_size
== 0)
644 if (ocount
== 1 && (overload
& 1))
646 else if (ocount
== 1 && (overload
& 2))
648 else if (ocount
== 3)
654 /* Put the cookie up front... */
655 memcpy (outpacket
-> options
, DHCP_OPTIONS_COOKIE
, 4);
658 /* If we're going to have to overload, store the overload
659 option at the beginning. If we can, though, just store the
660 whole thing in the packet's option buffer and leave it at
662 memcpy (&outpacket
-> options
[mainbufix
],
663 buffer
, option_size
);
664 mainbufix
+= option_size
;
666 outpacket
-> options
[mainbufix
++] = DHO_DHCP_OPTION_OVERLOAD
;
667 outpacket
-> options
[mainbufix
++] = 1;
668 outpacket
-> options
[mainbufix
++] = overload
;
671 memcpy (outpacket
-> file
,
672 &buffer
[ofbuf1
], DHCP_FILE_LEN
);
676 memcpy (outpacket
-> sname
, &buffer
[ofbuf2
],
679 memcpy (outpacket
-> sname
, &buffer
[ofbuf1
],
685 if (mainbufix
< main_buffer_size
)
687 length
= DHCP_FIXED_NON_UDP
+ mainbufix
;
689 /* Now hack in the agent options if there are any. */
690 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
693 store_options (0, &outpacket
-> options
[agentix
],
694 1500 - DHCP_FIXED_LEN
- agentix
,
695 inpacket
, lease
, client_state
,
696 in_options
, cfg_options
, scope
,
697 priority_list
, priority_len
,
700 /* Tack a DHO_END option onto the packet if we need to. */
701 if (agentix
< 1500 - DHCP_FIXED_LEN
&& need_endopt
)
702 outpacket
-> options
[agentix
++] = DHO_END
;
704 /* Figure out the length. */
705 length
= DHCP_FIXED_NON_UDP
+ agentix
;
709 /* Store all the requested options into the requested buffer. */
711 int store_options (ocount
, buffer
, buflen
, packet
, lease
, client_state
,
712 in_options
, cfg_options
, scope
, priority_list
, priority_len
,
713 first_cutoff
, second_cutoff
, terminate
, vuname
)
715 unsigned char *buffer
;
717 struct packet
*packet
;
719 struct client_state
*client_state
;
720 struct option_state
*in_options
;
721 struct option_state
*cfg_options
;
722 struct binding_scope
**scope
;
723 unsigned *priority_list
;
725 unsigned first_cutoff
, second_cutoff
;
729 int bufix
= 0, six
= 0, tix
= 0;
734 struct data_string od
;
735 struct option_cache
*oc
;
739 if (first_cutoff
>= buflen
)
740 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
742 bufend
= first_cutoff
;
747 if (second_cutoff
>= buflen
)
748 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
750 sbufend
= second_cutoff
;
754 memset (&od
, 0, sizeof od
);
756 /* Eliminate duplicate options in the parameter request list.
757 There's got to be some clever knuthian way to do this:
758 Eliminate all but the first occurance of a value in an array
759 of values without otherwise disturbing the order of the array. */
760 for (i
= 0; i
< priority_len
- 1; i
++) {
762 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
764 priority_list
[ix
- tto
] =
766 if (priority_list
[i
] == priority_list
[ix
]) {
773 /* Copy out the options in the order that they appear in the
775 for (i
= 0; i
< priority_len
; i
++) {
776 /* Number of bytes left to store (some may already
777 have been stored by a previous pass). */
779 int optstart
, soptstart
, toptstart
;
781 int have_encapsulation
= 0;
782 struct data_string encapsulation
;
785 memset (&encapsulation
, 0, sizeof encapsulation
);
787 /* Code for next option to try to store. */
788 code
= priority_list
[i
];
790 /* Look up the option in the site option space if the code
791 is above the cutoff, otherwise in the DHCP option space. */
792 if (code
>= cfg_options
-> site_code_min
)
793 u
= universes
[cfg_options
-> site_universe
];
797 oc
= lookup_option (u
, cfg_options
, code
);
799 /* It's an encapsulation, try to find the universe
800 to be encapsulated first, except that if it's a straight
801 encapsulation and the user has provided a value for the
802 encapsulation option, use the user-provided value. */
803 if (u
-> options
[code
] &&
804 ((u
-> options
[code
] -> format
[0] == 'E' && !oc
) ||
805 u
-> options
[code
] -> format
[0] == 'e')) {
807 struct option_cache
*tmp
;
808 struct data_string name
;
810 s
= strchr (u
-> options
[code
] -> format
, 'E');
812 t
= strchr (++s
, '.');
814 memset (&name
, 0, sizeof name
);
816 /* A zero-length universe name means the vendor
817 option space, if one is defined. */
819 if (vendor_cfg_option
) {
820 tmp
= lookup_option (vendor_cfg_option
-> universe
,
822 vendor_cfg_option
-> code
);
824 evaluate_option_cache (&name
, packet
, lease
,
830 name
.data
= (unsigned char *)s
;
831 name
.len
= strlen (s
);
834 name
.data
= (unsigned char *)s
;
838 /* If we found a universe, and there are options configured
839 for that universe, try to encapsulate it. */
842 (option_space_encapsulate
843 (&encapsulation
, packet
, lease
, client_state
,
844 in_options
, cfg_options
, scope
, &name
));
845 data_string_forget (&name
, MDL
);
850 /* In order to avoid memory leaks, we have to get to here
851 with any option cache that we allocated in tmp not being
852 referenced by tmp, and whatever option cache is referenced
853 by oc being an actual reference. lookup_option doesn't
854 generate a reference (this needs to be fixed), so the
855 preceding goop ensures that if we *didn't* generate a new
856 option cache, oc still winds up holding an actual reference. */
858 /* If no data is available for this option, skip it. */
859 if (!oc
&& !have_encapsulation
) {
863 /* Find the value of the option... */
865 evaluate_option_cache (&od
, packet
,
866 lease
, client_state
, in_options
,
867 cfg_options
, scope
, oc
, MDL
);
869 data_string_forget (&encapsulation
, MDL
);
870 data_string_forget (&od
, MDL
);
871 have_encapsulation
= 0;
876 /* We should now have a constant length for the option. */
878 if (have_encapsulation
) {
879 length
+= encapsulation
.len
;
881 data_string_copy (&od
, &encapsulation
, MDL
);
882 data_string_forget (&encapsulation
, MDL
);
884 struct buffer
*bp
= (struct buffer
*)0;
885 if (!buffer_allocate (&bp
, length
, MDL
)) {
886 option_cache_dereference (&oc
, MDL
);
887 data_string_forget (&od
, MDL
);
888 data_string_forget (&encapsulation
, MDL
);
891 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
892 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
894 data_string_forget (&od
, MDL
);
895 data_string_forget (&encapsulation
, MDL
);
896 od
.data
= &bp
-> data
[0];
897 buffer_reference (&od
.buffer
, bp
, MDL
);
898 buffer_dereference (&bp
, MDL
);
904 /* Do we add a NUL? */
905 if (terminate
&& dhcp_options
[code
].format
[0] == 't') {
912 /* Try to store the option. */
914 /* If the option's length is more than 255, we must store it
915 in multiple hunks. Store 255-byte hunks first. However,
916 in any case, if the option data will cross a buffer
917 boundary, split it across that boundary. */
930 unsigned incr
= length
;
934 /* Try to fit it in the options buffer. */
936 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
937 (bufix
+ 2 + length
< bufend
)) ||
938 (bufix
+ 5 + length
< bufend
))) {
941 /* Try to fit it in the second buffer. */
942 } else if (!splitup
&& first_cutoff
&&
943 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
944 base
= &buffer
[first_cutoff
];
946 /* Try to fit it in the third buffer. */
947 } else if (!splitup
&& second_cutoff
&&
948 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
949 base
= &buffer
[second_cutoff
];
951 /* Split the option up into the remaining space. */
955 /* Use any remaining options space. */
956 if (bufix
+ 6 < bufend
) {
957 incr
= bufend
- bufix
- 5;
960 /* Use any remaining first_cutoff space. */
961 } else if (first_cutoff
&&
962 (first_cutoff
+ six
+ 4 < sbufend
)) {
963 incr
= sbufend
- (first_cutoff
+ six
) - 3;
964 base
= &buffer
[first_cutoff
];
966 /* Use any remaining second_cutoff space. */
967 } else if (second_cutoff
&&
968 (second_cutoff
+ tix
+ 4 < buflen
)) {
969 incr
= buflen
- (second_cutoff
+ tix
) - 3;
970 base
= &buffer
[second_cutoff
];
972 /* Give up, roll back this option. */
986 /* Everything looks good - copy it in! */
988 base
[*pix
+ 1] = (unsigned char)incr
;
989 if (tto
&& incr
== length
) {
991 memcpy (base
+ *pix
+ 2,
992 od
.data
+ ix
, (unsigned)(incr
- 1));
993 base
[*pix
+ 2 + incr
- 1] = 0;
995 memcpy (base
+ *pix
+ 2,
996 od
.data
+ ix
, (unsigned)incr
);
1002 data_string_forget (&od
, MDL
);
1005 /* If we can overload, and we have, then PAD and END those spaces. */
1006 if (first_cutoff
&& six
) {
1007 if ((first_cutoff
+ six
+ 1) < sbufend
)
1008 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1009 sbufend
- (first_cutoff
+ six
+ 1));
1010 else if (first_cutoff
+ six
>= sbufend
)
1011 log_fatal("Second buffer overflow in overloaded options.");
1013 buffer
[first_cutoff
+ six
] = DHO_END
;
1014 *ocount
|= 1; /* So that caller knows there's data there. */
1017 if (second_cutoff
&& tix
) {
1018 if (second_cutoff
+ tix
+ 1 < buflen
) {
1019 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1020 buflen
- (second_cutoff
+ tix
+ 1));
1021 } else if (second_cutoff
+ tix
>= buflen
)
1022 log_fatal("Third buffer overflow in overloaded options.");
1024 buffer
[second_cutoff
+ tix
] = DHO_END
;
1025 *ocount
|= 2; /* So that caller knows there's data there. */
1028 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1029 log_fatal("Not enough space for option overload option.");
1034 /* Format the specified option so that a human can easily read it. */
1036 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1037 struct option
*option
;
1038 const unsigned char *data
;
1043 static char optbuf
[32768]; /* XXX */
1050 struct enumeration
*enumbuf
[32];
1053 const unsigned char *dp
= data
;
1063 memset (enumbuf
, 0, sizeof enumbuf
);
1065 /* Figure out the size of the data. */
1066 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1068 log_error ("%s: Extra codes in format string: %s",
1070 &(option
-> format
[i
]));
1074 fmtbuf
[l
] = option
-> format
[i
];
1075 switch (option
-> format
[i
]) {
1087 /* Skip the universe name. */
1088 while (option
-> format
[i
] &&
1089 option
-> format
[i
] != '.')
1092 for (k
= 0; k
< len
; k
++) {
1093 if (!isascii (data
[k
]) ||
1094 !isprint (data
[k
]))
1097 /* If we found no bogus characters, or the bogus
1098 character we found is a trailing NUL, it's
1099 okay to print this option as text. */
1100 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1119 while (option
-> format
[i
] &&
1120 option
-> format
[i
] != '.')
1123 find_enumeration (&option
-> format
[k
] + 1,
1152 log_error ("%s: garbage in format string: %s",
1154 &(option
-> format
[i
]));
1159 /* Check for too few bytes... */
1160 if (hunksize
- opthunk
> len
) {
1161 log_error ("%s: expecting at least %d bytes; got %d",
1166 /* Check for too many bytes... */
1167 if (numhunk
== -1 && hunksize
< len
)
1168 log_error ("%s: %d extra bytes",
1172 /* If this is an array, compute its size. */
1174 numhunk
= len
/ hunksize
;
1175 /* See if we got an exact number of hunks. */
1176 if (numhunk
> 0 && numhunk
* hunksize
< len
)
1177 log_error ("%s: %d extra bytes at end of array\n",
1179 len
- numhunk
* hunksize
);
1181 /* A one-hunk array prints the same as a single hunk. */
1185 /* Cycle through the array (or hunk) printing the data. */
1186 for (i
= 0; i
< numhunk
; i
++) {
1187 for (j
= 0; j
< numelem
; j
++) {
1188 switch (fmtbuf
[j
]) {
1192 for (; dp
< data
+ len
; dp
++) {
1193 if (!isascii (*dp
) ||
1195 /* Skip trailing NUL. */
1196 if (dp
+ 1 != data
+ len
||
1198 sprintf (op
, "\\%03o",
1202 } else if (*dp
== '"' ||
1216 /* pretty-printing an array of enums is
1217 going to get ugly. */
1222 if (!enumbuf
[j
] -> values
[i
].name
)
1224 if (enumbuf
[j
] -> values
[i
].value
==
1228 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
1232 foo
.s_addr
= htonl (getULong (dp
));
1233 strcpy (op
, inet_ntoa (foo
));
1237 sprintf (op
, "%ld", (long)getLong (dp
));
1241 tval
= getULong (dp
);
1243 sprintf (op
, "%s", "infinite");
1245 sprintf (op
, "%ld", tval
);
1249 (unsigned long)getULong (dp
));
1253 sprintf (op
, "%d", (int)getShort (dp
));
1257 sprintf (op
, "%d", (unsigned)getUShort (dp
));
1261 sprintf (op
, "%d", *(const char *)dp
++);
1265 sprintf (op
, "%d", *dp
++);
1268 sprintf (op
, "%x", *dp
++);
1271 strcpy (op
, *dp
++ ? "true" : "false");
1274 log_error ("Unexpected format code %c",
1278 if (dp
== data
+ len
)
1280 if (j
+ 1 < numelem
&& comma
!= ':')
1283 if (i
+ 1 < numhunk
) {
1286 if (dp
== data
+ len
)
1292 int get_option (result
, universe
, packet
, lease
, client_state
,
1293 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
1294 struct data_string
*result
;
1295 struct universe
*universe
;
1296 struct packet
*packet
;
1297 struct lease
*lease
;
1298 struct client_state
*client_state
;
1299 struct option_state
*in_options
;
1300 struct option_state
*cfg_options
;
1301 struct option_state
*options
;
1302 struct binding_scope
**scope
;
1307 struct option_cache
*oc
;
1309 if (!universe
-> lookup_func
)
1311 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
1314 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
1315 in_options
, cfg_options
, scope
, oc
,
1321 void set_option (universe
, options
, option
, op
)
1322 struct universe
*universe
;
1323 struct option_state
*options
;
1324 struct option_cache
*option
;
1325 enum statement_op op
;
1327 struct option_cache
*oc
, *noc
;
1332 case eval_statement
:
1333 case break_statement
:
1335 log_error ("bogus statement type in set_option.");
1338 case default_option_statement
:
1339 oc
= lookup_option (universe
, options
,
1340 option
-> option
-> code
);
1343 save_option (universe
, options
, option
);
1346 case supersede_option_statement
:
1347 case send_option_statement
:
1348 /* Install the option, replacing any existing version. */
1349 save_option (universe
, options
, option
);
1352 case append_option_statement
:
1353 case prepend_option_statement
:
1354 oc
= lookup_option (universe
, options
,
1355 option
-> option
-> code
);
1357 save_option (universe
, options
, option
);
1360 /* If it's not an expression, make it into one. */
1361 if (!oc
-> expression
&& oc
-> data
.len
) {
1362 if (!expression_allocate (&oc
-> expression
, MDL
)) {
1363 log_error ("Can't allocate const expression.");
1366 oc
-> expression
-> op
= expr_const_data
;
1368 (&oc
-> expression
-> data
.const_data
,
1370 data_string_forget (&oc
-> data
, MDL
);
1372 noc
= (struct option_cache
*)0;
1373 if (!option_cache_allocate (&noc
, MDL
))
1375 if (op
== append_option_statement
) {
1376 if (!make_concat (&noc
-> expression
,
1378 option
-> expression
)) {
1379 option_cache_dereference (&noc
, MDL
);
1383 if (!make_concat (&noc
-> expression
,
1384 option
-> expression
,
1385 oc
-> expression
)) {
1386 option_cache_dereference (&noc
, MDL
);
1390 noc
-> option
= oc
-> option
;
1391 save_option (universe
, options
, noc
);
1392 option_cache_dereference (&noc
, MDL
);
1397 struct option_cache
*lookup_option (universe
, options
, code
)
1398 struct universe
*universe
;
1399 struct option_state
*options
;
1403 return (struct option_cache
*)0;
1404 if (universe
-> lookup_func
)
1405 return (*universe
-> lookup_func
) (universe
, options
, code
);
1407 log_error ("can't look up options in %s space.",
1409 return (struct option_cache
*)0;
1412 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
1413 struct universe
*universe
;
1414 struct option_state
*options
;
1421 /* Make sure there's a hash table. */
1422 if (universe
-> index
>= options
-> universe_count
||
1423 !(options
-> universes
[universe
-> index
]))
1424 return (struct option_cache
*)0;
1426 hash
= options
-> universes
[universe
-> index
];
1428 hashix
= compute_option_hash (code
);
1429 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1430 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
1432 return (struct option_cache
*)(bptr
-> car
);
1434 return (struct option_cache
*)0;
1437 int save_option_buffer (struct universe
*universe
,
1438 struct option_state
*options
,
1440 unsigned char *buffer
, unsigned length
,
1441 struct option
*option
, int tp
)
1443 struct buffer
*lbp
= (struct buffer
*)0;
1444 struct option_cache
*op
= (struct option_cache
*)0;
1446 if (!option_cache_allocate (&op
, MDL
)) {
1447 log_error ("No memory for option %s.%s.",
1453 /* If we weren't passed a buffer in which the data are saved and
1454 refcounted, allocate one now. */
1456 if (!buffer_allocate (&lbp
, length
, MDL
)) {
1457 log_error ("no memory for option buffer.");
1459 option_cache_dereference (&op
, MDL
);
1462 memcpy (lbp
-> data
, buffer
, length
+ tp
);
1464 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
1467 /* Reference buffer copy to option cache. */
1468 op
-> data
.buffer
= (struct buffer
*)0;
1469 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
1471 /* Point option cache into buffer. */
1472 op
-> data
.data
= buffer
;
1473 op
-> data
.len
= length
;
1476 /* NUL terminate (we can get away with this because we (or
1477 the caller!) allocated one more than the buffer size, and
1478 because the byte following the end of an option is always
1479 the code of the next option, which the caller is getting
1480 out of the *original* buffer. */
1481 buffer
[length
] = 0;
1482 op
-> data
.terminated
= 1;
1484 op
-> data
.terminated
= 0;
1486 op
-> option
= option
;
1488 /* Now store the option. */
1489 save_option (universe
, options
, op
);
1491 /* And let go of our reference. */
1492 option_cache_dereference (&op
, MDL
);
1497 void save_option (struct universe
*universe
,
1498 struct option_state
*options
, struct option_cache
*oc
)
1500 if (universe
-> save_func
)
1501 (*universe
-> save_func
) (universe
, options
, oc
);
1503 log_error ("can't store options in %s space.",
1507 void save_hashed_option (universe
, options
, oc
)
1508 struct universe
*universe
;
1509 struct option_state
*options
;
1510 struct option_cache
*oc
;
1514 pair
*hash
= options
-> universes
[universe
-> index
];
1516 if (oc
-> refcnt
== 0)
1519 /* Compute the hash. */
1520 hashix
= compute_option_hash (oc
-> option
-> code
);
1522 /* If there's no hash table, make one. */
1524 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
1526 log_error ("no memory to store %s.%s",
1527 universe
-> name
, oc
-> option
-> name
);
1530 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
1531 options
-> universes
[universe
-> index
] = (VOIDPTR
)hash
;
1533 /* Try to find an existing option matching the new one. */
1534 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1535 if (((struct option_cache
*)
1536 (bptr
-> car
)) -> option
-> code
==
1537 oc
-> option
-> code
)
1541 /* If we find one, dereference it and put the new one
1544 option_cache_dereference
1545 ((struct option_cache
**)&bptr
-> car
, MDL
);
1546 option_cache_reference
1547 ((struct option_cache
**)&bptr
-> car
,
1553 /* Otherwise, just put the new one at the head of the list. */
1554 bptr
= new_pair (MDL
);
1556 log_error ("No memory for option_cache reference.");
1559 bptr
-> cdr
= hash
[hashix
];
1561 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
1562 hash
[hashix
] = bptr
;
1565 void delete_option (universe
, options
, code
)
1566 struct universe
*universe
;
1567 struct option_state
*options
;
1570 if (universe
-> delete_func
)
1571 (*universe
-> delete_func
) (universe
, options
, code
);
1573 log_error ("can't delete options from %s space.",
1577 void delete_hashed_option (universe
, options
, code
)
1578 struct universe
*universe
;
1579 struct option_state
*options
;
1583 pair bptr
, prev
= (pair
)0;
1584 pair
*hash
= options
-> universes
[universe
-> index
];
1586 /* There may not be any options in this space. */
1590 /* Try to find an existing option matching the new one. */
1591 hashix
= compute_option_hash (code
);
1592 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
1593 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
1598 /* If we found one, wipe it out... */
1601 prev
-> cdr
= bptr
-> cdr
;
1603 hash
[hashix
] = bptr
-> cdr
;
1604 option_cache_dereference
1605 ((struct option_cache
**)(&bptr
-> car
), MDL
);
1606 free_pair (bptr
, MDL
);
1610 extern struct option_cache
*free_option_caches
; /* XXX */
1612 int option_cache_dereference (ptr
, file
, line
)
1613 struct option_cache
**ptr
;
1617 if (!ptr
|| !*ptr
) {
1618 log_error ("Null pointer in option_cache_dereference: %s(%d)",
1620 #if defined (POINTER_DEBUG)
1628 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
1629 if (!(*ptr
) -> refcnt
) {
1630 if ((*ptr
) -> data
.buffer
)
1631 data_string_forget (&(*ptr
) -> data
, file
, line
);
1632 if ((*ptr
) -> expression
)
1633 expression_dereference (&(*ptr
) -> expression
,
1636 option_cache_dereference (&((*ptr
) -> next
),
1638 /* Put it back on the free list... */
1639 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
1640 free_option_caches
= *ptr
;
1641 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
1643 if ((*ptr
) -> refcnt
< 0) {
1644 log_error ("%s(%d): negative refcnt!", file
, line
);
1645 #if defined (DEBUG_RC_HISTORY)
1646 dump_rc_history (*ptr
);
1648 #if defined (POINTER_DEBUG)
1651 *ptr
= (struct option_cache
*)0;
1655 *ptr
= (struct option_cache
*)0;
1660 int hashed_option_state_dereference (universe
, state
, file
, line
)
1661 struct universe
*universe
;
1662 struct option_state
*state
;
1670 /* Get the pointer to the array of hash table bucket heads. */
1671 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
1675 /* For each non-null head, loop through all the buckets dereferencing
1676 the attached option cache structures and freeing the buckets. */
1677 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
1678 for (cp
= heads
[i
]; cp
; cp
= next
) {
1680 option_cache_dereference
1681 ((struct option_cache
**)&cp
-> car
,
1683 free_pair (cp
, file
, line
);
1687 dfree (heads
, file
, line
);
1688 state
-> universes
[universe
-> index
] = (void *)0;
1692 int store_option (result
, universe
, packet
, lease
, client_state
,
1693 in_options
, cfg_options
, scope
, oc
)
1694 struct data_string
*result
;
1695 struct universe
*universe
;
1696 struct packet
*packet
;
1697 struct lease
*lease
;
1698 struct client_state
*client_state
;
1699 struct option_state
*in_options
;
1700 struct option_state
*cfg_options
;
1701 struct binding_scope
**scope
;
1702 struct option_cache
*oc
;
1704 struct data_string d1
, d2
;
1706 memset (&d1
, 0, sizeof d1
);
1707 memset (&d2
, 0, sizeof d2
);
1709 if (evaluate_option_cache (&d2
, packet
, lease
, client_state
,
1710 in_options
, cfg_options
, scope
, oc
, MDL
)) {
1711 if (!buffer_allocate (&d1
.buffer
,
1713 universe
-> length_size
+
1714 universe
-> tag_size
+ d2
.len
), MDL
)) {
1715 data_string_forget (result
, MDL
);
1716 data_string_forget (&d2
, MDL
);
1719 d1
.data
= &d1
.buffer
-> data
[0];
1721 memcpy (d1
.buffer
-> data
,
1722 result
-> data
, result
-> len
);
1723 d1
.len
= result
-> len
;
1724 (*universe
-> store_tag
) (&d1
.buffer
-> data
[d1
.len
],
1725 oc
-> option
-> code
);
1726 d1
.len
+= universe
-> tag_size
;
1727 (*universe
-> store_length
) (&d1
.buffer
-> data
[d1
.len
],
1729 d1
.len
+= universe
-> length_size
;
1730 memcpy (&d1
.buffer
-> data
[d1
.len
], d2
.data
, d2
.len
);
1732 data_string_forget (&d2
, MDL
);
1733 data_string_forget (result
, MDL
);
1734 data_string_copy (result
, &d1
, MDL
);
1735 data_string_forget (&d1
, MDL
);
1741 int option_space_encapsulate (result
, packet
, lease
, client_state
,
1742 in_options
, cfg_options
, scope
, name
)
1743 struct data_string
*result
;
1744 struct packet
*packet
;
1745 struct lease
*lease
;
1746 struct client_state
*client_state
;
1747 struct option_state
*in_options
;
1748 struct option_state
*cfg_options
;
1749 struct binding_scope
**scope
;
1750 struct data_string
*name
;
1754 u
= (struct universe
*)0;
1755 universe_hash_lookup (&u
, universe_hash
,
1756 (const char *)name
-> data
, name
-> len
, MDL
);
1760 if (u
-> encapsulate
)
1761 return (*u
-> encapsulate
) (result
, packet
, lease
,
1763 in_options
, cfg_options
, scope
, u
);
1764 log_error ("encapsulation requested for %s with no support.",
1769 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
1770 in_options
, cfg_options
, scope
, universe
)
1771 struct data_string
*result
;
1772 struct packet
*packet
;
1773 struct lease
*lease
;
1774 struct client_state
*client_state
;
1775 struct option_state
*in_options
;
1776 struct option_state
*cfg_options
;
1777 struct binding_scope
**scope
;
1778 struct universe
*universe
;
1784 if (universe
-> index
>= cfg_options
-> universe_count
)
1787 hash
= cfg_options
-> universes
[universe
-> index
];
1792 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
1793 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
1794 if (store_option (result
, universe
, packet
,
1795 lease
, client_state
, in_options
,
1797 (struct option_cache
*)p
-> car
))
1805 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
1806 in_options
, cfg_options
, scope
, universe
)
1807 struct data_string
*result
;
1808 struct packet
*packet
;
1809 struct lease
*lease
;
1810 struct client_state
*client_state
;
1811 struct option_state
*in_options
;
1812 struct option_state
*cfg_options
;
1813 struct binding_scope
**scope
;
1814 struct universe
*universe
;
1818 static struct option_cache
*no_nwip
;
1819 struct data_string ds
;
1820 struct option_chain_head
*head
;
1822 if (universe
-> index
>= cfg_options
-> universe_count
)
1824 head
= ((struct option_chain_head
*)
1825 cfg_options
-> universes
[fqdn_universe
.index
]);
1830 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
1831 if (store_option (result
, universe
, packet
,
1832 lease
, client_state
, in_options
,
1834 (struct option_cache
*)ocp
-> car
))
1838 /* If there's no data, the nwip suboption is supposed to contain
1839 a suboption saying there's no data. */
1842 static unsigned char nni
[] = { 1, 0 };
1843 memset (&ds
, 0, sizeof ds
);
1846 if (option_cache_allocate (&no_nwip
, MDL
))
1847 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
1848 no_nwip
-> option
= nwip_universe
.options
[1];
1851 if (store_option (result
, universe
, packet
, lease
,
1852 client_state
, in_options
,
1853 cfg_options
, scope
, no_nwip
))
1857 memset (&ds
, 0, sizeof ds
);
1859 /* If we have nwip options, the first one has to be the
1860 nwip-exists-in-option-area option. */
1861 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
1862 data_string_forget (result
, MDL
);
1865 ds
.data
= &ds
.buffer
-> data
[0];
1866 ds
.buffer
-> data
[0] = 2;
1867 ds
.buffer
-> data
[1] = 0;
1868 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
1869 data_string_forget (result
, MDL
);
1870 data_string_copy (result
, &ds
, MDL
);
1871 data_string_forget (&ds
, MDL
);
1877 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
1878 in_options
, cfg_options
, scope
, universe
)
1879 struct data_string
*result
;
1880 struct packet
*packet
;
1881 struct lease
*lease
;
1882 struct client_state
*client_state
;
1883 struct option_state
*in_options
;
1884 struct option_state
*cfg_options
;
1885 struct binding_scope
**scope
;
1886 struct universe
*universe
;
1889 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
1892 struct buffer
*bp
= (struct buffer
*)0;
1893 struct option_chain_head
*head
;
1895 /* If there's no FQDN universe, don't encapsulate. */
1896 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
1898 head
= ((struct option_chain_head
*)
1899 cfg_options
-> universes
[fqdn_universe
.index
]);
1903 /* Figure out the values of all the suboptions. */
1904 memset (results
, 0, sizeof results
);
1905 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
1906 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
1907 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
1909 evaluate_option_cache (&results
[oc
-> option
-> code
],
1910 packet
, lease
, client_state
, in_options
,
1911 cfg_options
, scope
, oc
, MDL
);
1913 len
= 4 + results
[FQDN_FQDN
].len
;
1914 /* Save the contents of the option in a buffer. */
1915 if (!buffer_allocate (&bp
, len
, MDL
)) {
1916 log_error ("no memory for option buffer.");
1919 buffer_reference (&result
-> buffer
, bp
, MDL
);
1921 result
-> data
= &bp
-> data
[0];
1923 memset (&bp
-> data
[0], 0, len
);
1924 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
1925 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
1926 bp
-> data
[0] |= 2;
1927 if (results
[FQDN_SERVER_UPDATE
].len
&&
1928 results
[FQDN_SERVER_UPDATE
].data
[0])
1929 bp
-> data
[0] |= 1;
1930 if (results
[FQDN_RCODE1
].len
)
1931 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
1932 if (results
[FQDN_RCODE2
].len
)
1933 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
1935 if (results
[FQDN_ENCODED
].len
&&
1936 results
[FQDN_ENCODED
].data
[0]) {
1939 bp
-> data
[0] |= 4;
1940 out
= &bp
-> data
[3];
1941 if (results
[FQDN_FQDN
].len
) {
1943 while (i
< results
[FQDN_FQDN
].len
) {
1946 results
[FQDN_FQDN
].data
[j
]) &&
1947 j
< results
[FQDN_FQDN
].len
; j
++)
1950 memcpy (out
, &results
[FQDN_FQDN
].data
[i
],
1954 if (results
[FQDN_FQDN
].data
[j
] == '.')
1957 if ((results
[FQDN_FQDN
].data
1958 [results
[FQDN_FQDN
].len
- 1] == '.'))
1960 result
-> len
= out
- result
-> data
;
1961 result
-> terminated
= 0;
1964 if (results
[FQDN_FQDN
].len
) {
1965 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
1966 results
[FQDN_FQDN
].len
);
1967 result
-> len
+= results
[FQDN_FQDN
].len
;
1968 result
-> terminated
= 0;
1971 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
1972 if (results
[i
].len
)
1973 data_string_forget (&results
[i
], MDL
);
1975 buffer_dereference (&bp
, MDL
);
1979 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
1980 struct client_state
*client_state
,
1981 struct option_state
*in_options
,
1982 struct option_state
*cfg_options
,
1983 struct binding_scope
**scope
,
1984 struct universe
*u
, void *stuff
,
1985 void (*func
) (struct option_cache
*,
1987 struct lease
*, struct client_state
*,
1988 struct option_state
*,
1989 struct option_state
*,
1990 struct binding_scope
**,
1991 struct universe
*, void *))
1994 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
1995 cfg_options
, scope
, u
, stuff
, func
);
1998 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
1999 struct client_state
*client_state
,
2000 struct option_state
*in_options
,
2001 struct option_state
*cfg_options
,
2002 struct binding_scope
**scope
,
2003 struct universe
*u
, void *stuff
,
2004 void (*func
) (struct option_cache
*,
2006 struct lease
*, struct client_state
*,
2007 struct option_state
*,
2008 struct option_state
*,
2009 struct binding_scope
**,
2010 struct universe
*, void *),
2011 struct option_cache
*oc
,
2014 struct universe
*universe
= find_option_universe (oc
-> option
,
2017 if (universe
-> foreach
)
2018 (*universe
-> foreach
) (packet
, lease
, client_state
,
2019 in_options
, cfg_options
,
2020 scope
, universe
, stuff
, func
);
2023 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2024 struct client_state
*client_state
,
2025 struct option_state
*in_options
,
2026 struct option_state
*cfg_options
,
2027 struct binding_scope
**scope
,
2028 struct universe
*u
, void *stuff
,
2029 void (*func
) (struct option_cache
*,
2032 struct client_state
*,
2033 struct option_state
*,
2034 struct option_state
*,
2035 struct binding_scope
**,
2036 struct universe
*, void *))
2040 struct option_cache
*oc
;
2042 if (cfg_options
-> universe_count
<= u
-> index
)
2045 hash
= cfg_options
-> universes
[u
-> index
];
2048 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2050 /* XXX save _all_ options! XXX */
2051 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2052 oc
= (struct option_cache
*)p
-> car
;
2053 (*func
) (oc
, packet
, lease
, client_state
,
2054 in_options
, cfg_options
, scope
, u
, stuff
);
2059 void save_linked_option (universe
, options
, oc
)
2060 struct universe
*universe
;
2061 struct option_state
*options
;
2062 struct option_cache
*oc
;
2065 struct option_chain_head
*head
;
2067 if (universe
-> index
>= options
-> universe_count
)
2069 head
= ((struct option_chain_head
*)
2070 options
-> universes
[universe
-> index
]);
2072 if (!option_chain_head_allocate (((struct option_chain_head
**)
2073 &options
-> universes
2074 [universe
-> index
]), MDL
))
2076 head
= ((struct option_chain_head
*)
2077 options
-> universes
[universe
-> index
]);
2080 /* Find the tail of the list. */
2081 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
2083 ((struct option_cache
*)((*tail
) -> car
)) -> option
) {
2084 option_cache_dereference ((struct option_cache
**)
2085 (&(*tail
) -> car
), MDL
);
2086 option_cache_reference ((struct option_cache
**)
2087 (&(*tail
) -> car
), oc
, MDL
);
2092 *tail
= cons (0, 0);
2094 option_cache_reference ((struct option_cache
**)
2095 (&(*tail
) -> car
), oc
, MDL
);
2099 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
2100 in_options
, cfg_options
, scope
, universe
)
2101 struct data_string
*result
;
2102 struct packet
*packet
;
2103 struct lease
*lease
;
2104 struct client_state
*client_state
;
2105 struct option_state
*in_options
;
2106 struct option_state
*cfg_options
;
2107 struct binding_scope
**scope
;
2108 struct universe
*universe
;
2112 struct option_chain_head
*head
;
2114 if (universe
-> index
>= cfg_options
-> universe_count
)
2116 head
= ((struct option_chain_head
*)
2117 cfg_options
-> universes
[universe
-> index
]);
2122 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
2123 if (store_option (result
, universe
, packet
,
2124 lease
, client_state
, in_options
, cfg_options
,
2125 scope
, (struct option_cache
*)(oc
-> car
)))
2132 void delete_linked_option (universe
, options
, code
)
2133 struct universe
*universe
;
2134 struct option_state
*options
;
2137 pair
*tail
, tmp
= (pair
)0;
2138 struct option_chain_head
*head
;
2140 if (universe
-> index
>= options
-> universe_count
)
2142 head
= ((struct option_chain_head
*)
2143 options
-> universes
[universe
-> index
]);
2147 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
2149 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
2151 tmp
= (*tail
) -> cdr
;
2152 option_cache_dereference ((struct option_cache
**)
2153 (&(*tail
) -> car
), MDL
);
2161 struct option_cache
*lookup_linked_option (universe
, options
, code
)
2162 struct universe
*universe
;
2163 struct option_state
*options
;
2167 struct option_chain_head
*head
;
2169 if (universe
-> index
>= options
-> universe_count
)
2171 head
= ((struct option_chain_head
*)
2172 options
-> universes
[universe
-> index
]);
2176 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
2178 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
2179 return (struct option_cache
*)(oc
-> car
);
2183 return (struct option_cache
*)0;
2186 int linked_option_state_dereference (universe
, state
, file
, line
)
2187 struct universe
*universe
;
2188 struct option_state
*state
;
2192 return (option_chain_head_dereference
2193 ((struct option_chain_head
**)
2194 (&state
-> universes
[universe
-> index
]), MDL
));
2197 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
2198 struct client_state
*client_state
,
2199 struct option_state
*in_options
,
2200 struct option_state
*cfg_options
,
2201 struct binding_scope
**scope
,
2202 struct universe
*u
, void *stuff
,
2203 void (*func
) (struct option_cache
*,
2206 struct client_state
*,
2207 struct option_state
*,
2208 struct option_state
*,
2209 struct binding_scope
**,
2210 struct universe
*, void *))
2213 struct option_chain_head
*head
;
2215 if (u
-> index
>= cfg_options
-> universe_count
)
2217 head
= ((struct option_chain_head
*)
2218 cfg_options
-> universes
[u
-> index
]);
2221 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
2222 (*func
) ((struct option_cache
*)(car
-> car
),
2223 packet
, lease
, client_state
,
2224 in_options
, cfg_options
, scope
, u
, stuff
);
2228 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
2229 struct interface_info
*interface
;
2230 struct dhcp_packet
*packet
;
2232 unsigned int from_port
;
2234 struct hardware
*hfrom
;
2236 struct option_cache
*op
;
2237 struct packet
*decoded_packet
;
2238 #if defined (DEBUG_MEMORY_LEAKAGE)
2239 unsigned long previous_outstanding
= dmalloc_outstanding
;
2242 #if defined (TRACING)
2243 trace_inpacket_stash (interface
, packet
, len
, from_port
, from
, hfrom
);
2246 decoded_packet
= (struct packet
*)0;
2247 if (!packet_allocate (&decoded_packet
, MDL
)) {
2248 log_error ("do_packet: no memory for incoming packet!");
2251 decoded_packet
-> raw
= packet
;
2252 decoded_packet
-> packet_length
= len
;
2253 decoded_packet
-> client_port
= from_port
;
2254 decoded_packet
-> client_addr
= from
;
2255 interface_reference (&decoded_packet
-> interface
, interface
, MDL
);
2256 decoded_packet
-> haddr
= hfrom
;
2258 if (packet
-> hlen
> sizeof packet
-> chaddr
) {
2259 packet_dereference (&decoded_packet
, MDL
);
2260 log_info ("Discarding packet with bogus hlen.");
2264 /* If there's an option buffer, try to parse it. */
2265 if (decoded_packet
-> packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
2266 if (!parse_options (decoded_packet
)) {
2267 if (decoded_packet
-> options
)
2268 option_state_dereference
2269 (&decoded_packet
-> options
, MDL
);
2270 packet_dereference (&decoded_packet
, MDL
);
2274 if (decoded_packet
-> options_valid
&&
2275 (op
= lookup_option (&dhcp_universe
,
2276 decoded_packet
-> options
,
2277 DHO_DHCP_MESSAGE_TYPE
))) {
2278 struct data_string dp
;
2279 memset (&dp
, 0, sizeof dp
);
2280 evaluate_option_cache (&dp
, decoded_packet
,
2282 (struct client_state
*)0,
2283 decoded_packet
-> options
,
2284 (struct option_state
*)0,
2285 (struct binding_scope
**)0,
2288 decoded_packet
-> packet_type
= dp
.data
[0];
2290 decoded_packet
-> packet_type
= 0;
2291 data_string_forget (&dp
, MDL
);
2295 if (decoded_packet
-> packet_type
)
2296 dhcp (decoded_packet
);
2298 bootp (decoded_packet
);
2300 /* If the caller kept the packet, they'll have upped the refcnt. */
2301 packet_dereference (&decoded_packet
, MDL
);
2303 #if defined (DEBUG_MEMORY_LEAKAGE)
2304 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
2306 dmalloc_outstanding
- previous_outstanding
,
2307 dmalloc_outstanding
, dmalloc_longterm
);
2309 #if defined (DEBUG_MEMORY_LEAKAGE)
2310 dmalloc_dump_outstanding ();
2312 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
2313 dump_rc_history (0);