3 DHCP options parsing and reassembly. */
6 * Copyright (c) 2004-2012,2014 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
25 * https://www.isc.org/
29 #define DHCP_OPTION_DATA
31 #include <omapip/omapip_p.h>
34 struct option
*vendor_cfg_option
;
36 static int pretty_text(char **, char *, const unsigned char **,
37 const unsigned char *, int);
38 static int pretty_domain(char **, char *, const unsigned char **,
39 const unsigned char *);
40 static int prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
41 unsigned char *buffer
, unsigned length
,
42 unsigned code
, int terminatep
,
43 struct option_cache
**opp
);
45 /* Parse all available options out of the specified packet. */
47 int parse_options (packet
)
48 struct packet
*packet
;
50 struct option_cache
*op
= (struct option_cache
*)0;
52 /* Allocate a new option state. */
53 if (!option_state_allocate (&packet
-> options
, MDL
)) {
54 packet
-> options_valid
= 0;
58 /* If we don't see the magic cookie, there's nothing to parse. */
59 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
60 packet
-> options_valid
= 0;
64 /* Go through the options field, up to the end of the packet
66 if (!parse_option_buffer (packet
-> options
,
67 &packet
-> raw
-> options
[4],
68 (packet
-> packet_length
-
69 DHCP_FIXED_NON_UDP
- 4),
72 /* STSN servers have a bug where they send a mangled
73 domain-name option, and whatever is beyond that in
74 the packet is junk. Microsoft clients accept this,
75 which is probably why whoever implemented the STSN
76 server isn't aware of the problem yet. To work around
77 this, we will accept corrupt packets from the server if
78 they contain a valid DHCP_MESSAGE_TYPE option, but
79 will not accept any corrupt client packets (the ISC DHCP
80 server is sufficiently widely used that it is probably
81 beneficial for it to be picky) and will not accept
82 packets whose type can't be determined. */
84 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
85 DHO_DHCP_MESSAGE_TYPE
))) {
86 if (!op
-> data
.data
||
87 (op
-> data
.data
[0] != DHCPOFFER
&&
88 op
-> data
.data
[0] != DHCPACK
&&
89 op
-> data
.data
[0] != DHCPNAK
))
95 /* If we parsed a DHCP Option Overload option, parse more
96 options out of the buffer(s) containing them. */
97 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
98 DHO_DHCP_OPTION_OVERLOAD
))) {
99 if (op
-> data
.data
[0] & 1) {
100 if (!parse_option_buffer
102 (unsigned char *)packet
-> raw
-> file
,
103 sizeof packet
-> raw
-> file
,
107 if (op
-> data
.data
[0] & 2) {
108 if (!parse_option_buffer
110 (unsigned char *)packet
-> raw
-> sname
,
111 sizeof packet
-> raw
-> sname
,
116 packet
-> options_valid
= 1;
120 /* Parse options out of the specified buffer, storing addresses of option
121 * values in packet->options.
123 int parse_option_buffer (options
, buffer
, length
, universe
)
124 struct option_state
*options
;
125 const unsigned char *buffer
;
127 struct universe
*universe
;
129 unsigned len
, offset
;
131 struct option_cache
*op
= NULL
, *nop
= NULL
;
132 struct buffer
*bp
= (struct buffer
*)0;
133 struct option
*option
= NULL
;
134 char *reason
= "general failure";
136 if (!buffer_allocate (&bp
, length
, MDL
)) {
137 log_error ("no memory for option buffer.");
140 memcpy (bp
-> data
, buffer
, length
);
143 (offset
+ universe
->tag_size
) <= length
&&
144 (code
= universe
->get_tag(buffer
+ offset
)) != universe
->end
; ) {
145 offset
+= universe
->tag_size
;
147 /* Pad options don't have a length - just skip them. */
151 /* Don't look for length if the buffer isn't that big. */
152 if ((offset
+ universe
->length_size
) > length
) {
153 reason
= "code tag at end of buffer - missing "
158 /* All other fields (except PAD and END handled above)
159 * have a length field, unless it's a DHCPv6 zero-length
160 * options space (eg any of the enterprise-id'd options).
162 * Zero-length-size option spaces basically consume the
163 * entire options buffer, so have at it.
165 if (universe
->get_length
!= NULL
)
166 len
= universe
->get_length(buffer
+ offset
);
167 else if (universe
->length_size
== 0)
168 len
= length
- universe
->tag_size
;
170 log_fatal("Improperly configured option space(%s): "
171 "may not have a nonzero length size "
172 "AND a NULL get_length function.",
175 /* Silence compiler warnings. */
179 offset
+= universe
->length_size
;
181 option_code_hash_lookup(&option
, universe
->code_hash
, &code
,
184 /* If the length is outrageous, the options are bad. */
185 if (offset
+ len
> length
) {
186 reason
= "option length exceeds option buffer length";
188 log_error("parse_option_buffer: malformed option "
189 "%s.%s (code %u): %s.", universe
->name
,
190 option
? option
->name
: "<unknown>",
192 buffer_dereference (&bp
, MDL
);
196 /* If the option contains an encapsulation, parse it. If
197 the parse fails, or the option isn't an encapsulation (by
198 far the most common case), or the option isn't entirely
199 an encapsulation, keep the raw data as well. */
201 (option
->format
[0] == 'e' ||
202 option
->format
[0] == 'E') &&
203 (parse_encapsulated_suboptions(options
, option
,
204 bp
->data
+ offset
, len
,
206 op
= lookup_option(universe
, options
, code
);
208 if (op
!= NULL
&& universe
->concat_duplicates
) {
209 struct data_string
new;
210 memset(&new, 0, sizeof new);
211 if (!buffer_allocate(&new.buffer
,
214 log_error("parse_option_buffer: "
216 buffer_dereference(&bp
, MDL
);
219 /* Copy old option to new data object. */
220 memcpy(new.buffer
->data
, op
->data
.data
,
222 /* Concat new option behind old. */
223 memcpy(new.buffer
->data
+ op
->data
.len
,
224 bp
->data
+ offset
, len
);
225 new.len
= op
->data
.len
+ len
;
226 new.data
= new.buffer
->data
;
227 /* Save new concat'd object. */
228 data_string_forget(&op
->data
, MDL
);
229 data_string_copy(&op
->data
, &new, MDL
);
230 data_string_forget(&new, MDL
);
231 } else if (op
!= NULL
) {
232 /* We must append this statement onto the
235 while (op
->next
!= NULL
)
238 if (!option_cache_allocate(&nop
, MDL
)) {
239 log_error("parse_option_buffer: "
241 buffer_dereference(&bp
, MDL
);
245 option_reference(&nop
->option
, op
->option
, MDL
);
247 nop
->data
.buffer
= NULL
;
248 buffer_reference(&nop
->data
.buffer
, bp
, MDL
);
249 nop
->data
.data
= bp
->data
+ offset
;
252 option_cache_reference(&op
->next
, nop
, MDL
);
253 option_cache_dereference(&nop
, MDL
);
255 if (save_option_buffer(universe
, options
, bp
,
256 bp
->data
+ offset
, len
,
258 log_error("parse_option_buffer: "
259 "save_option_buffer failed");
260 buffer_dereference(&bp
, MDL
);
265 option_dereference(&option
, MDL
);
268 buffer_dereference (&bp
, MDL
);
272 /* If an option in an option buffer turns out to be an encapsulation,
273 figure out what to do. If we don't know how to de-encapsulate it,
274 or it's not well-formed, return zero; otherwise, return 1, indicating
275 that we succeeded in de-encapsulating it. */
277 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
281 struct universe
*universe
= (struct universe
*)0;
283 /* Look for the E option in the option format. */
284 s
= strchr (eopt
-> format
, 'E');
286 log_error ("internal encapsulation format error 1.");
289 /* Look for the universe name in the option format. */
290 t
= strchr (++s
, '.');
291 /* If there was no trailing '.', or there's something after the
292 trailing '.', the option is bogus and we can't use it. */
294 log_error ("internal encapsulation format error 2.");
297 if (t
== s
&& uname
) {
298 for (i
= 0; i
< universe_count
; i
++) {
299 if (!strcmp (universes
[i
] -> name
, uname
)) {
300 universe
= universes
[i
];
305 for (i
= 0; i
< universe_count
; i
++) {
306 if (strlen (universes
[i
] -> name
) == t
- s
&&
307 !memcmp (universes
[i
] -> name
,
308 s
, (unsigned)(t
- s
))) {
309 universe
= universes
[i
];
317 /* If an option in an option buffer turns out to be an encapsulation,
318 figure out what to do. If we don't know how to de-encapsulate it,
319 or it's not well-formed, return zero; otherwise, return 1, indicating
320 that we succeeded in de-encapsulating it. */
322 int parse_encapsulated_suboptions (struct option_state
*options
,
324 const unsigned char *buffer
,
325 unsigned len
, struct universe
*eu
,
329 struct universe
*universe
= find_option_universe (eopt
, uname
);
331 /* If we didn't find the universe, we can't do anything with it
332 right now (e.g., we can't decode vendor options until we've
333 decoded the packet and executed the scopes that it matches). */
337 /* If we don't have a decoding function for it, we can't decode
339 if (!universe
-> decode
)
342 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
344 /* If there is stuff before the suboptions, we have to keep it. */
345 if (eopt
-> format
[0] != 'E')
347 /* Otherwise, return the status of the decode function. */
351 int fqdn_universe_decode (struct option_state
*options
,
352 const unsigned char *buffer
,
353 unsigned length
, struct universe
*u
)
355 struct buffer
*bp
= (struct buffer
*)0;
357 /* FQDN options have to be at least four bytes long. */
361 /* Save the contents of the option in a buffer. */
362 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
363 log_error ("no memory for option buffer.");
366 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
368 if (buffer
[0] & 4) /* encoded */
372 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
373 bp
->data
, 1, FQDN_ENCODED
, 0)) {
375 buffer_dereference (&bp
, MDL
);
379 if (buffer
[0] & 1) /* server-update */
383 if (buffer
[0] & 2) /* no-client-update */
388 /* XXX Ideally we should store the name in DNS format, so if the
389 XXX label isn't in DNS format, we convert it to DNS format,
390 XXX rather than converting labels specified in DNS format to
391 XXX the plain ASCII representation. But that's hard, so
394 /* Not encoded using DNS format? */
395 if (!bp
-> data
[0]) {
398 /* Some broken clients NUL-terminate this option. */
399 if (buffer
[length
- 1] == 0) {
404 /* Determine the length of the hostname component of the
405 name. If the name contains no '.' character, it
406 represents a non-qualified label. */
407 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
410 /* Note: If the client sends a FQDN, the first '.' will
411 be used as a NUL terminator for the hostname. */
412 if (i
&& (!save_option_buffer(&fqdn_universe
, options
, bp
,
416 /* Note: If the client sends a single label, the
417 FQDN_DOMAINNAME option won't be set. */
418 if (length
> 4 + i
&&
419 (!save_option_buffer(&fqdn_universe
, options
, bp
,
420 &bp
-> data
[6 + i
], length
- 4 - i
,
421 FQDN_DOMAINNAME
, 1)))
423 /* Also save the whole name. */
425 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
426 &bp
-> data
[5], length
- 3,
432 unsigned total_len
= 0;
433 unsigned first_len
= 0;
439 while (s
< &bp
-> data
[0] + length
+ 2) {
442 log_info ("fancy bits in fqdn option");
449 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
450 log_info ("fqdn tag longer than buffer");
454 if (first_len
== 0) {
460 total_len
+= len
+ 1;
463 /* We wind up with a length that's one too many because
464 we shouldn't increment for the last label, but there's
465 no way to tell we're at the last label until we exit
471 first_len
= total_len
;
475 !save_option_buffer(&fqdn_universe
, options
, bp
,
476 &bp
-> data
[6], first_len
,
479 if (total_len
> 0 && first_len
!= total_len
) {
480 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
481 &bp
->data
[6 + first_len
],
482 total_len
- first_len
,
487 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
488 &bp
-> data
[6], total_len
,
493 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
495 FQDN_NO_CLIENT_UPDATE
, 0))
497 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
499 FQDN_SERVER_UPDATE
, 0))
502 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
506 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
511 buffer_dereference (&bp
, MDL
);
516 * Load all options into a buffer, and then split them out into the three
517 * separate fields in the dhcp packet (options, file, and sname) where
518 * options can be stored.
520 * returns 0 on error, length of packet on success
523 cons_options(struct packet
*inpacket
, struct dhcp_packet
*outpacket
,
524 struct lease
*lease
, struct client_state
*client_state
,
525 int mms
, struct option_state
*in_options
,
526 struct option_state
*cfg_options
,
527 struct binding_scope
**scope
,
528 int overload_avail
, int terminate
, int bootpp
,
529 struct data_string
*prl
, const char *vuname
)
531 #define PRIORITY_COUNT 300
532 unsigned priority_list
[PRIORITY_COUNT
];
534 unsigned char buffer
[4096], agentopts
[1024];
536 unsigned mb_size
= 0, mb_max
= 0;
537 unsigned option_size
= 0, agent_size
= 0;
540 struct option_cache
*op
;
541 struct data_string ds
;
543 int overload_used
= 0;
544 int of1
= 0, of2
= 0;
546 memset(&ds
, 0, sizeof ds
);
549 * If there's a Maximum Message Size option in the incoming packet
550 * and no alternate maximum message size has been specified, or
551 * if the one specified in the packet is shorter than the
552 * alternative, take the one in the packet.
556 (op
= lookup_option(&dhcp_universe
, inpacket
->options
,
557 DHO_DHCP_MAX_MESSAGE_SIZE
)) &&
558 (evaluate_option_cache(&ds
, inpacket
, lease
,
559 client_state
, in_options
,
560 cfg_options
, scope
, op
, MDL
) != 0)) {
561 if (ds
.len
>= sizeof (u_int16_t
)) {
562 i
= getUShort(ds
.data
);
563 if(!mms
|| (i
< mms
))
566 data_string_forget(&ds
, MDL
);
570 * If the client has provided a maximum DHCP message size,
571 * use that, up to the MTU limit. Otherwise, if it's BOOTP,
572 * only 64 bytes; otherwise use up to the minimum IP MTU size
575 * XXX if a BOOTP client specifies a max message size, we will
579 if (mms
< DHCP_MTU_MIN
)
580 /* Enforce minimum packet size, per RFC 2132 */
581 mb_size
= DHCP_MIN_OPTION_LEN
;
582 else if (mms
> DHCP_MTU_MAX
)
584 * TODO: Packets longer than 1500 bytes really
585 * should be allowed, but it requires upstream
586 * changes to the way the packet is allocated. For
587 * now, we forbid them. They won't be needed very
590 mb_size
= DHCP_MAX_OPTION_LEN
;
592 mb_size
= mms
- DHCP_FIXED_LEN
;
595 if (inpacket
!= NULL
&&
596 (inpacket
->packet_length
>= 64 + DHCP_FIXED_NON_UDP
))
597 mb_size
= inpacket
->packet_length
- DHCP_FIXED_NON_UDP
;
599 mb_size
= DHCP_MIN_OPTION_LEN
;
602 * If answering a client message, see whether any relay agent
603 * options were included with the message. If so, save them
604 * to copy back in later, and make space in the main buffer
605 * to accommodate them
607 if (client_state
== NULL
) {
608 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
610 agent_size
= store_options(NULL
, agentopts
, 0,
612 inpacket
, lease
, client_state
,
613 in_options
, cfg_options
, scope
,
614 priority_list
, priority_len
,
617 mb_size
+= agent_size
;
618 if (mb_size
> DHCP_MAX_OPTION_LEN
)
619 mb_size
= DHCP_MAX_OPTION_LEN
;
623 * Set offsets for buffer data to be copied into filename
624 * and servername fields
626 if (mb_size
> agent_size
)
627 mb_max
= mb_size
- agent_size
;
631 if (overload_avail
& 1) {
633 mb_max
+= DHCP_FILE_LEN
;
636 if (overload_avail
& 2) {
638 mb_max
+= DHCP_SNAME_LEN
;
642 * Preload the option priority list with protocol-mandatory options.
643 * This effectively gives these options the highest priority.
644 * This provides the order for any available options, the option
645 * must be in the option cache in order to actually be included.
648 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
649 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
650 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
651 priority_list
[priority_len
++] = DHO_DHCP_RENEWAL_TIME
;
652 priority_list
[priority_len
++] = DHO_DHCP_REBINDING_TIME
;
653 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
654 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
655 priority_list
[priority_len
++] = DHO_ASSOCIATED_IP
;
657 if (prl
!= NULL
&& prl
->len
> 0) {
658 if ((op
= lookup_option(&dhcp_universe
, cfg_options
,
659 DHO_SUBNET_SELECTION
))) {
660 if (priority_len
< PRIORITY_COUNT
)
661 priority_list
[priority_len
++] =
662 DHO_SUBNET_SELECTION
;
665 data_string_truncate(prl
, (PRIORITY_COUNT
- priority_len
));
668 * Copy the client's PRL onto the priority_list after our high
671 for (i
= 0; i
< prl
->len
; i
++) {
673 * Prevent client from changing order of delivery
674 * of relay agent information option.
676 if (prl
->data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
677 priority_list
[priority_len
++] = prl
->data
[i
];
681 * If the client doesn't request the FQDN option explicitly,
682 * to indicate priority, consider it lowest priority. Fit
683 * in the packet if there is space. Note that the option
684 * may only be included if the client supplied one.
686 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
687 (lookup_option(&fqdn_universe
, inpacket
->options
,
688 FQDN_ENCODED
) != NULL
))
689 priority_list
[priority_len
++] = DHO_FQDN
;
692 * Some DHCP Servers will give the subnet-mask option if
693 * it is not on the parameter request list - so some client
694 * implementations have come to rely on this - so we will
695 * also make sure we supply this, at lowest priority.
697 * This is only done in response to DHCPDISCOVER or
698 * DHCPREQUEST messages, to avoid providing the option on
699 * DHCPINFORM or DHCPLEASEQUERY responses (if the client
700 * didn't request it).
702 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
703 ((inpacket
->packet_type
== DHCPDISCOVER
) ||
704 (inpacket
->packet_type
== DHCPREQUEST
)))
705 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
708 * First, hardcode some more options that ought to be
709 * sent first...these are high priority to have in the
712 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
713 priority_list
[priority_len
++] = DHO_ROUTERS
;
714 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
715 priority_list
[priority_len
++] = DHO_HOST_NAME
;
716 priority_list
[priority_len
++] = DHO_FQDN
;
719 * Append a list of the standard DHCP options from the
720 * standard DHCP option space. Actually, if a site
721 * option space hasn't been specified, we wind up
722 * treating the dhcp option space as the site option
723 * space, and the first for loop is skipped, because
724 * it's slightly more general to do it this way,
725 * taking the 1Q99 DHCP futures work into account.
727 if (cfg_options
->site_code_min
) {
728 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
729 hash
= cfg_options
->universes
[dhcp_universe
.index
];
731 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
732 op
= (struct option_cache
*)(pp
->car
);
733 if (op
->option
->code
<
734 cfg_options
->site_code_min
&&
735 priority_len
< PRIORITY_COUNT
&&
736 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
737 priority_list
[priority_len
++] =
745 * Now cycle through the site option space, or if there
746 * is no site option space, we'll be cycling through the
749 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
750 hash
= cfg_options
->universes
[cfg_options
->site_universe
];
752 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
753 op
= (struct option_cache
*)(pp
->car
);
754 if (op
->option
->code
>=
755 cfg_options
->site_code_min
&&
756 priority_len
< PRIORITY_COUNT
&&
757 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
758 priority_list
[priority_len
++] =
764 * Put any spaces that are encapsulated on the list,
765 * sort out whether they contain values later.
767 for (i
= 0; i
< cfg_options
->universe_count
; i
++) {
768 if (universes
[i
]->enc_opt
&&
769 priority_len
< PRIORITY_COUNT
&&
770 universes
[i
]->enc_opt
->universe
== &dhcp_universe
) {
771 if (universes
[i
]->enc_opt
->code
!=
772 DHO_DHCP_AGENT_OPTIONS
)
773 priority_list
[priority_len
++] =
774 universes
[i
]->enc_opt
->code
;
779 * The vendor option space can't stand on its own, so always
780 * add it to the list.
782 if (priority_len
< PRIORITY_COUNT
)
783 priority_list
[priority_len
++] =
784 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
787 /* Put the cookie up front... */
788 memcpy(buffer
, DHCP_OPTIONS_COOKIE
, 4);
791 /* Copy the options into the big buffer... */
792 option_size
= store_options(&overload_used
, buffer
, index
, mb_max
,
793 inpacket
, lease
, client_state
,
794 in_options
, cfg_options
, scope
,
795 priority_list
, priority_len
,
796 of1
, of2
, terminate
, vuname
);
798 /* If store_options() failed */
799 if (option_size
== 0)
802 /* How much was stored in the main buffer? */
803 index
+= option_size
;
806 * If we're going to have to overload, store the overload
810 if (mb_size
- agent_size
- index
< 3)
813 buffer
[index
++] = DHO_DHCP_OPTION_OVERLOAD
;
815 buffer
[index
++] = overload_used
;
817 if (overload_used
& 1)
818 memcpy(outpacket
->file
, &buffer
[of1
], DHCP_FILE_LEN
);
820 if (overload_used
& 2)
821 memcpy(outpacket
->sname
, &buffer
[of2
], DHCP_SNAME_LEN
);
824 /* Now copy in preserved agent options, if any */
826 if (mb_size
- index
>= agent_size
) {
827 memcpy(&buffer
[index
], agentopts
, agent_size
);
830 log_error("Unable to store relay agent information "
834 /* Tack a DHO_END option onto the packet if we need to. */
836 buffer
[index
++] = DHO_END
;
838 /* Copy main buffer into the options buffer of the packet */
839 memcpy(outpacket
->options
, buffer
, index
);
841 /* Figure out the length. */
842 length
= DHCP_FIXED_NON_UDP
+ index
;
847 * XXX: We currently special case collecting VSIO options.
848 * We should be able to handle this in a more generic fashion, by
849 * including any encapsulated options that are present and desired.
850 * This will look something like the VSIO handling VSIO code.
851 * We may also consider handling the ORO-like options within
852 * encapsulated spaces.
862 vsio_options(struct option_cache
*oc
,
863 struct packet
*packet
,
864 struct lease
*dummy_lease
,
865 struct client_state
*dummy_client_state
,
866 struct option_state
*dummy_opt_state
,
867 struct option_state
*opt_state
,
868 struct binding_scope
**dummy_binding_scope
,
869 struct universe
*universe
,
870 void *void_vsio_state
) {
871 struct vsio_state
*vs
= (struct vsio_state
*)void_vsio_state
;
872 struct data_string ds
;
875 memset(&ds
, 0, sizeof(ds
));
876 if (evaluate_option_cache(&ds
, packet
, NULL
,
877 NULL
, opt_state
, NULL
,
878 &global_scope
, oc
, MDL
)) {
879 total_len
= ds
.len
+ universe
->tag_size
+ universe
->length_size
;
880 if (total_len
<= (vs
->buflen
- vs
->bufpos
)) {
881 if (universe
->tag_size
== 1) {
882 vs
->buf
[vs
->bufpos
++] = oc
->option
->code
;
883 } else if (universe
->tag_size
== 2) {
884 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
887 } else if (universe
->tag_size
== 4) {
888 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
892 if (universe
->length_size
== 1) {
893 vs
->buf
[vs
->bufpos
++] = ds
.len
;
894 } else if (universe
->length_size
== 2) {
895 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
898 } else if (universe
->length_size
== 4) {
899 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
903 memcpy(vs
->buf
+ vs
->bufpos
, ds
.data
, ds
.len
);
904 vs
->bufpos
+= ds
.len
;
906 log_debug("No space for option %d in VSIO space %s.",
907 oc
->option
->code
, universe
->name
);
909 data_string_forget(&ds
, MDL
);
911 log_error("Error evaluating option %d in VSIO space %s.",
912 oc
->option
->code
, universe
->name
);
917 * Stores the options from the DHCPv6 universe into the buffer given.
919 * Required options are given as a 0-terminated list of option codes.
920 * Once those are added, the ORO is consulted.
924 store_options6(char *buf
, int buflen
,
925 struct option_state
*opt_state
,
926 struct packet
*packet
,
927 const int *required_opts
,
928 struct data_string
*oro
) {
930 struct option_cache
*oc
;
932 struct data_string ds
;
936 int in_required_opts
;
937 int vsio_option_code
;
939 struct vsio_state vs
;
946 * Find the option code for the VSIO universe.
948 vsio_option_code
= 0;
949 o
= vsio_universe
.enc_opt
;
951 if (o
->universe
== &dhcpv6_universe
) {
952 vsio_option_code
= o
->code
;
955 o
= o
->universe
->enc_opt
;
957 if (vsio_option_code
== 0) {
958 log_fatal("No VSIO option code found.");
961 if (required_opts
!= NULL
) {
962 for (i
=0; required_opts
[i
] != 0; i
++) {
963 if (required_opts
[i
] == vsio_option_code
) {
967 oc
= lookup_option(&dhcpv6_universe
,
968 opt_state
, required_opts
[i
]);
972 memset(&ds
, 0, sizeof(ds
));
973 for (; oc
!= NULL
; oc
= oc
->next
) {
974 if (evaluate_option_cache(&ds
, packet
, NULL
,
980 tmp
= (unsigned char *)buf
;
986 putUShort(tmp
+2, ds
.len
);
988 memcpy(tmp
+4, ds
.data
, ds
.len
);
989 /* update position */
990 bufpos
+= (4 + ds
.len
);
992 log_debug("No space for "
996 data_string_forget(&ds
, MDL
);
998 log_error("Error evaluating option %d",
1008 oro_size
= oro
->len
/ 2;
1010 for (i
=0; i
<oro_size
; i
++) {
1011 memcpy(&code
, oro
->data
+(i
*2), 2);
1015 * See if we've already included this option because
1018 in_required_opts
= 0;
1019 if (required_opts
!= NULL
) {
1020 for (j
=0; required_opts
[j
] != 0; j
++) {
1021 if (required_opts
[j
] == code
) {
1022 in_required_opts
= 1;
1027 if (in_required_opts
) {
1032 * See if this is the VSIO option.
1034 if (code
== vsio_option_code
) {
1039 * Not already added, find this option.
1041 oc
= lookup_option(&dhcpv6_universe
, opt_state
, code
);
1042 memset(&ds
, 0, sizeof(ds
));
1043 for (; oc
!= NULL
; oc
= oc
->next
) {
1044 if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1046 &global_scope
, oc
, MDL
)) {
1047 if ((ds
.len
+ 4) <= (buflen
- bufpos
)) {
1048 tmp
= (unsigned char *)buf
+ bufpos
;
1050 putUShort(tmp
, code
);
1052 putUShort(tmp
+2, ds
.len
);
1054 memcpy(tmp
+4, ds
.data
, ds
.len
);
1055 /* update position */
1056 bufpos
+= (4 + ds
.len
);
1058 log_debug("No space for option %d",
1061 data_string_forget(&ds
, MDL
);
1063 log_error("Error evaluating option %d", code
);
1069 for (i
=0; i
< opt_state
->universe_count
; i
++) {
1070 if (opt_state
->universes
[i
] != NULL
) {
1071 o
= universes
[i
]->enc_opt
;
1073 (o
->universe
== &vsio_universe
)) {
1075 * Add the data from this VSIO option.
1079 vs
.bufpos
= bufpos
+8;
1080 option_space_foreach(packet
, NULL
,
1089 * If there was actually data here,
1092 if (vs
.bufpos
> bufpos
+8) {
1093 tmp
= (unsigned char *)buf
+
1098 vs
.bufpos
-bufpos
-4);
1099 putULong(tmp
+4, o
->code
);
1112 * Store all the requested options into the requested buffer.
1113 * XXX: ought to be static
1116 store_options(int *ocount
,
1117 unsigned char *buffer
, unsigned index
, unsigned buflen
,
1118 struct packet
*packet
, struct lease
*lease
,
1119 struct client_state
*client_state
,
1120 struct option_state
*in_options
,
1121 struct option_state
*cfg_options
,
1122 struct binding_scope
**scope
,
1123 unsigned *priority_list
, int priority_len
,
1124 unsigned first_cutoff
, int second_cutoff
, int terminate
,
1127 int bufix
= 0, six
= 0, tix
= 0;
1131 int bufend
, sbufend
;
1132 struct data_string od
;
1133 struct option_cache
*oc
;
1134 struct option
*option
= NULL
;
1138 * These arguments are relative to the start of the buffer, so
1139 * reduce them by the current buffer index, and advance the
1140 * buffer pointer to where we're going to start writing.
1142 buffer
= &buffer
[index
];
1145 first_cutoff
-= index
;
1147 second_cutoff
-= index
;
1149 /* Calculate the start and end of each section of the buffer */
1150 bufend
= sbufend
= buflen
;
1152 if (first_cutoff
>= buflen
)
1153 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
1154 bufend
= first_cutoff
;
1156 if (second_cutoff
) {
1157 if (second_cutoff
>= buflen
)
1158 log_fatal("%s:%d:store_options: Invalid second cutoff.",
1160 sbufend
= second_cutoff
;
1162 } else if (second_cutoff
) {
1163 if (second_cutoff
>= buflen
)
1164 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
1165 bufend
= second_cutoff
;
1168 memset (&od
, 0, sizeof od
);
1170 /* Eliminate duplicate options from the parameter request list.
1171 * Enforce RFC-mandated ordering of options that are present.
1173 for (i
= 0; i
< priority_len
; i
++) {
1174 /* Eliminate duplicates. */
1176 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
1178 priority_list
[ix
- tto
] =
1180 if (priority_list
[i
] == priority_list
[ix
]) {
1186 /* Enforce ordering of SUBNET_MASK options, according to
1187 * RFC2132 Section 3.3:
1189 * If both the subnet mask and the router option are
1190 * specified in a DHCP reply, the subnet mask option MUST
1193 * This guidance does not specify what to do if the client
1194 * PRL explicitly requests the options out of order, it is
1195 * a general statement.
1197 if (priority_list
[i
] == DHO_SUBNET_MASK
) {
1198 for (ix
= i
- 1 ; ix
>= 0 ; ix
--) {
1199 if (priority_list
[ix
] == DHO_ROUTERS
) {
1201 priority_list
[ix
] = DHO_SUBNET_MASK
;
1202 priority_list
[i
] = DHO_ROUTERS
;
1209 /* Copy out the options in the order that they appear in the
1211 for (i
= 0; i
< priority_len
; i
++) {
1212 /* Number of bytes left to store (some may already
1213 have been stored by a previous pass). */
1215 int optstart
, soptstart
, toptstart
;
1217 int have_encapsulation
= 0;
1218 struct data_string encapsulation
;
1221 memset (&encapsulation
, 0, sizeof encapsulation
);
1222 have_encapsulation
= 0;
1225 option_dereference(&option
, MDL
);
1227 /* Code for next option to try to store. */
1228 code
= priority_list
[i
];
1230 /* Look up the option in the site option space if the code
1231 is above the cutoff, otherwise in the DHCP option space. */
1232 if (code
>= cfg_options
-> site_code_min
)
1233 u
= universes
[cfg_options
-> site_universe
];
1237 oc
= lookup_option (u
, cfg_options
, code
);
1239 if (oc
&& oc
->option
)
1240 option_reference(&option
, oc
->option
, MDL
);
1242 option_code_hash_lookup(&option
, u
->code_hash
, &code
, 0, MDL
);
1244 /* If it's a straight encapsulation, and the user supplied a
1245 * value for the entire option, use that. Otherwise, search
1246 * the encapsulated space.
1248 * If it's a limited encapsulation with preceding data, and the
1249 * user supplied values for the preceding bytes, search the
1250 * encapsulated space.
1252 if ((option
!= NULL
) &&
1253 (((oc
== NULL
) && (option
->format
[0] == 'E')) ||
1254 ((oc
!= NULL
) && (option
->format
[0] == 'e')))) {
1256 struct option_cache
*tmp
;
1257 struct data_string name
;
1259 s
= strchr (option
->format
, 'E');
1261 t
= strchr (++s
, '.');
1263 memset (&name
, 0, sizeof name
);
1265 /* A zero-length universe name means the vendor
1266 option space, if one is defined. */
1268 if (vendor_cfg_option
) {
1269 tmp
= lookup_option (vendor_cfg_option
-> universe
,
1271 vendor_cfg_option
-> code
);
1273 /* No need to check the return as we check name.len below */
1274 (void) evaluate_option_cache (&name
, packet
, lease
,
1279 } else if (vuname
) {
1280 name
.data
= (unsigned char *)s
;
1281 name
.len
= strlen (s
);
1284 name
.data
= (unsigned char *)s
;
1288 /* If we found a universe, and there are options configured
1289 for that universe, try to encapsulate it. */
1291 have_encapsulation
=
1292 (option_space_encapsulate
1293 (&encapsulation
, packet
, lease
, client_state
,
1294 in_options
, cfg_options
, scope
, &name
));
1295 data_string_forget (&name
, MDL
);
1300 /* In order to avoid memory leaks, we have to get to here
1301 with any option cache that we allocated in tmp not being
1302 referenced by tmp, and whatever option cache is referenced
1303 by oc being an actual reference. lookup_option doesn't
1304 generate a reference (this needs to be fixed), so the
1305 preceding goop ensures that if we *didn't* generate a new
1306 option cache, oc still winds up holding an actual reference. */
1308 /* If no data is available for this option, skip it. */
1309 if (!oc
&& !have_encapsulation
) {
1313 /* Find the value of the option... */
1316 /* No need to check the return as we check od.len below */
1317 (void) evaluate_option_cache (&od
, packet
,
1318 lease
, client_state
, in_options
,
1319 cfg_options
, scope
, oc
, MDL
);
1321 /* If we have encapsulation for this option, and an oc
1322 * lookup succeeded, but the evaluation failed, it is
1323 * either because this is a complex atom (atoms before
1324 * E on format list) and the top half of the option is
1325 * not configured, or this is a simple encapsulated
1326 * space and the evaluator is giving us a NULL. Prefer
1327 * the evaluator's opinion over the subspace.
1330 data_string_forget (&encapsulation
, MDL
);
1331 data_string_forget (&od
, MDL
);
1336 /* We should now have a constant length for the option. */
1338 if (have_encapsulation
) {
1339 length
+= encapsulation
.len
;
1341 /* od.len can be nonzero if we got here without an
1342 * oc (cache lookup failed), but did have an encapsulated
1343 * simple encapsulation space.
1346 data_string_copy (&od
, &encapsulation
, MDL
);
1347 data_string_forget (&encapsulation
, MDL
);
1349 struct buffer
*bp
= (struct buffer
*)0;
1350 if (!buffer_allocate (&bp
, length
, MDL
)) {
1351 option_cache_dereference (&oc
, MDL
);
1352 data_string_forget (&od
, MDL
);
1353 data_string_forget (&encapsulation
, MDL
);
1356 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
1357 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
1359 data_string_forget (&od
, MDL
);
1360 data_string_forget (&encapsulation
, MDL
);
1361 od
.data
= &bp
-> data
[0];
1362 buffer_reference (&od
.buffer
, bp
, MDL
);
1363 buffer_dereference (&bp
, MDL
);
1369 /* Do we add a NUL? */
1370 if (terminate
&& option
&& format_has_text(option
->format
)) {
1377 /* Try to store the option. */
1379 /* If the option's length is more than 255, we must store it
1380 in multiple hunks. Store 255-byte hunks first. However,
1381 in any case, if the option data will cross a buffer
1382 boundary, split it across that boundary. */
1394 unsigned incr
= length
;
1396 unsigned char *base
;
1398 /* Try to fit it in the options buffer. */
1400 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
1401 (bufix
+ 2 + length
< bufend
)) ||
1402 (bufix
+ 5 + length
< bufend
))) {
1405 /* Try to fit it in the second buffer. */
1406 } else if (!splitup
&& first_cutoff
&&
1407 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
1408 base
= &buffer
[first_cutoff
];
1410 /* Try to fit it in the third buffer. */
1411 } else if (!splitup
&& second_cutoff
&&
1412 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
1413 base
= &buffer
[second_cutoff
];
1415 /* Split the option up into the remaining space. */
1419 /* Use any remaining options space. */
1420 if (bufix
+ 6 < bufend
) {
1421 incr
= bufend
- bufix
- 5;
1424 /* Use any remaining first_cutoff space. */
1425 } else if (first_cutoff
&&
1426 (first_cutoff
+ six
+ 4 < sbufend
)) {
1427 incr
= sbufend
- (first_cutoff
+ six
) - 3;
1428 base
= &buffer
[first_cutoff
];
1430 /* Use any remaining second_cutoff space. */
1431 } else if (second_cutoff
&&
1432 (second_cutoff
+ tix
+ 4 < buflen
)) {
1433 incr
= buflen
- (second_cutoff
+ tix
) - 3;
1434 base
= &buffer
[second_cutoff
];
1436 /* Give up, roll back this option. */
1450 /* Everything looks good - copy it in! */
1452 base
[*pix
+ 1] = (unsigned char)incr
;
1453 if (tto
&& incr
== length
) {
1455 memcpy (base
+ *pix
+ 2,
1456 od
.data
+ ix
, (unsigned)(incr
- 1));
1457 base
[*pix
+ 2 + incr
- 1] = 0;
1459 memcpy (base
+ *pix
+ 2,
1460 od
.data
+ ix
, (unsigned)incr
);
1466 data_string_forget (&od
, MDL
);
1470 option_dereference(&option
, MDL
);
1472 /* If we can overload, and we have, then PAD and END those spaces. */
1473 if (first_cutoff
&& six
) {
1474 if ((first_cutoff
+ six
+ 1) < sbufend
)
1475 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1476 sbufend
- (first_cutoff
+ six
+ 1));
1477 else if (first_cutoff
+ six
>= sbufend
)
1478 log_fatal("Second buffer overflow in overloaded options.");
1480 buffer
[first_cutoff
+ six
] = DHO_END
;
1482 *ocount
|= 1; /* So that caller knows there's data there. */
1485 if (second_cutoff
&& tix
) {
1486 if (second_cutoff
+ tix
+ 1 < buflen
) {
1487 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1488 buflen
- (second_cutoff
+ tix
+ 1));
1489 } else if (second_cutoff
+ tix
>= buflen
)
1490 log_fatal("Third buffer overflow in overloaded options.");
1492 buffer
[second_cutoff
+ tix
] = DHO_END
;
1494 *ocount
|= 2; /* So that caller knows there's data there. */
1497 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1498 log_fatal("Not enough space for option overload option.");
1503 /* Return true if the format string has a variable length text option
1504 * ("t"), return false otherwise.
1508 format_has_text(format
)
1514 while (*p
!= '\0') {
1520 /* These symbols are arbitrary, not fixed or
1521 * determinable length...text options with them is
1522 * invalid (whatever the case, they are never NULL
1533 /* 'c' only follows 'D' atoms, and indicates that
1534 * compression may be used. If there was a 'D'
1535 * atom already, we would have returned. So this
1536 * is an error, but continue looking for 't' anyway.
1538 log_error("format_has_text(%s): 'c' atoms are illegal "
1539 "except after 'D' atoms.", format
);
1542 /* 'E' is variable length, but not arbitrary...you
1543 * can find its length if you can find an END option.
1544 * N is (n)-byte in length but trails a name of a
1545 * space defining the enumeration values. So treat
1546 * both the same - valid, fixed-length fields.
1550 /* Consume the space name. */
1551 while ((*p
!= '\0') && (*p
++ != '.'))
1563 /* Determine the minimum length of a DHCP option prior to any variable
1564 * or inconsistent length formats, according to its configured format
1565 * variable (and possibly from supplied option cache contents for variable
1566 * length format symbols).
1570 format_min_length(format
, oc
)
1572 struct option_cache
*oc
;
1574 const char *p
, *name
;
1577 struct enumeration
*espace
;
1580 while (*p
!= '\0') {
1582 case '6': /* IPv6 Address */
1587 case 'I': /* IPv4 Address */
1588 case 'l': /* int32_t */
1589 case 'L': /* uint32_t */
1590 case 'T': /* Lease Time, uint32_t equivalent */
1595 case 's': /* int16_t */
1596 case 'S': /* uint16_t */
1601 case 'N': /* Enumeration value. */
1602 /* Consume space name. */
1606 log_fatal("Corrupt format: %s", format
);
1608 espace
= find_enumeration(name
, p
- name
);
1609 if (espace
== NULL
) {
1610 log_error("Unknown enumeration: %s", format
);
1611 /* Max is safest value to return. */
1615 min_len
+= espace
->width
;
1616 last_size
= espace
->width
;
1621 case 'b': /* int8_t */
1622 case 'B': /* uint8_t */
1623 case 'F': /* Flag that is always true. */
1624 case 'f': /* Flag */
1629 case 'o': /* Last argument is optional. */
1630 min_len
-= last_size
;
1632 /* XXX: It MAY be possible to sense the end of an
1633 * encapsulated space, but right now this is too
1634 * hard to support. Return a safe value.
1636 case 'e': /* Encapsulation hint (there is an 'E' later). */
1637 case 'E': /* Encapsulated options. */
1640 case 'd': /* "Domain name" */
1641 case 'D': /* "rfc1035 formatted names" */
1642 case 't': /* "ASCII Text" */
1643 case 'X': /* "ASCII or Hex Conditional */
1644 case 'x': /* "Hex" */
1645 case 'A': /* Array of all that precedes. */
1646 case 'a': /* Array of preceding symbol. */
1647 case 'Z': /* nothing. */
1650 case 'c': /* Compress flag for D atom. */
1651 log_error("format_min_length(%s): 'c' atom is illegal "
1652 "except after 'D' atom.", format
);
1656 /* No safe value is known. */
1657 log_error("format_min_length(%s): No safe value "
1658 "for unknown format symbols.", format
);
1667 /* Format the specified option so that a human can easily read it. */
1669 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1670 struct option
*option
;
1671 const unsigned char *data
;
1676 static char optbuf
[32768]; /* XXX */
1677 static char *endbuf
= &optbuf
[sizeof(optbuf
)];
1685 char fmtbuf
[32] = "";
1687 struct enumeration
*enumbuf
[32]; /* MUST be same as fmtbuf */
1689 const unsigned char *dp
= data
;
1692 isc_boolean_t a_array
= ISC_FALSE
;
1700 memset (enumbuf
, 0, sizeof enumbuf
);
1702 /* Figure out the size of the data. */
1703 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1704 if (l
>= sizeof(fmtbuf
) - 1)
1705 log_fatal("Bounds failure on internal buffer at "
1709 log_error ("%s: Extra codes in format string: %s",
1711 &(option
-> format
[i
]));
1715 fmtbuf
[l
] = option
-> format
[i
];
1716 switch (option
-> format
[i
]) {
1726 /* Skip the universe name. */
1727 while (option
-> format
[i
] &&
1728 option
-> format
[i
] != '.')
1732 for (k
= 0; k
< len
; k
++) {
1733 if (!isascii (data
[k
]) ||
1734 !isprint (data
[k
]))
1737 /* If we found no bogus characters, or the bogus
1738 character we found is a trailing NUL, it's
1739 okay to print this option as text. */
1740 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1754 /* The 'c' atom is a 'D' modifier only. */
1755 log_error("'c' atom not following D atom in format "
1756 "string: %s", option
->format
);
1760 * Skip the 'c' atom, if present. It does not affect
1761 * how we convert wire->text format (if compression is
1762 * present either way, we still process it).
1764 if (option
->format
[i
+1] == 'c')
1771 /* Fall Through ! */
1778 while (option
-> format
[i
] &&
1779 option
-> format
[i
] != '.')
1782 find_enumeration (&option
-> format
[k
] + 1,
1784 if (enumbuf
[l
] == NULL
) {
1788 hunksize
+= enumbuf
[l
]->width
;
1789 hunkinc
= enumbuf
[l
]->width
;
1822 log_error ("%s: garbage in format string: %s",
1824 &(option
-> format
[i
]));
1829 /* Check for too few bytes... */
1830 if (hunksize
- opthunk
> len
) {
1831 log_error ("%s: expecting at least %d bytes; got %d",
1836 /* Check for too many bytes... */
1837 if (numhunk
== -1 && hunksize
< len
)
1838 log_error ("%s: %d extra bytes",
1842 /* If this is an array, compute its size. */
1844 if (a_array
== ISC_TRUE
) {
1846 * It is an 'a' type array - we repeat the
1847 * last format type. A binary string for 'X'
1848 * is also like this. hunkinc is the size
1849 * of the last format type and we add 1 to
1850 * cover the entire first record.
1853 /* If format string had no valid entries prior to
1854 * 'a' hunkinc will be 0. Ex: "a", "oa", "aA" */
1856 log_error ("%s: invalid 'a' format: %s",
1857 option
->name
, option
->format
);
1861 numhunk
= ((len
- hunksize
) / hunkinc
) + 1;
1862 len_used
= hunksize
+ ((numhunk
- 1) * hunkinc
);
1865 * It is an 'A' type array - we repeat the
1869 /* If format string had no valid entries prior to
1870 * 'A' hunksize will be 0. Ex: "A", "oA", "foA" */
1871 if (hunksize
== 0) {
1872 log_error ("%s: invalid 'A' format: %s",
1873 option
->name
, option
->format
);
1877 numhunk
= len
/ hunksize
;
1878 len_used
= numhunk
* hunksize
;
1881 /* See if we got an exact number of hunks. */
1882 if (len_used
< len
) {
1883 log_error ("%s: %d extra bytes at end of array\n",
1890 /* A one-hunk array prints the same as a single hunk. */
1894 /* Cycle through the array (or hunk) printing the data. */
1895 for (i
= 0; i
< numhunk
; i
++) {
1896 if ((a_array
== ISC_TRUE
) && (i
!= 0) && (numelem
> 0)) {
1898 * For 'a' type of arrays we repeat
1899 * only the last format character
1900 * We should never hit the case of numelem == 0
1901 * but let's include the check to be safe.
1906 * for other types of arrays or the first
1907 * time through for 'a' types, we go through
1908 * the entire set of format characters.
1913 for (; j
< numelem
; j
++) {
1914 switch (fmtbuf
[j
]) {
1916 /* endbuf-1 leaves room for NULL. */
1917 k
= pretty_text(&op
, endbuf
- 1, &dp
,
1918 data
+ len
, emit_quotes
);
1920 log_error("Error printing text.");
1925 case 'D': /* RFC1035 format name list */
1926 for( ; dp
< (data
+ len
) ; dp
+= k
) {
1927 unsigned char nbuff
[NS_MAXCDNAME
];
1928 const unsigned char *nbp
, *nend
;
1930 nend
= &nbuff
[sizeof(nbuff
)];
1932 /* If this is for ISC DHCP consumption
1933 * (emit_quotes), lay it out as a list
1934 * of STRING tokens. Otherwise, it is
1935 * a space-separated list of DNS-
1936 * escaped names as /etc/resolv.conf
1940 if (op
+ 2 > endbuf
)
1948 /* XXX: if fmtbuf[j+1] != 'c', we
1949 * should warn if the data was
1950 * compressed anyway.
1952 k
= MRns_name_unpack(data
,
1958 log_error("Invalid domain "
1963 /* If emit_quotes, then use ISC DHCP
1964 * escapes. Otherwise, rely only on
1969 pretty_domain(&op
, endbuf
-1,
1972 /* ns_name_ntop() includes
1973 * a trailing NUL in its
1976 count
= MRns_name_ntop(
1981 log_error("Invalid "
1986 /* Consume all but the trailing
1991 /* Replace the trailing NUL
1992 * with the implicit root
1993 * (in the unlikely event the
1994 * domain name /is/ the root).
2001 /* pretty-printing an array of enums is
2002 going to get ugly. */
2009 switch (enumbuf
[j
]->width
) {
2011 tval
= getUChar(dp
);
2015 tval
= getUShort(dp
);
2019 tval
= getULong(dp
);
2023 log_fatal("Impossible case at %s:%d.",
2025 return "<double impossible condition>";
2029 if (!enumbuf
[j
] -> values
[i
].name
)
2031 if (enumbuf
[j
] -> values
[i
].value
==
2035 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
2036 dp
+= enumbuf
[j
]->width
;
2040 sprintf(op
, "%lu", tval
);
2045 memcpy(iaddr
.iabuf
, dp
, 4);
2046 strcpy(op
, piaddr(iaddr
));
2051 memcpy(iaddr
.iabuf
, dp
, 16);
2052 strcpy(op
, piaddr(iaddr
));
2056 sprintf (op
, "%ld", (long)getLong (dp
));
2060 tval
= getULong (dp
);
2062 sprintf (op
, "%s", "infinite");
2064 sprintf(op
, "%lu", tval
);
2068 (unsigned long)getULong(dp
));
2072 sprintf (op
, "%d", (int)getShort (dp
));
2076 sprintf(op
, "%u", (unsigned)getUShort(dp
));
2080 sprintf (op
, "%d", *(const char *)dp
++);
2083 sprintf (op
, "%d", *dp
++);
2087 sprintf (op
, "%x", *dp
++);
2090 strcpy (op
, *dp
++ ? "true" : "false");
2093 strcpy (op
, "true");
2100 log_error ("Unexpected format code %c",
2104 if (dp
== data
+ len
)
2106 if (j
+ 1 < numelem
&& comma
!= ':')
2109 if (i
+ 1 < numhunk
) {
2112 if (dp
== data
+ len
)
2118 int get_option (result
, universe
, packet
, lease
, client_state
,
2119 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2120 struct data_string
*result
;
2121 struct universe
*universe
;
2122 struct packet
*packet
;
2123 struct lease
*lease
;
2124 struct client_state
*client_state
;
2125 struct option_state
*in_options
;
2126 struct option_state
*cfg_options
;
2127 struct option_state
*options
;
2128 struct binding_scope
**scope
;
2133 struct option_cache
*oc
;
2135 if (!universe
-> lookup_func
)
2137 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
2140 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
2141 in_options
, cfg_options
, scope
, oc
,
2148 * Look for the option and dig out the value assoicated with it.
2149 * Currently this is used for 1 byte integers, it maybe expanded
2150 * in the future to handle other integers at which point it will
2151 * need a size argument.
2153 int get_option_int (result
, universe
, packet
, lease
, client_state
,
2154 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2156 struct universe
*universe
;
2157 struct packet
*packet
;
2158 struct lease
*lease
;
2159 struct client_state
*client_state
;
2160 struct option_state
*in_options
;
2161 struct option_state
*cfg_options
;
2162 struct option_state
*options
;
2163 struct binding_scope
**scope
;
2168 struct option_cache
*oc
;
2169 struct data_string d1
;
2172 /* basic sanity checks */
2173 if ((options
== NULL
) || (universe
->lookup_func
== NULL
))
2176 /* find the option cache */
2177 oc
= ((*universe
->lookup_func
)(universe
, options
, code
));
2181 /* if there is a value get it into the string */
2182 memset(&d1
, 0, sizeof(d1
));
2183 if (!evaluate_option_cache(&d1
, packet
, lease
, client_state
,
2184 in_options
, cfg_options
, scope
, oc
,
2188 /* If the length matches extract the value for the return */
2190 *result
= d1
.data
[0];
2193 data_string_forget(&d1
, MDL
);
2198 void set_option (universe
, options
, option
, op
)
2199 struct universe
*universe
;
2200 struct option_state
*options
;
2201 struct option_cache
*option
;
2202 enum statement_op op
;
2204 struct option_cache
*oc
, *noc
;
2209 case eval_statement
:
2210 case break_statement
:
2212 log_error ("bogus statement type in set_option.");
2215 case default_option_statement
:
2216 oc
= lookup_option (universe
, options
,
2217 option
-> option
-> code
);
2220 save_option (universe
, options
, option
);
2223 case supersede_option_statement
:
2224 case send_option_statement
:
2225 /* Install the option, replacing any existing version. */
2226 save_option (universe
, options
, option
);
2229 case append_option_statement
:
2230 case prepend_option_statement
:
2231 oc
= lookup_option (universe
, options
,
2232 option
-> option
-> code
);
2234 save_option (universe
, options
, option
);
2237 /* If it's not an expression, make it into one. */
2238 if (!oc
-> expression
&& oc
-> data
.len
) {
2239 if (!expression_allocate (&oc
-> expression
, MDL
)) {
2240 log_error ("Can't allocate const expression.");
2243 oc
-> expression
-> op
= expr_const_data
;
2245 (&oc
-> expression
-> data
.const_data
,
2247 data_string_forget (&oc
-> data
, MDL
);
2249 noc
= (struct option_cache
*)0;
2250 if (!option_cache_allocate (&noc
, MDL
))
2252 if (op
== append_option_statement
) {
2253 if (!make_concat (&noc
-> expression
,
2255 option
-> expression
)) {
2256 option_cache_dereference (&noc
, MDL
);
2260 if (!make_concat (&noc
-> expression
,
2261 option
-> expression
,
2262 oc
-> expression
)) {
2263 option_cache_dereference (&noc
, MDL
);
2267 option_reference(&(noc
->option
), oc
->option
, MDL
);
2268 save_option (universe
, options
, noc
);
2269 option_cache_dereference (&noc
, MDL
);
2274 struct option_cache
*lookup_option (universe
, options
, code
)
2275 struct universe
*universe
;
2276 struct option_state
*options
;
2280 return (struct option_cache
*)0;
2281 if (universe
-> lookup_func
)
2282 return (*universe
-> lookup_func
) (universe
, options
, code
);
2284 log_error ("can't look up options in %s space.",
2286 return (struct option_cache
*)0;
2289 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
2290 struct universe
*universe
;
2291 struct option_state
*options
;
2298 /* Make sure there's a hash table. */
2299 if (universe
-> index
>= options
-> universe_count
||
2300 !(options
-> universes
[universe
-> index
]))
2301 return (struct option_cache
*)0;
2303 hash
= options
-> universes
[universe
-> index
];
2305 hashix
= compute_option_hash (code
);
2306 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2307 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
2309 return (struct option_cache
*)(bptr
-> car
);
2311 return (struct option_cache
*)0;
2314 /* Save a specified buffer into an option cache. */
2316 save_option_buffer(struct universe
*universe
, struct option_state
*options
,
2317 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2318 unsigned code
, int terminatep
)
2320 struct option_cache
*op
= NULL
;
2323 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2329 save_option(universe
, options
, op
);
2333 option_cache_dereference(&op
, MDL
);
2338 /* Append a specified buffer onto the tail of an option cache. */
2340 append_option_buffer(struct universe
*universe
, struct option_state
*options
,
2341 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2342 unsigned code
, int terminatep
)
2344 struct option_cache
*op
= NULL
;
2347 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2353 also_save_option(universe
, options
, op
);
2357 option_cache_dereference(&op
, MDL
);
2362 /* Create/copy a buffer into a new option cache. */
2364 prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
2365 unsigned char *buffer
, unsigned length
, unsigned code
,
2366 int terminatep
, struct option_cache
**opp
)
2368 struct buffer
*lbp
= NULL
;
2369 struct option
*option
= NULL
;
2370 struct option_cache
*op
;
2373 /* Code sizes of 8, 16, and 32 bits are allowed. */
2374 switch(universe
->tag_size
) {
2384 if (code
> 0xffffffff)
2389 log_fatal("Inconsistent universe tag size at %s:%d.", MDL
);
2392 option_code_hash_lookup(&option
, universe
->code_hash
, &code
, 0, MDL
);
2394 /* If we created an option structure for each option a client
2395 * supplied, it's possible we may create > 2^32 option structures.
2396 * That's not feasible. So by failing to enter these option
2397 * structures into the code and name hash tables, references will
2398 * never be more than 1 - when the option cache is destroyed, this
2399 * will be cleaned up.
2402 char nbuf
[sizeof("unknown-4294967295")];
2404 sprintf(nbuf
, "unknown-%u", code
);
2406 option
= new_option(nbuf
, MDL
);
2411 option
->format
= default_option_format
;
2412 option
->universe
= universe
;
2413 option
->code
= code
;
2415 /* new_option() doesn't set references, pretend. */
2419 if (!option_cache_allocate (opp
, MDL
)) {
2420 log_error("No memory for option code %s.%s.",
2421 universe
->name
, option
->name
);
2426 /* Pointer rather than double pointer makes for less parens. */
2429 option_reference(&op
->option
, option
, MDL
);
2431 /* If we weren't passed a buffer in which the data are saved and
2432 refcounted, allocate one now. */
2434 if (!buffer_allocate (&lbp
, length
+ terminatep
, MDL
)) {
2435 log_error ("no memory for option buffer.");
2440 memcpy (lbp
-> data
, buffer
, length
+ terminatep
);
2442 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
2445 /* Reference buffer copy to option cache. */
2446 op
-> data
.buffer
= (struct buffer
*)0;
2447 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
2449 /* Point option cache into buffer. */
2450 op
-> data
.data
= buffer
;
2451 op
-> data
.len
= length
;
2454 /* NUL terminate (we can get away with this because we (or
2455 the caller!) allocated one more than the buffer size, and
2456 because the byte following the end of an option is always
2457 the code of the next option, which the caller is getting
2458 out of the *original* buffer. */
2459 buffer
[length
] = 0;
2460 op
-> data
.terminated
= 1;
2462 op
-> data
.terminated
= 0;
2464 /* If this option is ultimately a text option, null determinate to
2465 * comply with RFC2132 section 2. Mark a flag so this can be sensed
2466 * later to echo NULLs back to clients that supplied them (they
2467 * probably expect them).
2469 if (format_has_text(option
->format
)) {
2470 int min_len
= format_min_length(option
->format
, op
);
2472 while ((op
->data
.len
> min_len
) &&
2473 (op
->data
.data
[op
->data
.len
-1] == '\0')) {
2475 op
->flags
|= OPTION_HAD_NULLS
;
2479 /* And let go of our references. */
2482 buffer_dereference(&lbp
, MDL
);
2483 option_dereference(&option
, MDL
);
2489 count_options(struct option_cache
*dummy_oc
,
2490 struct packet
*dummy_packet
,
2491 struct lease
*dummy_lease
,
2492 struct client_state
*dummy_client_state
,
2493 struct option_state
*dummy_opt_state
,
2494 struct option_state
*opt_state
,
2495 struct binding_scope
**dummy_binding_scope
,
2496 struct universe
*dummy_universe
,
2497 void *void_accumulator
) {
2498 int *accumulator
= (int *)void_accumulator
;
2504 collect_oro(struct option_cache
*oc
,
2505 struct packet
*dummy_packet
,
2506 struct lease
*dummy_lease
,
2507 struct client_state
*dummy_client_state
,
2508 struct option_state
*dummy_opt_state
,
2509 struct option_state
*opt_state
,
2510 struct binding_scope
**dummy_binding_scope
,
2511 struct universe
*dummy_universe
,
2513 struct data_string
*oro
= (struct data_string
*)void_oro
;
2515 putUShort(oro
->buffer
->data
+ oro
->len
, oc
->option
->code
);
2519 /* build_server_oro() is presently unusued, but may be used at a future date
2520 * with support for Reconfigure messages (as a hint to the client about new
2521 * option value contents).
2524 build_server_oro(struct data_string
*server_oro
,
2525 struct option_state
*options
,
2526 const char *file
, int line
) {
2532 * Count the number of options, so we can allocate enough memory.
2533 * We want to mention sub-options too, so check all universes.
2536 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2537 NULL
, &dhcpv6_universe
, (void *)&num_opts
,
2539 for (i
=0; i
< options
->universe_count
; i
++) {
2540 if (options
->universes
[i
] != NULL
) {
2541 o
= universes
[i
]->enc_opt
;
2543 if (o
->universe
== &dhcpv6_universe
) {
2547 o
= o
->universe
->enc_opt
;
2555 memset(server_oro
, 0, sizeof(*server_oro
));
2556 if (!buffer_allocate(&server_oro
->buffer
, num_opts
* 2, MDL
)) {
2557 log_fatal("no memory to build server ORO");
2559 server_oro
->data
= server_oro
->buffer
->data
;
2563 * We want to mention sub-options too, so check all universes.
2565 server_oro
->len
= 0; /* gets set in collect_oro */
2566 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2567 NULL
, &dhcpv6_universe
, (void *)server_oro
,
2569 for (i
=0; i
< options
->universe_count
; i
++) {
2570 if (options
->universes
[i
] != NULL
) {
2571 o
= universes
[i
]->enc_opt
;
2573 if (o
->universe
== &dhcpv6_universe
) {
2575 tmp
= server_oro
->buffer
->data
;
2576 putUShort(tmp
+ server_oro
->len
,
2578 server_oro
->len
+= 2;
2581 o
= o
->universe
->enc_opt
;
2587 /* Wrapper function to put an option cache into an option state. */
2589 save_option(struct universe
*universe
, struct option_state
*options
,
2590 struct option_cache
*oc
)
2592 if (universe
->save_func
)
2593 (*universe
->save_func
)(universe
, options
, oc
, ISC_FALSE
);
2595 log_error("can't store options in %s space.", universe
->name
);
2598 /* Wrapper function to append an option cache into an option state's list. */
2600 also_save_option(struct universe
*universe
, struct option_state
*options
,
2601 struct option_cache
*oc
)
2603 if (universe
->save_func
)
2604 (*universe
->save_func
)(universe
, options
, oc
, ISC_TRUE
);
2606 log_error("can't store options in %s space.", universe
->name
);
2610 save_hashed_option(struct universe
*universe
, struct option_state
*options
,
2611 struct option_cache
*oc
, isc_boolean_t appendp
)
2615 pair
*hash
= options
-> universes
[universe
-> index
];
2616 struct option_cache
**ocloc
;
2618 if (oc
-> refcnt
== 0)
2621 /* Compute the hash. */
2622 hashix
= compute_option_hash (oc
-> option
-> code
);
2624 /* If there's no hash table, make one. */
2626 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
2628 log_error ("no memory to store %s.%s",
2629 universe
-> name
, oc
-> option
-> name
);
2632 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
2633 options
-> universes
[universe
-> index
] = (void *)hash
;
2635 /* Try to find an existing option matching the new one. */
2636 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2637 if (((struct option_cache
*)
2638 (bptr
-> car
)) -> option
-> code
==
2639 oc
-> option
-> code
)
2643 /* Deal with collisions on the hash list. */
2645 ocloc
= (struct option_cache
**)&bptr
->car
;
2648 * If appendp is set, append it onto the tail of the
2649 * ->next list. If it is not set, rotate it into
2650 * position at the head of the list.
2654 ocloc
= &(*ocloc
)->next
;
2655 } while (*ocloc
!= NULL
);
2657 option_cache_dereference(ocloc
, MDL
);
2660 option_cache_reference(ocloc
, oc
, MDL
);
2665 /* Otherwise, just put the new one at the head of the list. */
2666 bptr
= new_pair (MDL
);
2668 log_error ("No memory for option_cache reference.");
2671 bptr
-> cdr
= hash
[hashix
];
2673 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
2674 hash
[hashix
] = bptr
;
2677 void delete_option (universe
, options
, code
)
2678 struct universe
*universe
;
2679 struct option_state
*options
;
2682 if (universe
-> delete_func
)
2683 (*universe
-> delete_func
) (universe
, options
, code
);
2685 log_error ("can't delete options from %s space.",
2689 void delete_hashed_option (universe
, options
, code
)
2690 struct universe
*universe
;
2691 struct option_state
*options
;
2695 pair bptr
, prev
= (pair
)0;
2696 pair
*hash
= options
-> universes
[universe
-> index
];
2698 /* There may not be any options in this space. */
2702 /* Try to find an existing option matching the new one. */
2703 hashix
= compute_option_hash (code
);
2704 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2705 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
2710 /* If we found one, wipe it out... */
2713 prev
-> cdr
= bptr
-> cdr
;
2715 hash
[hashix
] = bptr
-> cdr
;
2716 option_cache_dereference
2717 ((struct option_cache
**)(&bptr
-> car
), MDL
);
2718 free_pair (bptr
, MDL
);
2722 extern struct option_cache
*free_option_caches
; /* XXX */
2724 int option_cache_dereference (ptr
, file
, line
)
2725 struct option_cache
**ptr
;
2729 if (!ptr
|| !*ptr
) {
2730 log_error ("Null pointer in option_cache_dereference: %s(%d)",
2732 #if defined (POINTER_DEBUG)
2740 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
2741 if (!(*ptr
) -> refcnt
) {
2742 if ((*ptr
) -> data
.buffer
)
2743 data_string_forget (&(*ptr
) -> data
, file
, line
);
2745 option_dereference(&(*ptr
)->option
, MDL
);
2746 if ((*ptr
) -> expression
)
2747 expression_dereference (&(*ptr
) -> expression
,
2750 option_cache_dereference (&((*ptr
) -> next
),
2752 /* Put it back on the free list... */
2753 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
2754 free_option_caches
= *ptr
;
2755 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
2757 if ((*ptr
) -> refcnt
< 0) {
2758 log_error ("%s(%d): negative refcnt!", file
, line
);
2759 #if defined (DEBUG_RC_HISTORY)
2760 dump_rc_history (*ptr
);
2762 #if defined (POINTER_DEBUG)
2765 *ptr
= (struct option_cache
*)0;
2769 *ptr
= (struct option_cache
*)0;
2774 int hashed_option_state_dereference (universe
, state
, file
, line
)
2775 struct universe
*universe
;
2776 struct option_state
*state
;
2784 /* Get the pointer to the array of hash table bucket heads. */
2785 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
2789 /* For each non-null head, loop through all the buckets dereferencing
2790 the attached option cache structures and freeing the buckets. */
2791 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2792 for (cp
= heads
[i
]; cp
; cp
= next
) {
2794 option_cache_dereference
2795 ((struct option_cache
**)&cp
-> car
,
2797 free_pair (cp
, file
, line
);
2801 dfree (heads
, file
, line
);
2802 state
-> universes
[universe
-> index
] = (void *)0;
2806 /* The 'data_string' primitive doesn't have an appension mechanism.
2807 * This function must then append a new option onto an existing buffer
2808 * by first duplicating the original buffer and appending the desired
2809 * values, followed by coping the new value into place.
2812 append_option(struct data_string
*dst
, struct universe
*universe
,
2813 struct option
*option
, struct data_string
*src
)
2815 struct data_string tmp
;
2817 if (src
->len
== 0 && option
->format
[0] != 'Z')
2820 memset(&tmp
, 0, sizeof(tmp
));
2822 /* Allocate a buffer to hold existing data, the current option's
2823 * tag and length, and the option's content.
2825 if (!buffer_allocate(&tmp
.buffer
,
2826 (dst
->len
+ universe
->length_size
+
2827 universe
->tag_size
+ src
->len
), MDL
)) {
2828 /* XXX: This kills all options presently stored in the
2829 * destination buffer. This is the way the original code
2830 * worked, and assumes an 'all or nothing' approach to
2831 * eg encapsulated option spaces. It may or may not be
2834 data_string_forget(dst
, MDL
);
2837 tmp
.data
= tmp
.buffer
->data
;
2839 /* Copy the existing data off the destination. */
2841 memcpy(tmp
.buffer
->data
, dst
->data
, dst
->len
);
2844 /* Place the new option tag and length. */
2845 (*universe
->store_tag
)(tmp
.buffer
->data
+ tmp
.len
, option
->code
);
2846 tmp
.len
+= universe
->tag_size
;
2847 (*universe
->store_length
)(tmp
.buffer
->data
+ tmp
.len
, src
->len
);
2848 tmp
.len
+= universe
->length_size
;
2850 /* Copy the option contents onto the end. */
2851 memcpy(tmp
.buffer
->data
+ tmp
.len
, src
->data
, src
->len
);
2852 tmp
.len
+= src
->len
;
2854 /* Play the shell game. */
2855 data_string_forget(dst
, MDL
);
2856 data_string_copy(dst
, &tmp
, MDL
);
2857 data_string_forget(&tmp
, MDL
);
2862 store_option(struct data_string
*result
, struct universe
*universe
,
2863 struct packet
*packet
, struct lease
*lease
,
2864 struct client_state
*client_state
,
2865 struct option_state
*in_options
, struct option_state
*cfg_options
,
2866 struct binding_scope
**scope
, struct option_cache
*oc
)
2868 struct data_string tmp
;
2869 struct universe
*subu
=NULL
;
2873 memset(&tmp
, 0, sizeof(tmp
));
2875 if (evaluate_option_cache(&tmp
, packet
, lease
, client_state
,
2876 in_options
, cfg_options
, scope
, oc
, MDL
)) {
2877 /* If the option is an extended 'e'ncapsulation (not a
2878 * direct 'E'ncapsulation), append the encapsulated space
2879 * onto the currently prepared value.
2882 if (oc
->option
->format
&&
2883 oc
->option
->format
[0] == 'e') {
2884 /* Skip forward to the universe name. */
2885 start
= strchr(oc
->option
->format
, 'E');
2889 /* Locate the name-terminating '.'. */
2890 end
= strchr(++start
, '.');
2892 /* A zero-length name is not allowed in
2893 * these kinds of encapsulations.
2895 if (end
== NULL
|| start
== end
)
2898 universe_hash_lookup(&subu
, universe_hash
,
2899 start
, end
- start
, MDL
);
2902 log_error("store_option: option %d "
2903 "refers to unknown "
2904 "option space '%.*s'.",
2906 (int)(end
- start
), start
);
2910 /* Append encapsulations, if any. We
2911 * already have the prepended values, so
2912 * we send those even if there are no
2913 * encapsulated options (and ->encapsulate()
2916 subu
->encapsulate(&tmp
, packet
, lease
,
2917 client_state
, in_options
,
2918 cfg_options
, scope
, subu
);
2921 } while (ISC_FALSE
);
2923 status
= append_option(result
, universe
, oc
->option
, &tmp
);
2924 data_string_forget(&tmp
, MDL
);
2932 int option_space_encapsulate (result
, packet
, lease
, client_state
,
2933 in_options
, cfg_options
, scope
, name
)
2934 struct data_string
*result
;
2935 struct packet
*packet
;
2936 struct lease
*lease
;
2937 struct client_state
*client_state
;
2938 struct option_state
*in_options
;
2939 struct option_state
*cfg_options
;
2940 struct binding_scope
**scope
;
2941 struct data_string
*name
;
2943 struct universe
*u
= NULL
;
2946 universe_hash_lookup(&u
, universe_hash
,
2947 (const char *)name
->data
, name
->len
, MDL
);
2949 log_error("option_space_encapsulate: option space '%.*s' does "
2950 "not exist, but is configured.",
2951 (int)name
->len
, name
->data
);
2955 if (u
->encapsulate
!= NULL
) {
2956 if (u
->encapsulate(result
, packet
, lease
, client_state
,
2957 in_options
, cfg_options
, scope
, u
))
2960 log_error("encapsulation requested for '%s' with no support.",
2966 /* Attempt to store any 'E'ncapsulated options that have not yet been
2967 * placed on the option buffer by the above (configuring a value in
2968 * the space over-rides any values in the child universe).
2970 * Note that there are far fewer universes than there will ever be
2971 * options in any universe. So it is faster to traverse the
2972 * configured universes, checking if each is encapsulated in the
2973 * current universe, and if so attempting to do so.
2975 * For each configured universe for this configuration option space,
2976 * which is encapsulated within the current universe, can not be found
2977 * by the lookup function (the universe-specific encapsulation
2978 * functions would already have stored such a value), and encapsulates
2979 * at least one option, append it.
2982 search_subencapsulation(struct data_string
*result
, struct packet
*packet
,
2983 struct lease
*lease
, struct client_state
*client_state
,
2984 struct option_state
*in_options
,
2985 struct option_state
*cfg_options
,
2986 struct binding_scope
**scope
,
2987 struct universe
*universe
)
2989 struct data_string sub
;
2990 struct universe
*subu
;
2993 memset(&sub
, 0, sizeof(sub
));
2994 for (i
= 0 ; i
< cfg_options
->universe_count
; i
++) {
2995 subu
= universes
[i
];
2998 log_fatal("Impossible condition at %s:%d.", MDL
);
3000 if (subu
->enc_opt
!= NULL
&&
3001 subu
->enc_opt
->universe
== universe
&&
3002 subu
->enc_opt
->format
!= NULL
&&
3003 subu
->enc_opt
->format
[0] == 'E' &&
3004 lookup_option(universe
, cfg_options
,
3005 subu
->enc_opt
->code
) == NULL
&&
3006 subu
->encapsulate(&sub
, packet
, lease
, client_state
,
3007 in_options
, cfg_options
,
3009 if (append_option(result
, universe
,
3010 subu
->enc_opt
, &sub
))
3013 data_string_forget(&sub
, MDL
);
3020 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
3021 in_options
, cfg_options
, scope
, universe
)
3022 struct data_string
*result
;
3023 struct packet
*packet
;
3024 struct lease
*lease
;
3025 struct client_state
*client_state
;
3026 struct option_state
*in_options
;
3027 struct option_state
*cfg_options
;
3028 struct binding_scope
**scope
;
3029 struct universe
*universe
;
3035 if (universe
-> index
>= cfg_options
-> universe_count
)
3038 hash
= cfg_options
-> universes
[universe
-> index
];
3042 /* For each hash bucket, and each configured option cache within
3043 * that bucket, append the option onto the buffer in encapsulated
3044 * format appropriate to the universe.
3047 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3048 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3049 if (store_option(result
, universe
, packet
, lease
,
3050 client_state
, in_options
, cfg_options
,
3051 scope
, (struct option_cache
*)p
->car
))
3056 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3057 in_options
, cfg_options
, scope
, universe
))
3063 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
3064 in_options
, cfg_options
, scope
, universe
)
3065 struct data_string
*result
;
3066 struct packet
*packet
;
3067 struct lease
*lease
;
3068 struct client_state
*client_state
;
3069 struct option_state
*in_options
;
3070 struct option_state
*cfg_options
;
3071 struct binding_scope
**scope
;
3072 struct universe
*universe
;
3076 static struct option_cache
*no_nwip
;
3077 struct data_string ds
;
3078 struct option_chain_head
*head
;
3080 if (universe
-> index
>= cfg_options
-> universe_count
)
3082 head
= ((struct option_chain_head
*)
3083 cfg_options
-> universes
[nwip_universe
.index
]);
3088 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3089 if (store_option (result
, universe
, packet
,
3090 lease
, client_state
, in_options
,
3092 (struct option_cache
*)ocp
-> car
))
3096 /* If there's no data, the nwip suboption is supposed to contain
3097 a suboption saying there's no data. */
3101 static unsigned char nni
[] = { 1, 0 };
3103 memset (&ds
, 0, sizeof ds
);
3106 if (option_cache_allocate (&no_nwip
, MDL
))
3107 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
3108 if (!option_code_hash_lookup(&no_nwip
->option
,
3109 nwip_universe
.code_hash
,
3111 log_fatal("Nwip option hash does not contain "
3115 if (store_option (result
, universe
, packet
, lease
,
3116 client_state
, in_options
,
3117 cfg_options
, scope
, no_nwip
))
3121 memset (&ds
, 0, sizeof ds
);
3123 /* If we have nwip options, the first one has to be the
3124 nwip-exists-in-option-area option. */
3125 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
3126 data_string_forget (result
, MDL
);
3129 ds
.data
= &ds
.buffer
-> data
[0];
3130 ds
.buffer
-> data
[0] = 2;
3131 ds
.buffer
-> data
[1] = 0;
3132 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
3133 data_string_forget (result
, MDL
);
3134 data_string_copy (result
, &ds
, MDL
);
3135 data_string_forget (&ds
, MDL
);
3141 /* We don't want to use ns_name_pton()...it doesn't tell us how many bytes
3142 * it has consumed, and it plays havoc with our escapes.
3144 * So this function does DNS encoding, and returns either the number of
3145 * octects consumed (on success), or -1 on failure.
3148 fqdn_encode(unsigned char *dst
, int dstlen
, const unsigned char *src
,
3152 int i
, j
, len
, outlen
=0;
3155 for (i
= 0, j
= 0 ; i
< srclen
; i
= j
) {
3156 while ((j
< srclen
) && (src
[j
] != '.') && (src
[j
] != '\0'))
3160 if ((outlen
+ 1 + len
) > dstlen
)
3166 /* We only do one FQDN, ending in one root label. */
3170 memcpy(out
, src
+ i
, len
);
3174 /* Advance past the root label. */
3178 if ((outlen
+ 1) > dstlen
)
3181 /* Place the root label. */
3188 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
3189 in_options
, cfg_options
, scope
, universe
)
3190 struct data_string
*result
;
3191 struct packet
*packet
;
3192 struct lease
*lease
;
3193 struct client_state
*client_state
;
3194 struct option_state
*in_options
;
3195 struct option_state
*cfg_options
;
3196 struct binding_scope
**scope
;
3197 struct universe
*universe
;
3200 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3204 struct buffer
*bp
= (struct buffer
*)0;
3205 struct option_chain_head
*head
;
3207 /* If there's no FQDN universe, don't encapsulate. */
3208 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
3210 head
= ((struct option_chain_head
*)
3211 cfg_options
-> universes
[fqdn_universe
.index
]);
3215 /* Figure out the values of all the suboptions. */
3216 memset (results
, 0, sizeof results
);
3217 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3218 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
3219 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
3221 /* No need to check the return code, we check the length later */
3222 (void) evaluate_option_cache (&results
[oc
->option
->code
],
3223 packet
, lease
, client_state
,
3224 in_options
, cfg_options
, scope
,
3227 /* We add a byte for the flags field.
3228 * We add two bytes for the two RCODE fields.
3229 * We add a byte because we will prepend a label count.
3230 * We add a byte because the input len doesn't count null termination,
3231 * and we will add a root label.
3233 len
= 5 + results
[FQDN_FQDN
].len
;
3234 /* Save the contents of the option in a buffer. */
3235 if (!buffer_allocate (&bp
, len
, MDL
)) {
3236 log_error ("no memory for option buffer.");
3240 buffer_reference (&result
-> buffer
, bp
, MDL
);
3242 result
-> data
= &bp
-> data
[0];
3244 memset (&bp
-> data
[0], 0, len
);
3245 /* XXX: The server should set bit 4 (yes, 4, not 3) to 1 if it is
3246 * not going to perform any ddns updates. The client should set the
3247 * bit if it doesn't want the server to perform any updates.
3248 * The problem is at this layer of abstraction we have no idea if
3249 * the caller is a client or server.
3251 * See RFC4702, Section 3.1, 'The "N" bit'.
3256 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3257 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3258 bp
-> data
[0] |= 2;
3259 if (results
[FQDN_SERVER_UPDATE
].len
&&
3260 results
[FQDN_SERVER_UPDATE
].data
[0])
3261 bp
-> data
[0] |= 1;
3262 if (results
[FQDN_RCODE1
].len
)
3263 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
3264 if (results
[FQDN_RCODE2
].len
)
3265 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
3267 if (results
[FQDN_ENCODED
].len
&&
3268 results
[FQDN_ENCODED
].data
[0]) {
3270 if (results
[FQDN_FQDN
].len
) {
3271 i
= fqdn_encode(&bp
->data
[3], len
- 3,
3272 results
[FQDN_FQDN
].data
,
3273 results
[FQDN_FQDN
].len
);
3281 result
->terminated
= 0;
3284 if (results
[FQDN_FQDN
].len
) {
3285 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
3286 results
[FQDN_FQDN
].len
);
3287 result
-> len
+= results
[FQDN_FQDN
].len
;
3288 result
-> terminated
= 0;
3292 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3293 if (results
[i
].len
)
3294 data_string_forget (&results
[i
], MDL
);
3296 buffer_dereference (&bp
, MDL
);
3298 data_string_forget(result
, MDL
);
3303 * Trap invalid attempts to inspect FQND6 contents.
3305 struct option_cache
*
3306 lookup_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3309 log_fatal("Impossible condition at %s:%d.", MDL
);
3314 * Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
3317 save_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3318 struct option_cache
*oc
, isc_boolean_t appendp
)
3320 log_fatal("Impossible condition at %s:%d.", MDL
);
3324 * Trap invalid attempts to delete an option out of the FQDN6 universe.
3327 delete_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3330 log_fatal("Impossible condition at %s:%d.", MDL
);
3333 /* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
3334 * V6's option cache entry.
3336 * This function is called speculatively by dhclient to setup
3337 * environment variables. But it would have already called the
3338 * foreach on the normal fqdn universe, so this is superfluous.
3341 fqdn6_option_space_foreach(struct packet
*packet
, struct lease
*lease
,
3342 struct client_state
*client_state
,
3343 struct option_state
*in_options
,
3344 struct option_state
*cfg_options
,
3345 struct binding_scope
**scope
,
3346 struct universe
*u
, void *stuff
,
3347 void (*func
)(struct option_cache
*,
3350 struct client_state
*,
3351 struct option_state
*,
3352 struct option_state
*,
3353 struct binding_scope
**,
3354 struct universe
*, void *))
3356 /* Pretend it is empty. */
3360 /* Turn the FQDN option space into a DHCPv6 FQDN option buffer.
3363 fqdn6_option_space_encapsulate(struct data_string
*result
,
3364 struct packet
*packet
, struct lease
*lease
,
3365 struct client_state
*client_state
,
3366 struct option_state
*in_options
,
3367 struct option_state
*cfg_options
,
3368 struct binding_scope
**scope
,
3369 struct universe
*universe
)
3372 struct option_chain_head
*head
;
3373 struct option_cache
*oc
;
3374 unsigned char *data
;
3375 int i
, len
, rval
= 0, count
;
3376 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3378 if (fqdn_universe
.index
>= cfg_options
->universe_count
)
3380 head
= ((struct option_chain_head
*)
3381 cfg_options
->universes
[fqdn_universe
.index
]);
3385 memset(results
, 0, sizeof(results
));
3386 for (ocp
= head
->first
; ocp
!= NULL
; ocp
= ocp
->cdr
) {
3387 oc
= (struct option_cache
*)(ocp
->car
);
3388 if (oc
->option
->code
> FQDN_SUBOPTION_COUNT
)
3389 log_fatal("Impossible condition at %s:%d.", MDL
);
3390 /* No need to check the return code, we check the length later */
3391 (void) evaluate_option_cache(&results
[oc
->option
->code
], packet
,
3392 lease
, client_state
, in_options
,
3393 cfg_options
, scope
, oc
, MDL
);
3396 /* We add a byte for the flags field at the start of the option.
3397 * We add a byte because we will prepend a label count.
3398 * We add a byte because the input length doesn't include a trailing
3399 * NULL, and we will add a root label.
3401 len
= results
[FQDN_FQDN
].len
+ 3;
3402 if (!buffer_allocate(&result
->buffer
, len
, MDL
)) {
3403 log_error("No memory for virtual option buffer.");
3406 data
= result
->buffer
->data
;
3407 result
->data
= data
;
3409 /* The first byte is the flags field. */
3412 /* XXX: The server should set bit 3 (yes, 3, not 4) to 1 if we
3413 * are not going to perform any DNS updates. The problem is
3414 * that at this layer of abstraction, we do not know if the caller
3415 * is the client or the server.
3417 * See RFC4704 Section 4.1, 'The "N" bit'.
3422 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3423 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3425 if (results
[FQDN_SERVER_UPDATE
].len
&&
3426 results
[FQDN_SERVER_UPDATE
].data
[0])
3429 /* If there is no name, we're done. */
3430 if (results
[FQDN_FQDN
].len
== 0) {
3435 /* Convert textual representation to DNS format. */
3436 count
= fqdn_encode(data
+ 1, len
- 1,
3437 results
[FQDN_FQDN
].data
, results
[FQDN_FQDN
].len
);
3441 data_string_forget(result
, MDL
);
3445 result
->len
+= count
;
3446 result
->terminated
= 0;
3452 for (i
= 1 ; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3454 data_string_forget(&results
[i
], MDL
);
3460 /* Read the DHCPv6 FQDN option's contents into the FQDN virtual space.
3463 fqdn6_universe_decode(struct option_state
*options
,
3464 const unsigned char *buffer
, unsigned length
,
3467 struct buffer
*bp
= NULL
;
3468 unsigned char *first_dot
;
3469 int len
, hlen
, dlen
;
3471 /* The FQDN option has to be at least 1 byte long. */
3475 /* Save the contents of the option in a buffer. There are 3
3476 * one-byte values we record from the packet, so we go ahead
3477 * and allocate a bigger buffer to accommodate them. But the
3478 * 'length' we got (because it is a DNS encoded string) is
3479 * one longer than we need...so we only add two extra octets.
3481 if (!buffer_allocate(&bp
, length
+ 2, MDL
)) {
3482 log_error("No memory for dhcp6.fqdn option buffer.");
3486 /* The v6 FQDN is always 'encoded' per DNS. */
3488 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3489 bp
->data
, 1, FQDN_ENCODED
, 0))
3492 /* XXX: We need to process 'The "N" bit'. */
3494 if (buffer
[0] & 1) /* server-update. */
3499 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 2, 1,
3500 FQDN_SERVER_UPDATE
, 0))
3503 if (buffer
[0] & 2) /* no-client-update. */
3508 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 1, 1,
3509 FQDN_NO_CLIENT_UPDATE
, 0))
3512 /* Convert the domain name to textual representation for config. */
3513 len
= MRns_name_ntop(buffer
+ 1, (char *)bp
->data
+ 3, length
- 1);
3515 log_error("Unable to convert dhcp6.fqdn domain name to "
3520 /* Save the domain name. */
3522 unsigned char *fqdn_start
= bp
->data
+ 3;
3524 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3525 fqdn_start
, len
, FQDN_FQDN
, 1))
3528 first_dot
= (unsigned char *)strchr((char *)fqdn_start
, '.');
3530 if (first_dot
!= NULL
) {
3531 hlen
= first_dot
- fqdn_start
;
3538 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3539 fqdn_start
, len
, FQDN_FQDN
, 1) ||
3541 !save_option_buffer(&fqdn_universe
, options
, bp
,
3543 FQDN_HOSTNAME
, 0)) ||
3545 !save_option_buffer(&fqdn_universe
, options
, bp
,
3546 first_dot
, dlen
, FQDN_DOMAINNAME
, 0)))
3550 buffer_dereference(&bp
, MDL
);
3554 buffer_dereference(&bp
, MDL
);
3558 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3559 struct client_state
*client_state
,
3560 struct option_state
*in_options
,
3561 struct option_state
*cfg_options
,
3562 struct binding_scope
**scope
,
3563 struct universe
*u
, void *stuff
,
3564 void (*func
) (struct option_cache
*,
3566 struct lease
*, struct client_state
*,
3567 struct option_state
*,
3568 struct option_state
*,
3569 struct binding_scope
**,
3570 struct universe
*, void *))
3573 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
3574 cfg_options
, scope
, u
, stuff
, func
);
3577 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
3578 struct client_state
*client_state
,
3579 struct option_state
*in_options
,
3580 struct option_state
*cfg_options
,
3581 struct binding_scope
**scope
,
3582 struct universe
*u
, void *stuff
,
3583 void (*func
) (struct option_cache
*,
3585 struct lease
*, struct client_state
*,
3586 struct option_state
*,
3587 struct option_state
*,
3588 struct binding_scope
**,
3589 struct universe
*, void *),
3590 struct option_cache
*oc
,
3593 struct universe
*universe
= find_option_universe (oc
-> option
,
3595 if (universe
-> foreach
)
3596 (*universe
-> foreach
) (packet
, lease
, client_state
,
3597 in_options
, cfg_options
,
3598 scope
, universe
, stuff
, func
);
3601 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3602 struct client_state
*client_state
,
3603 struct option_state
*in_options
,
3604 struct option_state
*cfg_options
,
3605 struct binding_scope
**scope
,
3606 struct universe
*u
, void *stuff
,
3607 void (*func
) (struct option_cache
*,
3610 struct client_state
*,
3611 struct option_state
*,
3612 struct option_state
*,
3613 struct binding_scope
**,
3614 struct universe
*, void *))
3618 struct option_cache
*oc
;
3620 if (cfg_options
-> universe_count
<= u
-> index
)
3623 hash
= cfg_options
-> universes
[u
-> index
];
3626 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3628 /* XXX save _all_ options! XXX */
3629 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3630 oc
= (struct option_cache
*)p
-> car
;
3631 (*func
) (oc
, packet
, lease
, client_state
,
3632 in_options
, cfg_options
, scope
, u
, stuff
);
3638 save_linked_option(struct universe
*universe
, struct option_state
*options
,
3639 struct option_cache
*oc
, isc_boolean_t appendp
)
3642 struct option_chain_head
*head
;
3643 struct option_cache
**ocloc
;
3645 if (universe
-> index
>= options
-> universe_count
)
3647 head
= ((struct option_chain_head
*)
3648 options
-> universes
[universe
-> index
]);
3650 if (!option_chain_head_allocate (((struct option_chain_head
**)
3651 &options
-> universes
3652 [universe
-> index
]), MDL
))
3654 head
= ((struct option_chain_head
*)
3655 options
-> universes
[universe
-> index
]);
3658 /* Find the tail of the list. */
3659 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3660 ocloc
= (struct option_cache
**)&(*tail
)->car
;
3662 if (oc
->option
->code
== (*ocloc
)->option
->code
) {
3665 ocloc
= &(*ocloc
)->next
;
3666 } while (*ocloc
!= NULL
);
3668 option_cache_dereference(ocloc
, MDL
);
3670 option_cache_reference(ocloc
, oc
, MDL
);
3675 *tail
= cons (0, 0);
3677 option_cache_reference ((struct option_cache
**)
3678 (&(*tail
) -> car
), oc
, MDL
);
3682 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
3683 in_options
, cfg_options
, scope
, universe
)
3684 struct data_string
*result
;
3685 struct packet
*packet
;
3686 struct lease
*lease
;
3687 struct client_state
*client_state
;
3688 struct option_state
*in_options
;
3689 struct option_state
*cfg_options
;
3690 struct binding_scope
**scope
;
3691 struct universe
*universe
;
3695 struct option_chain_head
*head
;
3697 if (universe
-> index
>= cfg_options
-> universe_count
)
3699 head
= ((struct option_chain_head
*)
3700 cfg_options
-> universes
[universe
-> index
]);
3704 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3705 if (store_option (result
, universe
, packet
,
3706 lease
, client_state
, in_options
, cfg_options
,
3707 scope
, (struct option_cache
*)(oc
-> car
)))
3711 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3712 in_options
, cfg_options
, scope
, universe
))
3718 void delete_linked_option (universe
, options
, code
)
3719 struct universe
*universe
;
3720 struct option_state
*options
;
3723 pair
*tail
, tmp
= (pair
)0;
3724 struct option_chain_head
*head
;
3726 if (universe
-> index
>= options
-> universe_count
)
3728 head
= ((struct option_chain_head
*)
3729 options
-> universes
[universe
-> index
]);
3733 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3735 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
3737 tmp
= (*tail
) -> cdr
;
3738 option_cache_dereference ((struct option_cache
**)
3739 (&(*tail
) -> car
), MDL
);
3747 struct option_cache
*lookup_linked_option (universe
, options
, code
)
3748 struct universe
*universe
;
3749 struct option_state
*options
;
3753 struct option_chain_head
*head
;
3755 if (universe
-> index
>= options
-> universe_count
)
3757 head
= ((struct option_chain_head
*)
3758 options
-> universes
[universe
-> index
]);
3762 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3764 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
3765 return (struct option_cache
*)(oc
-> car
);
3769 return (struct option_cache
*)0;
3772 int linked_option_state_dereference (universe
, state
, file
, line
)
3773 struct universe
*universe
;
3774 struct option_state
*state
;
3778 return (option_chain_head_dereference
3779 ((struct option_chain_head
**)
3780 (&state
-> universes
[universe
-> index
]), MDL
));
3783 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3784 struct client_state
*client_state
,
3785 struct option_state
*in_options
,
3786 struct option_state
*cfg_options
,
3787 struct binding_scope
**scope
,
3788 struct universe
*u
, void *stuff
,
3789 void (*func
) (struct option_cache
*,
3792 struct client_state
*,
3793 struct option_state
*,
3794 struct option_state
*,
3795 struct binding_scope
**,
3796 struct universe
*, void *))
3799 struct option_chain_head
*head
;
3801 if (u
-> index
>= cfg_options
-> universe_count
)
3803 head
= ((struct option_chain_head
*)
3804 cfg_options
-> universes
[u
-> index
]);
3807 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
3808 (*func
) ((struct option_cache
*)(car
-> car
),
3809 packet
, lease
, client_state
,
3810 in_options
, cfg_options
, scope
, u
, stuff
);
3814 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
3815 struct interface_info
*interface
;
3816 struct dhcp_packet
*packet
;
3818 unsigned int from_port
;
3820 struct hardware
*hfrom
;
3822 struct option_cache
*op
;
3823 struct packet
*decoded_packet
;
3824 #if defined (DEBUG_MEMORY_LEAKAGE)
3825 unsigned long previous_outstanding
= dmalloc_outstanding
;
3828 #if defined (TRACING)
3829 trace_inpacket_stash(interface
, packet
, len
, from_port
, from
, hfrom
);
3832 decoded_packet
= NULL
;
3833 if (!packet_allocate(&decoded_packet
, MDL
)) {
3834 log_error("do_packet: no memory for incoming packet!");
3837 decoded_packet
->raw
= packet
;
3838 decoded_packet
->packet_length
= len
;
3839 decoded_packet
->client_port
= from_port
;
3840 decoded_packet
->client_addr
= from
;
3841 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
3842 decoded_packet
->haddr
= hfrom
;
3844 if (packet
->hlen
> sizeof packet
->chaddr
) {
3845 packet_dereference(&decoded_packet
, MDL
);
3846 log_info("Discarding packet with bogus hlen.");
3850 /* If there's an option buffer, try to parse it. */
3851 if (decoded_packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
3852 if (!parse_options(decoded_packet
)) {
3853 if (decoded_packet
->options
)
3854 option_state_dereference
3855 (&decoded_packet
->options
, MDL
);
3856 packet_dereference (&decoded_packet
, MDL
);
3860 if (decoded_packet
->options_valid
&&
3861 (op
= lookup_option(&dhcp_universe
,
3862 decoded_packet
->options
,
3863 DHO_DHCP_MESSAGE_TYPE
))) {
3864 struct data_string dp
;
3865 memset(&dp
, 0, sizeof dp
);
3866 evaluate_option_cache(&dp
, decoded_packet
, NULL
, NULL
,
3867 decoded_packet
->options
, NULL
,
3870 decoded_packet
->packet_type
= dp
.data
[0];
3872 decoded_packet
->packet_type
= 0;
3873 data_string_forget(&dp
, MDL
);
3877 if (validate_packet(decoded_packet
) != 0) {
3878 if (decoded_packet
->packet_type
)
3879 dhcp(decoded_packet
);
3881 bootp(decoded_packet
);
3884 /* If the caller kept the packet, they'll have upped the refcnt. */
3885 packet_dereference(&decoded_packet
, MDL
);
3887 #if defined (DEBUG_MEMORY_LEAKAGE)
3888 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
3890 dmalloc_outstanding
- previous_outstanding
,
3891 dmalloc_outstanding
, dmalloc_longterm
);
3892 dmalloc_dump_outstanding();
3894 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
3900 packet6_len_okay(const char *packet
, int len
) {
3904 if ((packet
[0] == DHCPV6_RELAY_FORW
) ||
3905 (packet
[0] == DHCPV6_RELAY_REPL
)) {
3906 if (len
>= offsetof(struct dhcpv6_relay_packet
, options
)) {
3912 if (len
>= offsetof(struct dhcpv6_packet
, options
)) {
3922 do_packet6(struct interface_info
*interface
, const char *packet
,
3923 int len
, int from_port
, const struct iaddr
*from
,
3924 isc_boolean_t was_unicast
) {
3925 unsigned char msg_type
;
3926 const struct dhcpv6_packet
*msg
;
3927 const struct dhcpv6_relay_packet
*relay
;
3928 struct packet
*decoded_packet
;
3929 #if defined (DEBUG_MEMORY_LEAKAGE)
3930 unsigned long previous_outstanding
= dmalloc_outstanding
;
3933 if (!packet6_len_okay(packet
, len
)) {
3934 log_info("do_packet6: "
3935 "short packet from %s port %d, len %d, dropped",
3936 piaddr(*from
), from_port
, len
);
3940 decoded_packet
= NULL
;
3941 if (!packet_allocate(&decoded_packet
, MDL
)) {
3942 log_error("do_packet6: no memory for incoming packet.");
3946 if (!option_state_allocate(&decoded_packet
->options
, MDL
)) {
3947 log_error("do_packet6: no memory for options.");
3948 packet_dereference(&decoded_packet
, MDL
);
3952 /* IPv4 information, already set to 0 */
3953 /* decoded_packet->packet_type = 0; */
3954 /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
3955 /* decoded_packet->circuit_id = NULL; */
3956 /* decoded_packet->circuit_id_len = 0; */
3957 /* decoded_packet->remote_id = NULL; */
3958 /* decoded_packet->remote_id_len = 0; */
3959 decoded_packet
->raw
= (struct dhcp_packet
*)packet
;
3960 decoded_packet
->packet_length
= (unsigned)len
;
3961 decoded_packet
->client_port
= from_port
;
3962 decoded_packet
->client_addr
= *from
;
3963 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
3965 decoded_packet
->unicast
= was_unicast
;
3967 msg_type
= packet
[0];
3968 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
3969 (msg_type
== DHCPV6_RELAY_REPL
)) {
3970 int relaylen
= (int)(offsetof(struct dhcpv6_relay_packet
, options
));
3971 relay
= (const struct dhcpv6_relay_packet
*)packet
;
3972 decoded_packet
->dhcpv6_msg_type
= relay
->msg_type
;
3974 /* relay-specific data */
3975 decoded_packet
->dhcpv6_hop_count
= relay
->hop_count
;
3976 memcpy(&decoded_packet
->dhcpv6_link_address
,
3977 relay
->link_address
, sizeof(relay
->link_address
));
3978 memcpy(&decoded_packet
->dhcpv6_peer_address
,
3979 relay
->peer_address
, sizeof(relay
->peer_address
));
3981 if (!parse_option_buffer(decoded_packet
->options
,
3982 relay
->options
, len
- relaylen
,
3983 &dhcpv6_universe
)) {
3984 /* no logging here, as parse_option_buffer() logs all
3985 cases where it fails */
3986 packet_dereference(&decoded_packet
, MDL
);
3990 int msglen
= (int)(offsetof(struct dhcpv6_packet
, options
));
3991 msg
= (const struct dhcpv6_packet
*)packet
;
3992 decoded_packet
->dhcpv6_msg_type
= msg
->msg_type
;
3994 /* message-specific data */
3995 memcpy(decoded_packet
->dhcpv6_transaction_id
,
3996 msg
->transaction_id
,
3997 sizeof(decoded_packet
->dhcpv6_transaction_id
));
3999 if (!parse_option_buffer(decoded_packet
->options
,
4000 msg
->options
, len
- msglen
,
4001 &dhcpv6_universe
)) {
4002 /* no logging here, as parse_option_buffer() logs all
4003 cases where it fails */
4004 packet_dereference(&decoded_packet
, MDL
);
4009 dhcpv6(decoded_packet
);
4011 packet_dereference(&decoded_packet
, MDL
);
4013 #if defined (DEBUG_MEMORY_LEAKAGE)
4014 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4016 dmalloc_outstanding
- previous_outstanding
,
4017 dmalloc_outstanding
, dmalloc_longterm
);
4018 dmalloc_dump_outstanding();
4020 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4027 pretty_escape(char **dst
, char *dend
, const unsigned char **src
,
4028 const unsigned char *send
)
4032 /* If there aren't as many bytes left as there are in the source
4033 * buffer, don't even bother entering the loop.
4035 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4036 *dst
== NULL
|| *src
== NULL
|| (*dst
>= dend
) || (*src
> send
) ||
4037 ((send
- *src
) > (dend
- *dst
)))
4040 for ( ; *src
< send
; (*src
)++) {
4041 if (!isascii (**src
) || !isprint (**src
)) {
4042 /* Skip trailing NUL. */
4043 if ((*src
+ 1) != send
|| **src
!= '\0') {
4044 if (*dst
+ 4 > dend
)
4047 sprintf(*dst
, "\\%03o",
4052 } else if (**src
== '"' || **src
== '\'' || **src
== '$' ||
4053 **src
== '`' || **src
== '\\' || **src
== '|' ||
4055 if (*dst
+ 2 > dend
)
4064 if (*dst
+ 1 > dend
)
4077 pretty_text(char **dst
, char *dend
, const unsigned char **src
,
4078 const unsigned char *send
, int emit_quotes
)
4082 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4083 *dst
== NULL
|| *src
== NULL
||
4084 ((*dst
+ (emit_quotes
? 2 : 0)) > dend
) || (*src
> send
))
4092 /* dend-1 leaves 1 byte for the closing quote. */
4093 count
= pretty_escape(dst
, dend
- (emit_quotes
? 1 : 0), src
, send
);
4098 if (emit_quotes
&& (*dst
< dend
)) {
4102 /* Includes quote prior to pretty_escape(); */
4110 pretty_domain(char **dst
, char *dend
, const unsigned char **src
,
4111 const unsigned char *send
)
4113 const unsigned char *tend
;
4117 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4118 *dst
== NULL
|| *src
== NULL
||
4119 ((*dst
+ 2) > dend
) || (*src
>= send
))
4126 /* Continue loop until end of src buffer. */
4130 /* Consume tag size. */
4134 /* At root, finis. */
4138 tend
= (*src
) + tsiz
;
4140 /* If the tag exceeds the source buffer, it's illegal.
4141 * This should also trap compression pointers (which should
4142 * not be in these buffers).
4147 /* dend-2 leaves room for a trailing dot and quote. */
4148 status
= pretty_escape(dst
, dend
-2, src
, tend
);
4150 if ((status
== -1) || ((*dst
+ 2) > dend
))
4155 count
+= status
+ 1;
4166 * Add the option identified with the option number and data to the
4170 add_option(struct option_state
*options
,
4171 unsigned int option_num
,
4173 unsigned int data_len
)
4175 struct option_cache
*oc
;
4176 struct option
*option
;
4178 /* INSIST(options != NULL); */
4179 /* INSIST(data != NULL); */
4182 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
4183 &option_num
, 0, MDL
)) {
4184 log_error("Attempting to add unknown option %d.", option_num
);
4189 if (!option_cache_allocate(&oc
, MDL
)) {
4190 log_error("No memory for option cache adding %s (option %d).",
4191 option
->name
, option_num
);
4195 if (!make_const_data(&oc
->expression
,
4201 log_error("No memory for constant data adding %s (option %d).",
4202 option
->name
, option_num
);
4203 option_cache_dereference(&oc
, MDL
);
4207 option_reference(&(oc
->option
), option
, MDL
);
4208 save_option(&dhcp_universe
, options
, oc
);
4209 option_cache_dereference(&oc
, MDL
);
4215 * Checks if received BOOTP/DHCPv4 packet is sane
4217 * @param packet received, decoded packet
4219 * @return 1 if packet is sane, 0 if it is not
4221 int validate_packet(struct packet
*packet
)
4223 struct option_cache
*oc
= NULL
;
4225 oc
= lookup_option (&dhcp_universe
, packet
->options
,
4226 DHO_DHCP_CLIENT_IDENTIFIER
);
4228 /* Let's check if client-identifier is sane */
4229 if (oc
->data
.len
== 0) {
4230 log_debug("Dropped DHCPv4 packet with zero-length client-id");
4233 } else if (oc
->data
.len
== 1) {
4235 * RFC2132, section 9.14 states that minimum length of client-id
4236 * is 2. We will allow single-character client-ids for now (for
4237 * backwards compatibility), but warn the user that support for
4238 * this is against the standard.
4240 log_debug("Accepted DHCPv4 packet with one-character client-id - "
4241 "a future version of ISC DHCP will reject this");
4245 * If hlen is 0 we don't have any identifier, we warn the user
4246 * but continue processing the packet as we can.
4248 if (packet
->raw
->hlen
== 0) {
4249 log_debug("Received DHCPv4 packet without client-id"
4250 " option and empty hlen field.");
4254 /* @todo: Add checks for other received options */