1 /* $NetBSD: options.c,v 1.1.1.3 2014/07/12 11:57:46 spz Exp $ */
4 DHCP options parsing and reassembly. */
7 * Copyright (c) 2004-2012,2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1995-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: options.c,v 1.1.1.3 2014/07/12 11:57:46 spz Exp $");
33 #define DHCP_OPTION_DATA
35 #include <omapip/omapip_p.h>
38 struct option
*vendor_cfg_option
;
40 static int pretty_text(char **, char *, const unsigned char **,
41 const unsigned char *, int);
42 static int pretty_domain(char **, char *, const unsigned char **,
43 const unsigned char *);
44 static int prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
45 unsigned char *buffer
, unsigned length
,
46 unsigned code
, int terminatep
,
47 struct option_cache
**opp
);
49 /* Parse all available options out of the specified packet. */
51 int parse_options (packet
)
52 struct packet
*packet
;
54 struct option_cache
*op
= (struct option_cache
*)0;
56 /* Allocate a new option state. */
57 if (!option_state_allocate (&packet
-> options
, MDL
)) {
58 packet
-> options_valid
= 0;
62 /* If we don't see the magic cookie, there's nothing to parse. */
63 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
64 packet
-> options_valid
= 0;
68 /* Go through the options field, up to the end of the packet
70 if (!parse_option_buffer (packet
-> options
,
71 &packet
-> raw
-> options
[4],
72 (packet
-> packet_length
-
73 DHCP_FIXED_NON_UDP
- 4),
76 /* STSN servers have a bug where they send a mangled
77 domain-name option, and whatever is beyond that in
78 the packet is junk. Microsoft clients accept this,
79 which is probably why whoever implemented the STSN
80 server isn't aware of the problem yet. To work around
81 this, we will accept corrupt packets from the server if
82 they contain a valid DHCP_MESSAGE_TYPE option, but
83 will not accept any corrupt client packets (the ISC DHCP
84 server is sufficiently widely used that it is probably
85 beneficial for it to be picky) and will not accept
86 packets whose type can't be determined. */
88 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
89 DHO_DHCP_MESSAGE_TYPE
))) {
90 if (!op
-> data
.data
||
91 (op
-> data
.data
[0] != DHCPOFFER
&&
92 op
-> data
.data
[0] != DHCPACK
&&
93 op
-> data
.data
[0] != DHCPNAK
))
99 /* If we parsed a DHCP Option Overload option, parse more
100 options out of the buffer(s) containing them. */
101 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
102 DHO_DHCP_OPTION_OVERLOAD
))) {
103 if (op
-> data
.data
[0] & 1) {
104 if (!parse_option_buffer
106 (unsigned char *)packet
-> raw
-> file
,
107 sizeof packet
-> raw
-> file
,
111 if (op
-> data
.data
[0] & 2) {
112 if (!parse_option_buffer
114 (unsigned char *)packet
-> raw
-> sname
,
115 sizeof packet
-> raw
-> sname
,
120 packet
-> options_valid
= 1;
124 /* Parse options out of the specified buffer, storing addresses of option
125 * values in packet->options.
127 int parse_option_buffer (options
, buffer
, length
, universe
)
128 struct option_state
*options
;
129 const unsigned char *buffer
;
131 struct universe
*universe
;
133 unsigned len
, offset
;
135 struct option_cache
*op
= NULL
, *nop
= NULL
;
136 struct buffer
*bp
= (struct buffer
*)0;
137 struct option
*option
= NULL
;
138 char *reason
= "general failure";
140 if (!buffer_allocate (&bp
, length
, MDL
)) {
141 log_error ("no memory for option buffer.");
144 memcpy (bp
-> data
, buffer
, length
);
147 (offset
+ universe
->tag_size
) <= length
&&
148 (code
= universe
->get_tag(buffer
+ offset
)) != universe
->end
; ) {
149 offset
+= universe
->tag_size
;
151 /* Pad options don't have a length - just skip them. */
155 /* Don't look for length if the buffer isn't that big. */
156 if ((offset
+ universe
->length_size
) > length
) {
157 reason
= "code tag at end of buffer - missing "
162 /* All other fields (except PAD and END handled above)
163 * have a length field, unless it's a DHCPv6 zero-length
164 * options space (eg any of the enterprise-id'd options).
166 * Zero-length-size option spaces basically consume the
167 * entire options buffer, so have at it.
169 if (universe
->get_length
!= NULL
)
170 len
= universe
->get_length(buffer
+ offset
);
171 else if (universe
->length_size
== 0)
172 len
= length
- universe
->tag_size
;
174 log_fatal("Improperly configured option space(%s): "
175 "may not have a nonzero length size "
176 "AND a NULL get_length function.",
179 /* Silence compiler warnings. */
183 offset
+= universe
->length_size
;
185 option_code_hash_lookup(&option
, universe
->code_hash
, &code
,
188 /* If the length is outrageous, the options are bad. */
189 if (offset
+ len
> length
) {
190 reason
= "option length exceeds option buffer length";
192 log_error("parse_option_buffer: malformed option "
193 "%s.%s (code %u): %s.", universe
->name
,
194 option
? option
->name
: "<unknown>",
196 buffer_dereference (&bp
, MDL
);
200 /* If the option contains an encapsulation, parse it. If
201 the parse fails, or the option isn't an encapsulation (by
202 far the most common case), or the option isn't entirely
203 an encapsulation, keep the raw data as well. */
205 (option
->format
[0] == 'e' ||
206 option
->format
[0] == 'E') &&
207 (parse_encapsulated_suboptions(options
, option
,
208 bp
->data
+ offset
, len
,
210 op
= lookup_option(universe
, options
, code
);
212 if (op
!= NULL
&& universe
->concat_duplicates
) {
213 struct data_string
new;
214 memset(&new, 0, sizeof new);
215 if (!buffer_allocate(&new.buffer
,
218 log_error("parse_option_buffer: "
220 buffer_dereference(&bp
, MDL
);
223 /* Copy old option to new data object. */
224 memcpy(new.buffer
->data
, op
->data
.data
,
226 /* Concat new option behind old. */
227 memcpy(new.buffer
->data
+ op
->data
.len
,
228 bp
->data
+ offset
, len
);
229 new.len
= op
->data
.len
+ len
;
230 new.data
= new.buffer
->data
;
231 /* Save new concat'd object. */
232 data_string_forget(&op
->data
, MDL
);
233 data_string_copy(&op
->data
, &new, MDL
);
234 data_string_forget(&new, MDL
);
235 } else if (op
!= NULL
) {
236 /* We must append this statement onto the
239 while (op
->next
!= NULL
)
242 if (!option_cache_allocate(&nop
, MDL
)) {
243 log_error("parse_option_buffer: "
245 buffer_dereference(&bp
, MDL
);
249 option_reference(&nop
->option
, op
->option
, MDL
);
251 nop
->data
.buffer
= NULL
;
252 buffer_reference(&nop
->data
.buffer
, bp
, MDL
);
253 nop
->data
.data
= bp
->data
+ offset
;
256 option_cache_reference(&op
->next
, nop
, MDL
);
257 option_cache_dereference(&nop
, MDL
);
259 if (save_option_buffer(universe
, options
, bp
,
260 bp
->data
+ offset
, len
,
262 log_error("parse_option_buffer: "
263 "save_option_buffer failed");
264 buffer_dereference(&bp
, MDL
);
269 option_dereference(&option
, MDL
);
272 buffer_dereference (&bp
, MDL
);
276 /* If an option in an option buffer turns out to be an encapsulation,
277 figure out what to do. If we don't know how to de-encapsulate it,
278 or it's not well-formed, return zero; otherwise, return 1, indicating
279 that we succeeded in de-encapsulating it. */
281 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
285 struct universe
*universe
= (struct universe
*)0;
287 /* Look for the E option in the option format. */
288 s
= strchr (eopt
-> format
, 'E');
290 log_error ("internal encapsulation format error 1.");
293 /* Look for the universe name in the option format. */
294 t
= strchr (++s
, '.');
295 /* If there was no trailing '.', or there's something after the
296 trailing '.', the option is bogus and we can't use it. */
298 log_error ("internal encapsulation format error 2.");
301 if (t
== s
&& uname
) {
302 for (i
= 0; i
< universe_count
; i
++) {
303 if (!strcmp (universes
[i
] -> name
, uname
)) {
304 universe
= universes
[i
];
309 for (i
= 0; i
< universe_count
; i
++) {
310 if (strlen (universes
[i
] -> name
) == t
- s
&&
311 !memcmp (universes
[i
] -> name
,
312 s
, (unsigned)(t
- s
))) {
313 universe
= universes
[i
];
321 /* If an option in an option buffer turns out to be an encapsulation,
322 figure out what to do. If we don't know how to de-encapsulate it,
323 or it's not well-formed, return zero; otherwise, return 1, indicating
324 that we succeeded in de-encapsulating it. */
326 int parse_encapsulated_suboptions (struct option_state
*options
,
328 const unsigned char *buffer
,
329 unsigned len
, struct universe
*eu
,
333 struct universe
*universe
= find_option_universe (eopt
, uname
);
335 /* If we didn't find the universe, we can't do anything with it
336 right now (e.g., we can't decode vendor options until we've
337 decoded the packet and executed the scopes that it matches). */
341 /* If we don't have a decoding function for it, we can't decode
343 if (!universe
-> decode
)
346 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
348 /* If there is stuff before the suboptions, we have to keep it. */
349 if (eopt
-> format
[0] != 'E')
351 /* Otherwise, return the status of the decode function. */
355 int fqdn_universe_decode (struct option_state
*options
,
356 const unsigned char *buffer
,
357 unsigned length
, struct universe
*u
)
359 struct buffer
*bp
= (struct buffer
*)0;
361 /* FQDN options have to be at least four bytes long. */
365 /* Save the contents of the option in a buffer. */
366 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
367 log_error ("no memory for option buffer.");
370 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
372 if (buffer
[0] & 4) /* encoded */
376 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
377 bp
->data
, 1, FQDN_ENCODED
, 0)) {
379 buffer_dereference (&bp
, MDL
);
383 if (buffer
[0] & 1) /* server-update */
387 if (buffer
[0] & 2) /* no-client-update */
392 /* XXX Ideally we should store the name in DNS format, so if the
393 XXX label isn't in DNS format, we convert it to DNS format,
394 XXX rather than converting labels specified in DNS format to
395 XXX the plain ASCII representation. But that's hard, so
398 /* Not encoded using DNS format? */
399 if (!bp
-> data
[0]) {
402 /* Some broken clients NUL-terminate this option. */
403 if (buffer
[length
- 1] == 0) {
408 /* Determine the length of the hostname component of the
409 name. If the name contains no '.' character, it
410 represents a non-qualified label. */
411 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
414 /* Note: If the client sends a FQDN, the first '.' will
415 be used as a NUL terminator for the hostname. */
416 if (i
&& (!save_option_buffer(&fqdn_universe
, options
, bp
,
420 /* Note: If the client sends a single label, the
421 FQDN_DOMAINNAME option won't be set. */
422 if (length
> 4 + i
&&
423 (!save_option_buffer(&fqdn_universe
, options
, bp
,
424 &bp
-> data
[6 + i
], length
- 4 - i
,
425 FQDN_DOMAINNAME
, 1)))
427 /* Also save the whole name. */
429 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
430 &bp
-> data
[5], length
- 3,
436 unsigned total_len
= 0;
437 unsigned first_len
= 0;
443 while (s
< &bp
-> data
[0] + length
+ 2) {
446 log_info ("fancy bits in fqdn option");
453 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
454 log_info ("fqdn tag longer than buffer");
458 if (first_len
== 0) {
464 total_len
+= len
+ 1;
467 /* We wind up with a length that's one too many because
468 we shouldn't increment for the last label, but there's
469 no way to tell we're at the last label until we exit
475 first_len
= total_len
;
479 !save_option_buffer(&fqdn_universe
, options
, bp
,
480 &bp
-> data
[6], first_len
,
483 if (total_len
> 0 && first_len
!= total_len
) {
484 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
485 &bp
->data
[6 + first_len
],
486 total_len
- first_len
,
491 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
492 &bp
-> data
[6], total_len
,
497 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
499 FQDN_NO_CLIENT_UPDATE
, 0))
501 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
503 FQDN_SERVER_UPDATE
, 0))
506 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
510 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
515 buffer_dereference (&bp
, MDL
);
520 * Load all options into a buffer, and then split them out into the three
521 * separate fields in the dhcp packet (options, file, and sname) where
522 * options can be stored.
524 * returns 0 on error, length of packet on success
527 cons_options(struct packet
*inpacket
, struct dhcp_packet
*outpacket
,
528 struct lease
*lease
, struct client_state
*client_state
,
529 int mms
, struct option_state
*in_options
,
530 struct option_state
*cfg_options
,
531 struct binding_scope
**scope
,
532 int overload_avail
, int terminate
, int bootpp
,
533 struct data_string
*prl
, const char *vuname
)
535 #define PRIORITY_COUNT 300
536 unsigned priority_list
[PRIORITY_COUNT
];
538 unsigned char buffer
[4096], agentopts
[1024];
540 unsigned mb_size
= 0, mb_max
= 0;
541 unsigned option_size
= 0, agent_size
= 0;
544 struct option_cache
*op
;
545 struct data_string ds
;
547 int overload_used
= 0;
548 int of1
= 0, of2
= 0;
550 memset(&ds
, 0, sizeof ds
);
553 * If there's a Maximum Message Size option in the incoming packet
554 * and no alternate maximum message size has been specified, or
555 * if the one specified in the packet is shorter than the
556 * alternative, take the one in the packet.
560 (op
= lookup_option(&dhcp_universe
, inpacket
->options
,
561 DHO_DHCP_MAX_MESSAGE_SIZE
)) &&
562 (evaluate_option_cache(&ds
, inpacket
, lease
,
563 client_state
, in_options
,
564 cfg_options
, scope
, op
, MDL
) != 0)) {
565 if (ds
.len
>= sizeof (u_int16_t
)) {
566 i
= getUShort(ds
.data
);
567 if(!mms
|| (i
< mms
))
570 data_string_forget(&ds
, MDL
);
574 * If the client has provided a maximum DHCP message size,
575 * use that, up to the MTU limit. Otherwise, if it's BOOTP,
576 * only 64 bytes; otherwise use up to the minimum IP MTU size
579 * XXX if a BOOTP client specifies a max message size, we will
583 if (mms
< DHCP_MTU_MIN
)
584 /* Enforce minimum packet size, per RFC 2132 */
585 mb_size
= DHCP_MIN_OPTION_LEN
;
586 else if (mms
> DHCP_MTU_MAX
)
588 * TODO: Packets longer than 1500 bytes really
589 * should be allowed, but it requires upstream
590 * changes to the way the packet is allocated. For
591 * now, we forbid them. They won't be needed very
594 mb_size
= DHCP_MAX_OPTION_LEN
;
596 mb_size
= mms
- DHCP_FIXED_LEN
;
599 if (inpacket
!= NULL
&&
600 (inpacket
->packet_length
>= 64 + DHCP_FIXED_NON_UDP
))
601 mb_size
= inpacket
->packet_length
- DHCP_FIXED_NON_UDP
;
603 mb_size
= DHCP_MIN_OPTION_LEN
;
606 * If answering a client message, see whether any relay agent
607 * options were included with the message. If so, save them
608 * to copy back in later, and make space in the main buffer
609 * to accommodate them
611 if (client_state
== NULL
) {
612 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
614 agent_size
= store_options(NULL
, agentopts
, 0,
616 inpacket
, lease
, client_state
,
617 in_options
, cfg_options
, scope
,
618 priority_list
, priority_len
,
621 mb_size
+= agent_size
;
622 if (mb_size
> DHCP_MAX_OPTION_LEN
)
623 mb_size
= DHCP_MAX_OPTION_LEN
;
627 * Set offsets for buffer data to be copied into filename
628 * and servername fields
632 if (overload_avail
& 1) {
634 mb_max
+= DHCP_FILE_LEN
;
637 if (overload_avail
& 2) {
639 mb_max
+= DHCP_SNAME_LEN
;
643 * Preload the option priority list with protocol-mandatory options.
644 * This effectively gives these options the highest priority.
645 * This provides the order for any available options, the option
646 * must be in the option cache in order to actually be included.
649 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
650 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
651 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
652 priority_list
[priority_len
++] = DHO_DHCP_RENEWAL_TIME
;
653 priority_list
[priority_len
++] = DHO_DHCP_REBINDING_TIME
;
654 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
655 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
656 priority_list
[priority_len
++] = DHO_ASSOCIATED_IP
;
658 if (prl
!= NULL
&& prl
->len
> 0) {
659 if ((op
= lookup_option(&dhcp_universe
, cfg_options
,
660 DHO_SUBNET_SELECTION
))) {
661 if (priority_len
< PRIORITY_COUNT
)
662 priority_list
[priority_len
++] =
663 DHO_SUBNET_SELECTION
;
666 data_string_truncate(prl
, (PRIORITY_COUNT
- priority_len
));
669 * Copy the client's PRL onto the priority_list after our high
672 for (i
= 0; i
< prl
->len
; i
++) {
674 * Prevent client from changing order of delivery
675 * of relay agent information option.
677 if (prl
->data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
678 priority_list
[priority_len
++] = prl
->data
[i
];
682 * If the client doesn't request the FQDN option explicitly,
683 * to indicate priority, consider it lowest priority. Fit
684 * in the packet if there is space. Note that the option
685 * may only be included if the client supplied one.
687 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
688 (lookup_option(&fqdn_universe
, inpacket
->options
,
689 FQDN_ENCODED
) != NULL
))
690 priority_list
[priority_len
++] = DHO_FQDN
;
693 * Some DHCP Servers will give the subnet-mask option if
694 * it is not on the parameter request list - so some client
695 * implementations have come to rely on this - so we will
696 * also make sure we supply this, at lowest priority.
698 * This is only done in response to DHCPDISCOVER or
699 * DHCPREQUEST messages, to avoid providing the option on
700 * DHCPINFORM or DHCPLEASEQUERY responses (if the client
701 * didn't request it).
703 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
704 ((inpacket
->packet_type
== DHCPDISCOVER
) ||
705 (inpacket
->packet_type
== DHCPREQUEST
)))
706 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
709 * First, hardcode some more options that ought to be
710 * sent first...these are high priority to have in the
713 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
714 priority_list
[priority_len
++] = DHO_ROUTERS
;
715 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
716 priority_list
[priority_len
++] = DHO_HOST_NAME
;
717 priority_list
[priority_len
++] = DHO_FQDN
;
720 * Append a list of the standard DHCP options from the
721 * standard DHCP option space. Actually, if a site
722 * option space hasn't been specified, we wind up
723 * treating the dhcp option space as the site option
724 * space, and the first for loop is skipped, because
725 * it's slightly more general to do it this way,
726 * taking the 1Q99 DHCP futures work into account.
728 if (cfg_options
->site_code_min
) {
729 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
730 hash
= cfg_options
->universes
[dhcp_universe
.index
];
732 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
733 op
= (struct option_cache
*)(pp
->car
);
734 if (op
->option
->code
<
735 cfg_options
->site_code_min
&&
736 priority_len
< PRIORITY_COUNT
&&
737 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
738 priority_list
[priority_len
++] =
746 * Now cycle through the site option space, or if there
747 * is no site option space, we'll be cycling through the
750 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
751 hash
= cfg_options
->universes
[cfg_options
->site_universe
];
753 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
754 op
= (struct option_cache
*)(pp
->car
);
755 if (op
->option
->code
>=
756 cfg_options
->site_code_min
&&
757 priority_len
< PRIORITY_COUNT
&&
758 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
759 priority_list
[priority_len
++] =
765 * Put any spaces that are encapsulated on the list,
766 * sort out whether they contain values later.
768 for (i
= 0; i
< cfg_options
->universe_count
; i
++) {
769 if (universes
[i
]->enc_opt
&&
770 priority_len
< PRIORITY_COUNT
&&
771 universes
[i
]->enc_opt
->universe
== &dhcp_universe
) {
772 if (universes
[i
]->enc_opt
->code
!=
773 DHO_DHCP_AGENT_OPTIONS
)
774 priority_list
[priority_len
++] =
775 universes
[i
]->enc_opt
->code
;
780 * The vendor option space can't stand on its own, so always
781 * add it to the list.
783 if (priority_len
< PRIORITY_COUNT
)
784 priority_list
[priority_len
++] =
785 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
788 /* Put the cookie up front... */
789 memcpy(buffer
, DHCP_OPTIONS_COOKIE
, 4);
792 /* Copy the options into the big buffer... */
793 option_size
= store_options(&overload_used
, buffer
, index
, mb_max
,
794 inpacket
, lease
, client_state
,
795 in_options
, cfg_options
, scope
,
796 priority_list
, priority_len
,
797 of1
, of2
, terminate
, vuname
);
799 /* If store_options() failed */
800 if (option_size
== 0)
803 /* How much was stored in the main buffer? */
804 index
+= option_size
;
807 * If we're going to have to overload, store the overload
811 if (mb_size
- agent_size
- index
< 3)
814 buffer
[index
++] = DHO_DHCP_OPTION_OVERLOAD
;
816 buffer
[index
++] = overload_used
;
818 if (overload_used
& 1)
819 memcpy(outpacket
->file
, &buffer
[of1
], DHCP_FILE_LEN
);
821 if (overload_used
& 2)
822 memcpy(outpacket
->sname
, &buffer
[of2
], DHCP_SNAME_LEN
);
825 /* Now copy in preserved agent options, if any */
827 if (mb_size
- index
>= agent_size
) {
828 memcpy(&buffer
[index
], agentopts
, agent_size
);
831 log_error("Unable to store relay agent information "
835 /* Tack a DHO_END option onto the packet if we need to. */
837 buffer
[index
++] = DHO_END
;
839 /* Copy main buffer into the options buffer of the packet */
840 memcpy(outpacket
->options
, buffer
, index
);
842 /* Figure out the length. */
843 length
= DHCP_FIXED_NON_UDP
+ index
;
848 * XXX: We currently special case collecting VSIO options.
849 * We should be able to handle this in a more generic fashion, by
850 * including any encapsulated options that are present and desired.
851 * This will look something like the VSIO handling VSIO code.
852 * We may also consider handling the ORO-like options within
853 * encapsulated spaces.
863 vsio_options(struct option_cache
*oc
,
864 struct packet
*packet
,
865 struct lease
*dummy_lease
,
866 struct client_state
*dummy_client_state
,
867 struct option_state
*dummy_opt_state
,
868 struct option_state
*opt_state
,
869 struct binding_scope
**dummy_binding_scope
,
870 struct universe
*universe
,
871 void *void_vsio_state
) {
872 struct vsio_state
*vs
= (struct vsio_state
*)void_vsio_state
;
873 struct data_string ds
;
876 memset(&ds
, 0, sizeof(ds
));
877 if (evaluate_option_cache(&ds
, packet
, NULL
,
878 NULL
, opt_state
, NULL
,
879 &global_scope
, oc
, MDL
)) {
880 total_len
= ds
.len
+ universe
->tag_size
+ universe
->length_size
;
881 if (total_len
<= (vs
->buflen
- vs
->bufpos
)) {
882 if (universe
->tag_size
== 1) {
883 vs
->buf
[vs
->bufpos
++] = oc
->option
->code
;
884 } else if (universe
->tag_size
== 2) {
885 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
888 } else if (universe
->tag_size
== 4) {
889 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
893 if (universe
->length_size
== 1) {
894 vs
->buf
[vs
->bufpos
++] = ds
.len
;
895 } else if (universe
->length_size
== 2) {
896 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
899 } else if (universe
->length_size
== 4) {
900 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
904 memcpy(vs
->buf
+ vs
->bufpos
, ds
.data
, ds
.len
);
905 vs
->bufpos
+= ds
.len
;
907 log_debug("No space for option %d in VSIO space %s.",
908 oc
->option
->code
, universe
->name
);
910 data_string_forget(&ds
, MDL
);
912 log_error("Error evaluating option %d in VSIO space %s.",
913 oc
->option
->code
, universe
->name
);
918 * Stores the options from the DHCPv6 universe into the buffer given.
920 * Required options are given as a 0-terminated list of option codes.
921 * Once those are added, the ORO is consulted.
925 store_options6(char *buf
, int buflen
,
926 struct option_state
*opt_state
,
927 struct packet
*packet
,
928 const int *required_opts
,
929 struct data_string
*oro
) {
931 struct option_cache
*oc
;
933 struct data_string ds
;
937 int in_required_opts
;
938 int vsio_option_code
;
940 struct vsio_state vs
;
947 * Find the option code for the VSIO universe.
949 vsio_option_code
= 0;
950 o
= vsio_universe
.enc_opt
;
952 if (o
->universe
== &dhcpv6_universe
) {
953 vsio_option_code
= o
->code
;
956 o
= o
->universe
->enc_opt
;
958 if (vsio_option_code
== 0) {
959 log_fatal("No VSIO option code found.");
962 if (required_opts
!= NULL
) {
963 for (i
=0; required_opts
[i
] != 0; i
++) {
964 if (required_opts
[i
] == vsio_option_code
) {
968 oc
= lookup_option(&dhcpv6_universe
,
969 opt_state
, required_opts
[i
]);
973 memset(&ds
, 0, sizeof(ds
));
974 for (; oc
!= NULL
; oc
= oc
->next
) {
975 if (evaluate_option_cache(&ds
, packet
, NULL
,
981 tmp
= (unsigned char *)buf
;
987 putUShort(tmp
+2, ds
.len
);
989 memcpy(tmp
+4, ds
.data
, ds
.len
);
990 /* update position */
991 bufpos
+= (4 + ds
.len
);
993 log_debug("No space for "
997 data_string_forget(&ds
, MDL
);
999 log_error("Error evaluating option %d",
1009 oro_size
= oro
->len
/ 2;
1011 for (i
=0; i
<oro_size
; i
++) {
1012 memcpy(&code
, oro
->data
+(i
*2), 2);
1016 * See if we've already included this option because
1019 in_required_opts
= 0;
1020 if (required_opts
!= NULL
) {
1021 for (j
=0; required_opts
[j
] != 0; j
++) {
1022 if (required_opts
[j
] == code
) {
1023 in_required_opts
= 1;
1028 if (in_required_opts
) {
1033 * See if this is the VSIO option.
1035 if (code
== vsio_option_code
) {
1040 * Not already added, find this option.
1042 oc
= lookup_option(&dhcpv6_universe
, opt_state
, code
);
1043 memset(&ds
, 0, sizeof(ds
));
1044 for (; oc
!= NULL
; oc
= oc
->next
) {
1045 if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1047 &global_scope
, oc
, MDL
)) {
1048 if ((ds
.len
+ 4) <= (buflen
- bufpos
)) {
1049 tmp
= (unsigned char *)buf
+ bufpos
;
1051 putUShort(tmp
, code
);
1053 putUShort(tmp
+2, ds
.len
);
1055 memcpy(tmp
+4, ds
.data
, ds
.len
);
1056 /* update position */
1057 bufpos
+= (4 + ds
.len
);
1059 log_debug("No space for option %d",
1062 data_string_forget(&ds
, MDL
);
1064 log_error("Error evaluating option %d", code
);
1070 for (i
=0; i
< opt_state
->universe_count
; i
++) {
1071 if (opt_state
->universes
[i
] != NULL
) {
1072 o
= universes
[i
]->enc_opt
;
1074 (o
->universe
== &vsio_universe
)) {
1076 * Add the data from this VSIO option.
1080 vs
.bufpos
= bufpos
+8;
1081 option_space_foreach(packet
, NULL
,
1090 * If there was actually data here,
1093 if (vs
.bufpos
> bufpos
+8) {
1094 tmp
= (unsigned char *)buf
+
1099 vs
.bufpos
-bufpos
-4);
1100 putULong(tmp
+4, o
->code
);
1113 * Store all the requested options into the requested buffer.
1114 * XXX: ought to be static
1117 store_options(int *ocount
,
1118 unsigned char *buffer
, unsigned index
, unsigned buflen
,
1119 struct packet
*packet
, struct lease
*lease
,
1120 struct client_state
*client_state
,
1121 struct option_state
*in_options
,
1122 struct option_state
*cfg_options
,
1123 struct binding_scope
**scope
,
1124 unsigned *priority_list
, int priority_len
,
1125 unsigned first_cutoff
, int second_cutoff
, int terminate
,
1128 int bufix
= 0, six
= 0, tix
= 0;
1132 int bufend
, sbufend
;
1133 struct data_string od
;
1134 struct option_cache
*oc
;
1135 struct option
*option
= NULL
;
1139 * These arguments are relative to the start of the buffer, so
1140 * reduce them by the current buffer index, and advance the
1141 * buffer pointer to where we're going to start writing.
1143 buffer
= &buffer
[index
];
1146 first_cutoff
-= index
;
1148 second_cutoff
-= index
;
1150 /* Calculate the start and end of each section of the buffer */
1151 bufend
= sbufend
= buflen
;
1153 if (first_cutoff
>= buflen
)
1154 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
1155 bufend
= first_cutoff
;
1157 if (second_cutoff
) {
1158 if (second_cutoff
>= buflen
)
1159 log_fatal("%s:%d:store_options: Invalid second cutoff.",
1161 sbufend
= second_cutoff
;
1163 } else if (second_cutoff
) {
1164 if (second_cutoff
>= buflen
)
1165 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
1166 bufend
= second_cutoff
;
1169 memset (&od
, 0, sizeof od
);
1171 /* Eliminate duplicate options from the parameter request list.
1172 * Enforce RFC-mandated ordering of options that are present.
1174 for (i
= 0; i
< priority_len
- 1; i
++) {
1175 /* Eliminate duplicates. */
1177 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
1179 priority_list
[ix
- tto
] =
1181 if (priority_list
[i
] == priority_list
[ix
]) {
1187 /* Enforce ordering of SUBNET_MASK options, according to
1188 * RFC2132 Section 3.3:
1190 * If both the subnet mask and the router option are
1191 * specified in a DHCP reply, the subnet mask option MUST
1194 * This guidance does not specify what to do if the client
1195 * PRL explicitly requests the options out of order, it is
1196 * a general statement.
1198 if (priority_list
[i
] == DHO_SUBNET_MASK
) {
1199 for (ix
= i
- 1 ; ix
>= 0 ; ix
--) {
1200 if (priority_list
[ix
] == DHO_ROUTERS
) {
1202 priority_list
[ix
] = DHO_SUBNET_MASK
;
1203 priority_list
[i
] = DHO_ROUTERS
;
1210 /* Copy out the options in the order that they appear in the
1212 for (i
= 0; i
< priority_len
; i
++) {
1213 /* Number of bytes left to store (some may already
1214 have been stored by a previous pass). */
1216 int optstart
, soptstart
, toptstart
;
1218 int have_encapsulation
= 0;
1219 struct data_string encapsulation
;
1222 memset (&encapsulation
, 0, sizeof encapsulation
);
1223 have_encapsulation
= 0;
1226 option_dereference(&option
, MDL
);
1228 /* Code for next option to try to store. */
1229 code
= priority_list
[i
];
1231 /* Look up the option in the site option space if the code
1232 is above the cutoff, otherwise in the DHCP option space. */
1233 if (code
>= cfg_options
-> site_code_min
)
1234 u
= universes
[cfg_options
-> site_universe
];
1238 oc
= lookup_option (u
, cfg_options
, code
);
1240 if (oc
&& oc
->option
)
1241 option_reference(&option
, oc
->option
, MDL
);
1243 option_code_hash_lookup(&option
, u
->code_hash
, &code
, 0, MDL
);
1245 /* If it's a straight encapsulation, and the user supplied a
1246 * value for the entire option, use that. Otherwise, search
1247 * the encapsulated space.
1249 * If it's a limited encapsulation with preceding data, and the
1250 * user supplied values for the preceding bytes, search the
1251 * encapsulated space.
1253 if ((option
!= NULL
) &&
1254 (((oc
== NULL
) && (option
->format
[0] == 'E')) ||
1255 ((oc
!= NULL
) && (option
->format
[0] == 'e')))) {
1257 struct option_cache
*tmp
;
1258 struct data_string name
;
1260 s
= strchr (option
->format
, 'E');
1262 t
= strchr (++s
, '.');
1264 memset (&name
, 0, sizeof name
);
1266 /* A zero-length universe name means the vendor
1267 option space, if one is defined. */
1269 if (vendor_cfg_option
) {
1270 tmp
= lookup_option (vendor_cfg_option
-> universe
,
1272 vendor_cfg_option
-> code
);
1274 /* No need to check the return as we check name.len below */
1275 (void) evaluate_option_cache (&name
, packet
, lease
,
1280 } else if (vuname
) {
1281 name
.data
= (unsigned char *)s
;
1282 name
.len
= strlen (s
);
1285 name
.data
= (unsigned char *)s
;
1289 /* If we found a universe, and there are options configured
1290 for that universe, try to encapsulate it. */
1292 have_encapsulation
=
1293 (option_space_encapsulate
1294 (&encapsulation
, packet
, lease
, client_state
,
1295 in_options
, cfg_options
, scope
, &name
));
1296 data_string_forget (&name
, MDL
);
1301 /* In order to avoid memory leaks, we have to get to here
1302 with any option cache that we allocated in tmp not being
1303 referenced by tmp, and whatever option cache is referenced
1304 by oc being an actual reference. lookup_option doesn't
1305 generate a reference (this needs to be fixed), so the
1306 preceding goop ensures that if we *didn't* generate a new
1307 option cache, oc still winds up holding an actual reference. */
1309 /* If no data is available for this option, skip it. */
1310 if (!oc
&& !have_encapsulation
) {
1314 /* Find the value of the option... */
1317 /* No need to check the return as we check od.len below */
1318 (void) evaluate_option_cache (&od
, packet
,
1319 lease
, client_state
, in_options
,
1320 cfg_options
, scope
, oc
, MDL
);
1322 /* If we have encapsulation for this option, and an oc
1323 * lookup succeeded, but the evaluation failed, it is
1324 * either because this is a complex atom (atoms before
1325 * E on format list) and the top half of the option is
1326 * not configured, or this is a simple encapsulated
1327 * space and the evaluator is giving us a NULL. Prefer
1328 * the evaluator's opinion over the subspace.
1331 data_string_forget (&encapsulation
, MDL
);
1332 data_string_forget (&od
, MDL
);
1337 /* We should now have a constant length for the option. */
1339 if (have_encapsulation
) {
1340 length
+= encapsulation
.len
;
1342 /* od.len can be nonzero if we got here without an
1343 * oc (cache lookup failed), but did have an encapsulated
1344 * simple encapsulation space.
1347 data_string_copy (&od
, &encapsulation
, MDL
);
1348 data_string_forget (&encapsulation
, MDL
);
1350 struct buffer
*bp
= (struct buffer
*)0;
1351 if (!buffer_allocate (&bp
, length
, MDL
)) {
1352 option_cache_dereference (&oc
, MDL
);
1353 data_string_forget (&od
, MDL
);
1354 data_string_forget (&encapsulation
, MDL
);
1357 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
1358 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
1360 data_string_forget (&od
, MDL
);
1361 data_string_forget (&encapsulation
, MDL
);
1362 od
.data
= &bp
-> data
[0];
1363 buffer_reference (&od
.buffer
, bp
, MDL
);
1364 buffer_dereference (&bp
, MDL
);
1370 /* Do we add a NUL? */
1371 if (terminate
&& option
&& format_has_text(option
->format
)) {
1378 /* Try to store the option. */
1380 /* If the option's length is more than 255, we must store it
1381 in multiple hunks. Store 255-byte hunks first. However,
1382 in any case, if the option data will cross a buffer
1383 boundary, split it across that boundary. */
1395 unsigned incr
= length
;
1397 unsigned char *base
;
1399 /* Try to fit it in the options buffer. */
1401 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
1402 (bufix
+ 2 + length
< bufend
)) ||
1403 (bufix
+ 5 + length
< bufend
))) {
1406 /* Try to fit it in the second buffer. */
1407 } else if (!splitup
&& first_cutoff
&&
1408 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
1409 base
= &buffer
[first_cutoff
];
1411 /* Try to fit it in the third buffer. */
1412 } else if (!splitup
&& second_cutoff
&&
1413 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
1414 base
= &buffer
[second_cutoff
];
1416 /* Split the option up into the remaining space. */
1420 /* Use any remaining options space. */
1421 if (bufix
+ 6 < bufend
) {
1422 incr
= bufend
- bufix
- 5;
1425 /* Use any remaining first_cutoff space. */
1426 } else if (first_cutoff
&&
1427 (first_cutoff
+ six
+ 4 < sbufend
)) {
1428 incr
= sbufend
- (first_cutoff
+ six
) - 3;
1429 base
= &buffer
[first_cutoff
];
1431 /* Use any remaining second_cutoff space. */
1432 } else if (second_cutoff
&&
1433 (second_cutoff
+ tix
+ 4 < buflen
)) {
1434 incr
= buflen
- (second_cutoff
+ tix
) - 3;
1435 base
= &buffer
[second_cutoff
];
1437 /* Give up, roll back this option. */
1451 /* Everything looks good - copy it in! */
1453 base
[*pix
+ 1] = (unsigned char)incr
;
1454 if (tto
&& incr
== length
) {
1456 memcpy (base
+ *pix
+ 2,
1457 od
.data
+ ix
, (unsigned)(incr
- 1));
1458 base
[*pix
+ 2 + incr
- 1] = 0;
1460 memcpy (base
+ *pix
+ 2,
1461 od
.data
+ ix
, (unsigned)incr
);
1467 data_string_forget (&od
, MDL
);
1471 option_dereference(&option
, MDL
);
1473 /* If we can overload, and we have, then PAD and END those spaces. */
1474 if (first_cutoff
&& six
) {
1475 if ((first_cutoff
+ six
+ 1) < sbufend
)
1476 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1477 sbufend
- (first_cutoff
+ six
+ 1));
1478 else if (first_cutoff
+ six
>= sbufend
)
1479 log_fatal("Second buffer overflow in overloaded options.");
1481 buffer
[first_cutoff
+ six
] = DHO_END
;
1483 *ocount
|= 1; /* So that caller knows there's data there. */
1486 if (second_cutoff
&& tix
) {
1487 if (second_cutoff
+ tix
+ 1 < buflen
) {
1488 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1489 buflen
- (second_cutoff
+ tix
+ 1));
1490 } else if (second_cutoff
+ tix
>= buflen
)
1491 log_fatal("Third buffer overflow in overloaded options.");
1493 buffer
[second_cutoff
+ tix
] = DHO_END
;
1495 *ocount
|= 2; /* So that caller knows there's data there. */
1498 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1499 log_fatal("Not enough space for option overload option.");
1504 /* Return true if the format string has a variable length text option
1505 * ("t"), return false otherwise.
1509 format_has_text(format
)
1515 while (*p
!= '\0') {
1521 /* These symbols are arbitrary, not fixed or
1522 * determinable length...text options with them is
1523 * invalid (whatever the case, they are never NULL
1534 /* 'c' only follows 'D' atoms, and indicates that
1535 * compression may be used. If there was a 'D'
1536 * atom already, we would have returned. So this
1537 * is an error, but continue looking for 't' anyway.
1539 log_error("format_has_text(%s): 'c' atoms are illegal "
1540 "except after 'D' atoms.", format
);
1543 /* 'E' is variable length, but not arbitrary...you
1544 * can find its length if you can find an END option.
1545 * N is (n)-byte in length but trails a name of a
1546 * space defining the enumeration values. So treat
1547 * both the same - valid, fixed-length fields.
1551 /* Consume the space name. */
1552 while ((*p
!= '\0') && (*p
++ != '.'))
1564 /* Determine the minimum length of a DHCP option prior to any variable
1565 * or inconsistent length formats, according to its configured format
1566 * variable (and possibly from supplied option cache contents for variable
1567 * length format symbols).
1571 format_min_length(format
, oc
)
1573 struct option_cache
*oc
;
1575 const char *p
, *name
;
1578 struct enumeration
*espace
;
1581 while (*p
!= '\0') {
1583 case '6': /* IPv6 Address */
1588 case 'I': /* IPv4 Address */
1589 case 'l': /* int32_t */
1590 case 'L': /* uint32_t */
1591 case 'T': /* Lease Time, uint32_t equivalent */
1596 case 's': /* int16_t */
1597 case 'S': /* uint16_t */
1602 case 'N': /* Enumeration value. */
1603 /* Consume space name. */
1607 log_fatal("Corrupt format: %s", format
);
1609 espace
= find_enumeration(name
, p
- name
);
1610 if (espace
== NULL
) {
1611 log_error("Unknown enumeration: %s", format
);
1612 /* Max is safest value to return. */
1616 min_len
+= espace
->width
;
1617 last_size
= espace
->width
;
1622 case 'b': /* int8_t */
1623 case 'B': /* uint8_t */
1624 case 'F': /* Flag that is always true. */
1625 case 'f': /* Flag */
1630 case 'o': /* Last argument is optional. */
1631 min_len
-= last_size
;
1633 /* XXX: It MAY be possible to sense the end of an
1634 * encapsulated space, but right now this is too
1635 * hard to support. Return a safe value.
1637 case 'e': /* Encapsulation hint (there is an 'E' later). */
1638 case 'E': /* Encapsulated options. */
1641 case 'd': /* "Domain name" */
1642 case 'D': /* "rfc1035 formatted names" */
1643 case 't': /* "ASCII Text" */
1644 case 'X': /* "ASCII or Hex Conditional */
1645 case 'x': /* "Hex" */
1646 case 'A': /* Array of all that precedes. */
1647 case 'a': /* Array of preceding symbol. */
1648 case 'Z': /* nothing. */
1651 case 'c': /* Compress flag for D atom. */
1652 log_error("format_min_length(%s): 'c' atom is illegal "
1653 "except after 'D' atom.", format
);
1657 /* No safe value is known. */
1658 log_error("format_min_length(%s): No safe value "
1659 "for unknown format symbols.", format
);
1668 /* Format the specified option so that a human can easily read it. */
1670 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1671 struct option
*option
;
1672 const unsigned char *data
;
1677 static char optbuf
[32768]; /* XXX */
1678 static char *endbuf
= &optbuf
[sizeof(optbuf
)];
1686 char fmtbuf
[32] = "";
1688 struct enumeration
*enumbuf
[32]; /* MUST be same as fmtbuf */
1690 const unsigned char *dp
= data
;
1693 isc_boolean_t a_array
= ISC_FALSE
;
1701 memset (enumbuf
, 0, sizeof enumbuf
);
1703 /* Figure out the size of the data. */
1704 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1705 if (l
>= sizeof(fmtbuf
) - 1)
1706 log_fatal("Bounds failure on internal buffer at "
1710 log_error ("%s: Extra codes in format string: %s",
1712 &(option
-> format
[i
]));
1716 fmtbuf
[l
] = option
-> format
[i
];
1717 switch (option
-> format
[i
]) {
1727 /* Skip the universe name. */
1728 while (option
-> format
[i
] &&
1729 option
-> format
[i
] != '.')
1733 for (k
= 0; k
< len
; k
++) {
1734 if (!isascii (data
[k
]) ||
1735 !isprint (data
[k
]))
1738 /* If we found no bogus characters, or the bogus
1739 character we found is a trailing NUL, it's
1740 okay to print this option as text. */
1741 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1755 /* The 'c' atom is a 'D' modifier only. */
1756 log_error("'c' atom not following D atom in format "
1757 "string: %s", option
->format
);
1761 * Skip the 'c' atom, if present. It does not affect
1762 * how we convert wire->text format (if compression is
1763 * present either way, we still process it).
1765 if (option
->format
[i
+1] == 'c')
1772 /* Fall Through ! */
1779 while (option
-> format
[i
] &&
1780 option
-> format
[i
] != '.')
1783 find_enumeration (&option
-> format
[k
] + 1,
1785 if (enumbuf
[l
] == NULL
) {
1789 hunksize
+= enumbuf
[l
]->width
;
1790 hunkinc
= enumbuf
[l
]->width
;
1823 log_error ("%s: garbage in format string: %s",
1825 &(option
-> format
[i
]));
1830 /* Check for too few bytes... */
1831 if (hunksize
- opthunk
> len
) {
1832 log_error ("%s: expecting at least %d bytes; got %d",
1837 /* Check for too many bytes... */
1838 if (numhunk
== -1 && hunksize
< len
)
1839 log_error ("%s: %d extra bytes",
1843 /* If this is an array, compute its size. */
1845 if (a_array
== ISC_TRUE
) {
1847 * It is an 'a' type array - we repeat the
1848 * last format type. A binary string for 'X'
1849 * is also like this. hunkinc is the size
1850 * of the last format type and we add 1 to
1851 * cover the entire first record.
1853 numhunk
= ((len
- hunksize
) / hunkinc
) + 1;
1854 len_used
= hunksize
+ ((numhunk
- 1) * hunkinc
);
1857 * It is an 'A' type array - we repeat the
1860 numhunk
= len
/ hunksize
;
1861 len_used
= numhunk
* hunksize
;
1864 /* See if we got an exact number of hunks. */
1865 if (len_used
< len
) {
1866 log_error ("%s: %d extra bytes at end of array\n",
1873 /* A one-hunk array prints the same as a single hunk. */
1877 /* Cycle through the array (or hunk) printing the data. */
1878 for (i
= 0; i
< numhunk
; i
++) {
1879 if ((a_array
== ISC_TRUE
) && (i
!= 0) && (numelem
> 0)) {
1881 * For 'a' type of arrays we repeat
1882 * only the last format character
1883 * We should never hit the case of numelem == 0
1884 * but let's include the check to be safe.
1889 * for other types of arrays or the first
1890 * time through for 'a' types, we go through
1891 * the entire set of format characters.
1896 for (; j
< numelem
; j
++) {
1897 switch (fmtbuf
[j
]) {
1899 /* endbuf-1 leaves room for NULL. */
1900 k
= pretty_text(&op
, endbuf
- 1, &dp
,
1901 data
+ len
, emit_quotes
);
1903 log_error("Error printing text.");
1908 case 'D': /* RFC1035 format name list */
1909 for( ; dp
< (data
+ len
) ; dp
+= k
) {
1910 unsigned char nbuff
[NS_MAXCDNAME
];
1911 const unsigned char *nbp
, *nend
;
1913 nend
= &nbuff
[sizeof(nbuff
)];
1915 /* If this is for ISC DHCP consumption
1916 * (emit_quotes), lay it out as a list
1917 * of STRING tokens. Otherwise, it is
1918 * a space-separated list of DNS-
1919 * escaped names as /etc/resolv.conf
1923 if (op
+ 2 > endbuf
)
1931 /* XXX: if fmtbuf[j+1] != 'c', we
1932 * should warn if the data was
1933 * compressed anyway.
1935 k
= MRns_name_unpack(data
,
1941 log_error("Invalid domain "
1946 /* If emit_quotes, then use ISC DHCP
1947 * escapes. Otherwise, rely only on
1952 pretty_domain(&op
, endbuf
-1,
1955 /* ns_name_ntop() includes
1956 * a trailing NUL in its
1959 count
= MRns_name_ntop(
1964 log_error("Invalid "
1969 /* Consume all but the trailing
1974 /* Replace the trailing NUL
1975 * with the implicit root
1976 * (in the unlikely event the
1977 * domain name /is/ the root).
1984 /* pretty-printing an array of enums is
1985 going to get ugly. */
1992 switch (enumbuf
[j
]->width
) {
1994 tval
= getUChar(dp
);
1998 tval
= getUShort(dp
);
2002 tval
= getULong(dp
);
2006 log_fatal("Impossible case at %s:%d.",
2008 return "<double impossible condition>";
2012 if (!enumbuf
[j
] -> values
[i
].name
)
2014 if (enumbuf
[j
] -> values
[i
].value
==
2018 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
2019 dp
+= enumbuf
[j
]->width
;
2023 sprintf(op
, "%lu", tval
);
2028 memcpy(iaddr
.iabuf
, dp
, 4);
2029 strcpy(op
, piaddr(iaddr
));
2034 memcpy(iaddr
.iabuf
, dp
, 16);
2035 strcpy(op
, piaddr(iaddr
));
2039 sprintf (op
, "%ld", (long)getLong (dp
));
2043 tval
= getULong (dp
);
2045 sprintf (op
, "%s", "infinite");
2047 sprintf(op
, "%lu", tval
);
2051 (unsigned long)getULong(dp
));
2055 sprintf (op
, "%d", (int)getShort (dp
));
2059 sprintf(op
, "%u", (unsigned)getUShort(dp
));
2063 sprintf (op
, "%d", *(const char *)dp
++);
2066 sprintf (op
, "%d", *dp
++);
2070 sprintf (op
, "%x", *dp
++);
2073 strcpy (op
, *dp
++ ? "true" : "false");
2076 strcpy (op
, "true");
2083 log_error ("Unexpected format code %c",
2087 if (dp
== data
+ len
)
2089 if (j
+ 1 < numelem
&& comma
!= ':')
2092 if (i
+ 1 < numhunk
) {
2095 if (dp
== data
+ len
)
2101 int get_option (result
, universe
, packet
, lease
, client_state
,
2102 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2103 struct data_string
*result
;
2104 struct universe
*universe
;
2105 struct packet
*packet
;
2106 struct lease
*lease
;
2107 struct client_state
*client_state
;
2108 struct option_state
*in_options
;
2109 struct option_state
*cfg_options
;
2110 struct option_state
*options
;
2111 struct binding_scope
**scope
;
2116 struct option_cache
*oc
;
2118 if (!universe
-> lookup_func
)
2120 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
2123 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
2124 in_options
, cfg_options
, scope
, oc
,
2130 void set_option (universe
, options
, option
, op
)
2131 struct universe
*universe
;
2132 struct option_state
*options
;
2133 struct option_cache
*option
;
2134 enum statement_op op
;
2136 struct option_cache
*oc
, *noc
;
2141 case eval_statement
:
2142 case break_statement
:
2144 log_error ("bogus statement type in set_option.");
2147 case default_option_statement
:
2148 oc
= lookup_option (universe
, options
,
2149 option
-> option
-> code
);
2152 save_option (universe
, options
, option
);
2155 case supersede_option_statement
:
2156 case send_option_statement
:
2157 /* Install the option, replacing any existing version. */
2158 save_option (universe
, options
, option
);
2161 case append_option_statement
:
2162 case prepend_option_statement
:
2163 oc
= lookup_option (universe
, options
,
2164 option
-> option
-> code
);
2166 save_option (universe
, options
, option
);
2169 /* If it's not an expression, make it into one. */
2170 if (!oc
-> expression
&& oc
-> data
.len
) {
2171 if (!expression_allocate (&oc
-> expression
, MDL
)) {
2172 log_error ("Can't allocate const expression.");
2175 oc
-> expression
-> op
= expr_const_data
;
2177 (&oc
-> expression
-> data
.const_data
,
2179 data_string_forget (&oc
-> data
, MDL
);
2181 noc
= (struct option_cache
*)0;
2182 if (!option_cache_allocate (&noc
, MDL
))
2184 if (op
== append_option_statement
) {
2185 if (!make_concat (&noc
-> expression
,
2187 option
-> expression
)) {
2188 option_cache_dereference (&noc
, MDL
);
2192 if (!make_concat (&noc
-> expression
,
2193 option
-> expression
,
2194 oc
-> expression
)) {
2195 option_cache_dereference (&noc
, MDL
);
2199 option_reference(&(noc
->option
), oc
->option
, MDL
);
2200 save_option (universe
, options
, noc
);
2201 option_cache_dereference (&noc
, MDL
);
2206 struct option_cache
*lookup_option (universe
, options
, code
)
2207 struct universe
*universe
;
2208 struct option_state
*options
;
2212 return (struct option_cache
*)0;
2213 if (universe
-> lookup_func
)
2214 return (*universe
-> lookup_func
) (universe
, options
, code
);
2216 log_error ("can't look up options in %s space.",
2218 return (struct option_cache
*)0;
2221 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
2222 struct universe
*universe
;
2223 struct option_state
*options
;
2230 /* Make sure there's a hash table. */
2231 if (universe
-> index
>= options
-> universe_count
||
2232 !(options
-> universes
[universe
-> index
]))
2233 return (struct option_cache
*)0;
2235 hash
= options
-> universes
[universe
-> index
];
2237 hashix
= compute_option_hash (code
);
2238 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2239 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
2241 return (struct option_cache
*)(bptr
-> car
);
2243 return (struct option_cache
*)0;
2246 /* Save a specified buffer into an option cache. */
2248 save_option_buffer(struct universe
*universe
, struct option_state
*options
,
2249 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2250 unsigned code
, int terminatep
)
2252 struct option_cache
*op
= NULL
;
2255 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2261 save_option(universe
, options
, op
);
2265 option_cache_dereference(&op
, MDL
);
2270 /* Append a specified buffer onto the tail of an option cache. */
2272 append_option_buffer(struct universe
*universe
, struct option_state
*options
,
2273 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2274 unsigned code
, int terminatep
)
2276 struct option_cache
*op
= NULL
;
2279 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2285 also_save_option(universe
, options
, op
);
2289 option_cache_dereference(&op
, MDL
);
2294 /* Create/copy a buffer into a new option cache. */
2296 prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
2297 unsigned char *buffer
, unsigned length
, unsigned code
,
2298 int terminatep
, struct option_cache
**opp
)
2300 struct buffer
*lbp
= NULL
;
2301 struct option
*option
= NULL
;
2302 struct option_cache
*op
;
2305 /* Code sizes of 8, 16, and 32 bits are allowed. */
2306 switch(universe
->tag_size
) {
2316 if (code
> 0xffffffff)
2321 log_fatal("Inconsistent universe tag size at %s:%d.", MDL
);
2324 option_code_hash_lookup(&option
, universe
->code_hash
, &code
, 0, MDL
);
2326 /* If we created an option structure for each option a client
2327 * supplied, it's possible we may create > 2^32 option structures.
2328 * That's not feasible. So by failing to enter these option
2329 * structures into the code and name hash tables, references will
2330 * never be more than 1 - when the option cache is destroyed, this
2331 * will be cleaned up.
2334 char nbuf
[sizeof("unknown-4294967295")];
2336 sprintf(nbuf
, "unknown-%u", code
);
2338 option
= new_option(nbuf
, MDL
);
2343 option
->format
= default_option_format
;
2344 option
->universe
= universe
;
2345 option
->code
= code
;
2347 /* new_option() doesn't set references, pretend. */
2351 if (!option_cache_allocate (opp
, MDL
)) {
2352 log_error("No memory for option code %s.%s.",
2353 universe
->name
, option
->name
);
2358 /* Pointer rather than double pointer makes for less parens. */
2361 option_reference(&op
->option
, option
, MDL
);
2363 /* If we weren't passed a buffer in which the data are saved and
2364 refcounted, allocate one now. */
2366 if (!buffer_allocate (&lbp
, length
+ terminatep
, MDL
)) {
2367 log_error ("no memory for option buffer.");
2372 memcpy (lbp
-> data
, buffer
, length
+ terminatep
);
2374 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
2377 /* Reference buffer copy to option cache. */
2378 op
-> data
.buffer
= (struct buffer
*)0;
2379 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
2381 /* Point option cache into buffer. */
2382 op
-> data
.data
= buffer
;
2383 op
-> data
.len
= length
;
2386 /* NUL terminate (we can get away with this because we (or
2387 the caller!) allocated one more than the buffer size, and
2388 because the byte following the end of an option is always
2389 the code of the next option, which the caller is getting
2390 out of the *original* buffer. */
2391 buffer
[length
] = 0;
2392 op
-> data
.terminated
= 1;
2394 op
-> data
.terminated
= 0;
2396 /* If this option is ultimately a text option, null determinate to
2397 * comply with RFC2132 section 2. Mark a flag so this can be sensed
2398 * later to echo NULLs back to clients that supplied them (they
2399 * probably expect them).
2401 if (format_has_text(option
->format
)) {
2402 int min_len
= format_min_length(option
->format
, op
);
2404 while ((op
->data
.len
> min_len
) &&
2405 (op
->data
.data
[op
->data
.len
-1] == '\0')) {
2407 op
->flags
|= OPTION_HAD_NULLS
;
2411 /* And let go of our references. */
2414 buffer_dereference(&lbp
, MDL
);
2415 option_dereference(&option
, MDL
);
2421 count_options(struct option_cache
*dummy_oc
,
2422 struct packet
*dummy_packet
,
2423 struct lease
*dummy_lease
,
2424 struct client_state
*dummy_client_state
,
2425 struct option_state
*dummy_opt_state
,
2426 struct option_state
*opt_state
,
2427 struct binding_scope
**dummy_binding_scope
,
2428 struct universe
*dummy_universe
,
2429 void *void_accumulator
) {
2430 int *accumulator
= (int *)void_accumulator
;
2436 collect_oro(struct option_cache
*oc
,
2437 struct packet
*dummy_packet
,
2438 struct lease
*dummy_lease
,
2439 struct client_state
*dummy_client_state
,
2440 struct option_state
*dummy_opt_state
,
2441 struct option_state
*opt_state
,
2442 struct binding_scope
**dummy_binding_scope
,
2443 struct universe
*dummy_universe
,
2445 struct data_string
*oro
= (struct data_string
*)void_oro
;
2447 putUShort(oro
->buffer
->data
+ oro
->len
, oc
->option
->code
);
2451 /* build_server_oro() is presently unusued, but may be used at a future date
2452 * with support for Reconfigure messages (as a hint to the client about new
2453 * option value contents).
2456 build_server_oro(struct data_string
*server_oro
,
2457 struct option_state
*options
,
2458 const char *file
, int line
) {
2464 * Count the number of options, so we can allocate enough memory.
2465 * We want to mention sub-options too, so check all universes.
2468 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2469 NULL
, &dhcpv6_universe
, (void *)&num_opts
,
2471 for (i
=0; i
< options
->universe_count
; i
++) {
2472 if (options
->universes
[i
] != NULL
) {
2473 o
= universes
[i
]->enc_opt
;
2475 if (o
->universe
== &dhcpv6_universe
) {
2479 o
= o
->universe
->enc_opt
;
2487 memset(server_oro
, 0, sizeof(*server_oro
));
2488 if (!buffer_allocate(&server_oro
->buffer
, num_opts
* 2, MDL
)) {
2489 log_fatal("no memory to build server ORO");
2491 server_oro
->data
= server_oro
->buffer
->data
;
2495 * We want to mention sub-options too, so check all universes.
2497 server_oro
->len
= 0; /* gets set in collect_oro */
2498 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2499 NULL
, &dhcpv6_universe
, (void *)server_oro
,
2501 for (i
=0; i
< options
->universe_count
; i
++) {
2502 if (options
->universes
[i
] != NULL
) {
2503 o
= universes
[i
]->enc_opt
;
2505 if (o
->universe
== &dhcpv6_universe
) {
2507 tmp
= server_oro
->buffer
->data
;
2508 putUShort(tmp
+ server_oro
->len
,
2510 server_oro
->len
+= 2;
2513 o
= o
->universe
->enc_opt
;
2519 /* Wrapper function to put an option cache into an option state. */
2521 save_option(struct universe
*universe
, struct option_state
*options
,
2522 struct option_cache
*oc
)
2524 if (universe
->save_func
)
2525 (*universe
->save_func
)(universe
, options
, oc
, ISC_FALSE
);
2527 log_error("can't store options in %s space.", universe
->name
);
2530 /* Wrapper function to append an option cache into an option state's list. */
2532 also_save_option(struct universe
*universe
, struct option_state
*options
,
2533 struct option_cache
*oc
)
2535 if (universe
->save_func
)
2536 (*universe
->save_func
)(universe
, options
, oc
, ISC_TRUE
);
2538 log_error("can't store options in %s space.", universe
->name
);
2542 save_hashed_option(struct universe
*universe
, struct option_state
*options
,
2543 struct option_cache
*oc
, isc_boolean_t appendp
)
2547 pair
*hash
= options
-> universes
[universe
-> index
];
2548 struct option_cache
**ocloc
;
2550 if (oc
-> refcnt
== 0)
2553 /* Compute the hash. */
2554 hashix
= compute_option_hash (oc
-> option
-> code
);
2556 /* If there's no hash table, make one. */
2558 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
2560 log_error ("no memory to store %s.%s",
2561 universe
-> name
, oc
-> option
-> name
);
2564 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
2565 options
-> universes
[universe
-> index
] = (void *)hash
;
2567 /* Try to find an existing option matching the new one. */
2568 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2569 if (((struct option_cache
*)
2570 (bptr
-> car
)) -> option
-> code
==
2571 oc
-> option
-> code
)
2575 /* Deal with collisions on the hash list. */
2577 ocloc
= (struct option_cache
**)&bptr
->car
;
2580 * If appendp is set, append it onto the tail of the
2581 * ->next list. If it is not set, rotate it into
2582 * position at the head of the list.
2586 ocloc
= &(*ocloc
)->next
;
2587 } while (*ocloc
!= NULL
);
2589 option_cache_dereference(ocloc
, MDL
);
2592 option_cache_reference(ocloc
, oc
, MDL
);
2597 /* Otherwise, just put the new one at the head of the list. */
2598 bptr
= new_pair (MDL
);
2600 log_error ("No memory for option_cache reference.");
2603 bptr
-> cdr
= hash
[hashix
];
2605 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
2606 hash
[hashix
] = bptr
;
2609 void delete_option (universe
, options
, code
)
2610 struct universe
*universe
;
2611 struct option_state
*options
;
2614 if (universe
-> delete_func
)
2615 (*universe
-> delete_func
) (universe
, options
, code
);
2617 log_error ("can't delete options from %s space.",
2621 void delete_hashed_option (universe
, options
, code
)
2622 struct universe
*universe
;
2623 struct option_state
*options
;
2627 pair bptr
, prev
= (pair
)0;
2628 pair
*hash
= options
-> universes
[universe
-> index
];
2630 /* There may not be any options in this space. */
2634 /* Try to find an existing option matching the new one. */
2635 hashix
= compute_option_hash (code
);
2636 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2637 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
2642 /* If we found one, wipe it out... */
2645 prev
-> cdr
= bptr
-> cdr
;
2647 hash
[hashix
] = bptr
-> cdr
;
2648 option_cache_dereference
2649 ((struct option_cache
**)(&bptr
-> car
), MDL
);
2650 free_pair (bptr
, MDL
);
2654 extern struct option_cache
*free_option_caches
; /* XXX */
2656 int option_cache_dereference (ptr
, file
, line
)
2657 struct option_cache
**ptr
;
2661 if (!ptr
|| !*ptr
) {
2662 log_error ("Null pointer in option_cache_dereference: %s(%d)",
2664 #if defined (POINTER_DEBUG)
2672 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
2673 if (!(*ptr
) -> refcnt
) {
2674 if ((*ptr
) -> data
.buffer
)
2675 data_string_forget (&(*ptr
) -> data
, file
, line
);
2677 option_dereference(&(*ptr
)->option
, MDL
);
2678 if ((*ptr
) -> expression
)
2679 expression_dereference (&(*ptr
) -> expression
,
2682 option_cache_dereference (&((*ptr
) -> next
),
2684 /* Put it back on the free list... */
2685 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
2686 free_option_caches
= *ptr
;
2687 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
2689 if ((*ptr
) -> refcnt
< 0) {
2690 log_error ("%s(%d): negative refcnt!", file
, line
);
2691 #if defined (DEBUG_RC_HISTORY)
2692 dump_rc_history (*ptr
);
2694 #if defined (POINTER_DEBUG)
2697 *ptr
= (struct option_cache
*)0;
2701 *ptr
= (struct option_cache
*)0;
2706 int hashed_option_state_dereference (universe
, state
, file
, line
)
2707 struct universe
*universe
;
2708 struct option_state
*state
;
2716 /* Get the pointer to the array of hash table bucket heads. */
2717 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
2721 /* For each non-null head, loop through all the buckets dereferencing
2722 the attached option cache structures and freeing the buckets. */
2723 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2724 for (cp
= heads
[i
]; cp
; cp
= next
) {
2726 option_cache_dereference
2727 ((struct option_cache
**)&cp
-> car
,
2729 free_pair (cp
, file
, line
);
2733 dfree (heads
, file
, line
);
2734 state
-> universes
[universe
-> index
] = (void *)0;
2738 /* The 'data_string' primitive doesn't have an appension mechanism.
2739 * This function must then append a new option onto an existing buffer
2740 * by first duplicating the original buffer and appending the desired
2741 * values, followed by coping the new value into place.
2744 append_option(struct data_string
*dst
, struct universe
*universe
,
2745 struct option
*option
, struct data_string
*src
)
2747 struct data_string tmp
;
2749 if (src
->len
== 0 && option
->format
[0] != 'Z')
2752 memset(&tmp
, 0, sizeof(tmp
));
2754 /* Allocate a buffer to hold existing data, the current option's
2755 * tag and length, and the option's content.
2757 if (!buffer_allocate(&tmp
.buffer
,
2758 (dst
->len
+ universe
->length_size
+
2759 universe
->tag_size
+ src
->len
), MDL
)) {
2760 /* XXX: This kills all options presently stored in the
2761 * destination buffer. This is the way the original code
2762 * worked, and assumes an 'all or nothing' approach to
2763 * eg encapsulated option spaces. It may or may not be
2766 data_string_forget(dst
, MDL
);
2769 tmp
.data
= tmp
.buffer
->data
;
2771 /* Copy the existing data off the destination. */
2773 memcpy(tmp
.buffer
->data
, dst
->data
, dst
->len
);
2776 /* Place the new option tag and length. */
2777 (*universe
->store_tag
)(tmp
.buffer
->data
+ tmp
.len
, option
->code
);
2778 tmp
.len
+= universe
->tag_size
;
2779 (*universe
->store_length
)(tmp
.buffer
->data
+ tmp
.len
, src
->len
);
2780 tmp
.len
+= universe
->length_size
;
2782 /* Copy the option contents onto the end. */
2783 memcpy(tmp
.buffer
->data
+ tmp
.len
, src
->data
, src
->len
);
2784 tmp
.len
+= src
->len
;
2786 /* Play the shell game. */
2787 data_string_forget(dst
, MDL
);
2788 data_string_copy(dst
, &tmp
, MDL
);
2789 data_string_forget(&tmp
, MDL
);
2794 store_option(struct data_string
*result
, struct universe
*universe
,
2795 struct packet
*packet
, struct lease
*lease
,
2796 struct client_state
*client_state
,
2797 struct option_state
*in_options
, struct option_state
*cfg_options
,
2798 struct binding_scope
**scope
, struct option_cache
*oc
)
2800 struct data_string tmp
;
2801 struct universe
*subu
=NULL
;
2805 memset(&tmp
, 0, sizeof(tmp
));
2807 if (evaluate_option_cache(&tmp
, packet
, lease
, client_state
,
2808 in_options
, cfg_options
, scope
, oc
, MDL
)) {
2809 /* If the option is an extended 'e'ncapsulation (not a
2810 * direct 'E'ncapsulation), append the encapsulated space
2811 * onto the currently prepared value.
2814 if (oc
->option
->format
&&
2815 oc
->option
->format
[0] == 'e') {
2816 /* Skip forward to the universe name. */
2817 start
= strchr(oc
->option
->format
, 'E');
2821 /* Locate the name-terminating '.'. */
2822 end
= strchr(++start
, '.');
2824 /* A zero-length name is not allowed in
2825 * these kinds of encapsulations.
2827 if (end
== NULL
|| start
== end
)
2830 universe_hash_lookup(&subu
, universe_hash
,
2831 start
, end
- start
, MDL
);
2834 log_error("store_option: option %d "
2835 "refers to unknown "
2836 "option space '%.*s'.",
2838 (int)(end
- start
), start
);
2842 /* Append encapsulations, if any. We
2843 * already have the prepended values, so
2844 * we send those even if there are no
2845 * encapsulated options (and ->encapsulate()
2848 subu
->encapsulate(&tmp
, packet
, lease
,
2849 client_state
, in_options
,
2850 cfg_options
, scope
, subu
);
2853 } while (ISC_FALSE
);
2855 status
= append_option(result
, universe
, oc
->option
, &tmp
);
2856 data_string_forget(&tmp
, MDL
);
2864 int option_space_encapsulate (result
, packet
, lease
, client_state
,
2865 in_options
, cfg_options
, scope
, name
)
2866 struct data_string
*result
;
2867 struct packet
*packet
;
2868 struct lease
*lease
;
2869 struct client_state
*client_state
;
2870 struct option_state
*in_options
;
2871 struct option_state
*cfg_options
;
2872 struct binding_scope
**scope
;
2873 struct data_string
*name
;
2875 struct universe
*u
= NULL
;
2878 universe_hash_lookup(&u
, universe_hash
,
2879 (const char *)name
->data
, name
->len
, MDL
);
2881 log_error("option_space_encapsulate: option space '%.*s' does "
2882 "not exist, but is configured.",
2883 (int)name
->len
, name
->data
);
2887 if (u
->encapsulate
!= NULL
) {
2888 if (u
->encapsulate(result
, packet
, lease
, client_state
,
2889 in_options
, cfg_options
, scope
, u
))
2892 log_error("encapsulation requested for '%s' with no support.",
2898 /* Attempt to store any 'E'ncapsulated options that have not yet been
2899 * placed on the option buffer by the above (configuring a value in
2900 * the space over-rides any values in the child universe).
2902 * Note that there are far fewer universes than there will ever be
2903 * options in any universe. So it is faster to traverse the
2904 * configured universes, checking if each is encapsulated in the
2905 * current universe, and if so attempting to do so.
2907 * For each configured universe for this configuration option space,
2908 * which is encapsulated within the current universe, can not be found
2909 * by the lookup function (the universe-specific encapsulation
2910 * functions would already have stored such a value), and encapsulates
2911 * at least one option, append it.
2914 search_subencapsulation(struct data_string
*result
, struct packet
*packet
,
2915 struct lease
*lease
, struct client_state
*client_state
,
2916 struct option_state
*in_options
,
2917 struct option_state
*cfg_options
,
2918 struct binding_scope
**scope
,
2919 struct universe
*universe
)
2921 struct data_string sub
;
2922 struct universe
*subu
;
2925 memset(&sub
, 0, sizeof(sub
));
2926 for (i
= 0 ; i
< cfg_options
->universe_count
; i
++) {
2927 subu
= universes
[i
];
2930 log_fatal("Impossible condition at %s:%d.", MDL
);
2932 if (subu
->enc_opt
!= NULL
&&
2933 subu
->enc_opt
->universe
== universe
&&
2934 subu
->enc_opt
->format
!= NULL
&&
2935 subu
->enc_opt
->format
[0] == 'E' &&
2936 lookup_option(universe
, cfg_options
,
2937 subu
->enc_opt
->code
) == NULL
&&
2938 subu
->encapsulate(&sub
, packet
, lease
, client_state
,
2939 in_options
, cfg_options
,
2941 if (append_option(result
, universe
,
2942 subu
->enc_opt
, &sub
))
2945 data_string_forget(&sub
, MDL
);
2952 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
2953 in_options
, cfg_options
, scope
, universe
)
2954 struct data_string
*result
;
2955 struct packet
*packet
;
2956 struct lease
*lease
;
2957 struct client_state
*client_state
;
2958 struct option_state
*in_options
;
2959 struct option_state
*cfg_options
;
2960 struct binding_scope
**scope
;
2961 struct universe
*universe
;
2967 if (universe
-> index
>= cfg_options
-> universe_count
)
2970 hash
= cfg_options
-> universes
[universe
-> index
];
2974 /* For each hash bucket, and each configured option cache within
2975 * that bucket, append the option onto the buffer in encapsulated
2976 * format appropriate to the universe.
2979 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2980 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2981 if (store_option(result
, universe
, packet
, lease
,
2982 client_state
, in_options
, cfg_options
,
2983 scope
, (struct option_cache
*)p
->car
))
2988 if (search_subencapsulation(result
, packet
, lease
, client_state
,
2989 in_options
, cfg_options
, scope
, universe
))
2995 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
2996 in_options
, cfg_options
, scope
, universe
)
2997 struct data_string
*result
;
2998 struct packet
*packet
;
2999 struct lease
*lease
;
3000 struct client_state
*client_state
;
3001 struct option_state
*in_options
;
3002 struct option_state
*cfg_options
;
3003 struct binding_scope
**scope
;
3004 struct universe
*universe
;
3008 static struct option_cache
*no_nwip
;
3009 struct data_string ds
;
3010 struct option_chain_head
*head
;
3012 if (universe
-> index
>= cfg_options
-> universe_count
)
3014 head
= ((struct option_chain_head
*)
3015 cfg_options
-> universes
[nwip_universe
.index
]);
3020 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3021 if (store_option (result
, universe
, packet
,
3022 lease
, client_state
, in_options
,
3024 (struct option_cache
*)ocp
-> car
))
3028 /* If there's no data, the nwip suboption is supposed to contain
3029 a suboption saying there's no data. */
3033 static unsigned char nni
[] = { 1, 0 };
3035 memset (&ds
, 0, sizeof ds
);
3038 if (option_cache_allocate (&no_nwip
, MDL
))
3039 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
3040 if (!option_code_hash_lookup(&no_nwip
->option
,
3041 nwip_universe
.code_hash
,
3043 log_fatal("Nwip option hash does not contain "
3047 if (store_option (result
, universe
, packet
, lease
,
3048 client_state
, in_options
,
3049 cfg_options
, scope
, no_nwip
))
3053 memset (&ds
, 0, sizeof ds
);
3055 /* If we have nwip options, the first one has to be the
3056 nwip-exists-in-option-area option. */
3057 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
3058 data_string_forget (result
, MDL
);
3061 ds
.data
= &ds
.buffer
-> data
[0];
3062 ds
.buffer
-> data
[0] = 2;
3063 ds
.buffer
-> data
[1] = 0;
3064 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
3065 data_string_forget (result
, MDL
);
3066 data_string_copy (result
, &ds
, MDL
);
3067 data_string_forget (&ds
, MDL
);
3073 /* We don't want to use ns_name_pton()...it doesn't tell us how many bytes
3074 * it has consumed, and it plays havoc with our escapes.
3076 * So this function does DNS encoding, and returns either the number of
3077 * octects consumed (on success), or -1 on failure.
3080 fqdn_encode(unsigned char *dst
, int dstlen
, const unsigned char *src
,
3084 int i
, j
, len
, outlen
=0;
3087 for (i
= 0, j
= 0 ; i
< srclen
; i
= j
) {
3088 while ((j
< srclen
) && (src
[j
] != '.') && (src
[j
] != '\0'))
3092 if ((outlen
+ 1 + len
) > dstlen
)
3098 /* We only do one FQDN, ending in one root label. */
3102 memcpy(out
, src
+ i
, len
);
3106 /* Advance past the root label. */
3110 if ((outlen
+ 1) > dstlen
)
3113 /* Place the root label. */
3120 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
3121 in_options
, cfg_options
, scope
, universe
)
3122 struct data_string
*result
;
3123 struct packet
*packet
;
3124 struct lease
*lease
;
3125 struct client_state
*client_state
;
3126 struct option_state
*in_options
;
3127 struct option_state
*cfg_options
;
3128 struct binding_scope
**scope
;
3129 struct universe
*universe
;
3132 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3136 struct buffer
*bp
= (struct buffer
*)0;
3137 struct option_chain_head
*head
;
3139 /* If there's no FQDN universe, don't encapsulate. */
3140 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
3142 head
= ((struct option_chain_head
*)
3143 cfg_options
-> universes
[fqdn_universe
.index
]);
3147 /* Figure out the values of all the suboptions. */
3148 memset (results
, 0, sizeof results
);
3149 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3150 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
3151 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
3153 /* No need to check the return code, we check the length later */
3154 (void) evaluate_option_cache (&results
[oc
->option
->code
],
3155 packet
, lease
, client_state
,
3156 in_options
, cfg_options
, scope
,
3159 /* We add a byte for the flags field.
3160 * We add two bytes for the two RCODE fields.
3161 * We add a byte because we will prepend a label count.
3162 * We add a byte because the input len doesn't count null termination,
3163 * and we will add a root label.
3165 len
= 5 + results
[FQDN_FQDN
].len
;
3166 /* Save the contents of the option in a buffer. */
3167 if (!buffer_allocate (&bp
, len
, MDL
)) {
3168 log_error ("no memory for option buffer.");
3172 buffer_reference (&result
-> buffer
, bp
, MDL
);
3174 result
-> data
= &bp
-> data
[0];
3176 memset (&bp
-> data
[0], 0, len
);
3177 /* XXX: The server should set bit 4 (yes, 4, not 3) to 1 if it is
3178 * not going to perform any ddns updates. The client should set the
3179 * bit if it doesn't want the server to perform any updates.
3180 * The problem is at this layer of abstraction we have no idea if
3181 * the caller is a client or server.
3183 * See RFC4702, Section 3.1, 'The "N" bit'.
3188 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3189 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3190 bp
-> data
[0] |= 2;
3191 if (results
[FQDN_SERVER_UPDATE
].len
&&
3192 results
[FQDN_SERVER_UPDATE
].data
[0])
3193 bp
-> data
[0] |= 1;
3194 if (results
[FQDN_RCODE1
].len
)
3195 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
3196 if (results
[FQDN_RCODE2
].len
)
3197 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
3199 if (results
[FQDN_ENCODED
].len
&&
3200 results
[FQDN_ENCODED
].data
[0]) {
3202 if (results
[FQDN_FQDN
].len
) {
3203 i
= fqdn_encode(&bp
->data
[3], len
- 3,
3204 results
[FQDN_FQDN
].data
,
3205 results
[FQDN_FQDN
].len
);
3213 result
->terminated
= 0;
3216 if (results
[FQDN_FQDN
].len
) {
3217 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
3218 results
[FQDN_FQDN
].len
);
3219 result
-> len
+= results
[FQDN_FQDN
].len
;
3220 result
-> terminated
= 0;
3224 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3225 if (results
[i
].len
)
3226 data_string_forget (&results
[i
], MDL
);
3228 buffer_dereference (&bp
, MDL
);
3230 data_string_forget(result
, MDL
);
3235 * Trap invalid attempts to inspect FQND6 contents.
3237 struct option_cache
*
3238 lookup_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3241 log_fatal("Impossible condition at %s:%d.", MDL
);
3246 * Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
3249 save_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3250 struct option_cache
*oc
, isc_boolean_t appendp
)
3252 log_fatal("Impossible condition at %s:%d.", MDL
);
3256 * Trap invalid attempts to delete an option out of the FQDN6 universe.
3259 delete_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3262 log_fatal("Impossible condition at %s:%d.", MDL
);
3265 /* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
3266 * V6's option cache entry.
3268 * This function is called speculatively by dhclient to setup
3269 * environment variables. But it would have already called the
3270 * foreach on the normal fqdn universe, so this is superfluous.
3273 fqdn6_option_space_foreach(struct packet
*packet
, struct lease
*lease
,
3274 struct client_state
*client_state
,
3275 struct option_state
*in_options
,
3276 struct option_state
*cfg_options
,
3277 struct binding_scope
**scope
,
3278 struct universe
*u
, void *stuff
,
3279 void (*func
)(struct option_cache
*,
3282 struct client_state
*,
3283 struct option_state
*,
3284 struct option_state
*,
3285 struct binding_scope
**,
3286 struct universe
*, void *))
3288 /* Pretend it is empty. */
3292 /* Turn the FQDN option space into a DHCPv6 FQDN option buffer.
3295 fqdn6_option_space_encapsulate(struct data_string
*result
,
3296 struct packet
*packet
, struct lease
*lease
,
3297 struct client_state
*client_state
,
3298 struct option_state
*in_options
,
3299 struct option_state
*cfg_options
,
3300 struct binding_scope
**scope
,
3301 struct universe
*universe
)
3304 struct option_chain_head
*head
;
3305 struct option_cache
*oc
;
3306 unsigned char *data
;
3307 int i
, len
, rval
= 0, count
;
3308 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3310 if (fqdn_universe
.index
>= cfg_options
->universe_count
)
3312 head
= ((struct option_chain_head
*)
3313 cfg_options
->universes
[fqdn_universe
.index
]);
3317 memset(results
, 0, sizeof(results
));
3318 for (ocp
= head
->first
; ocp
!= NULL
; ocp
= ocp
->cdr
) {
3319 oc
= (struct option_cache
*)(ocp
->car
);
3320 if (oc
->option
->code
> FQDN_SUBOPTION_COUNT
)
3321 log_fatal("Impossible condition at %s:%d.", MDL
);
3322 /* No need to check the return code, we check the length later */
3323 (void) evaluate_option_cache(&results
[oc
->option
->code
], packet
,
3324 lease
, client_state
, in_options
,
3325 cfg_options
, scope
, oc
, MDL
);
3328 /* We add a byte for the flags field at the start of the option.
3329 * We add a byte because we will prepend a label count.
3330 * We add a byte because the input length doesn't include a trailing
3331 * NULL, and we will add a root label.
3333 len
= results
[FQDN_FQDN
].len
+ 3;
3334 if (!buffer_allocate(&result
->buffer
, len
, MDL
)) {
3335 log_error("No memory for virtual option buffer.");
3338 data
= result
->buffer
->data
;
3339 result
->data
= data
;
3341 /* The first byte is the flags field. */
3344 /* XXX: The server should set bit 3 (yes, 3, not 4) to 1 if we
3345 * are not going to perform any DNS updates. The problem is
3346 * that at this layer of abstraction, we do not know if the caller
3347 * is the client or the server.
3349 * See RFC4704 Section 4.1, 'The "N" bit'.
3354 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3355 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3357 if (results
[FQDN_SERVER_UPDATE
].len
&&
3358 results
[FQDN_SERVER_UPDATE
].data
[0])
3361 /* If there is no name, we're done. */
3362 if (results
[FQDN_FQDN
].len
== 0) {
3367 /* Convert textual representation to DNS format. */
3368 count
= fqdn_encode(data
+ 1, len
- 1,
3369 results
[FQDN_FQDN
].data
, results
[FQDN_FQDN
].len
);
3373 data_string_forget(result
, MDL
);
3377 result
->len
+= count
;
3378 result
->terminated
= 0;
3384 for (i
= 1 ; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3386 data_string_forget(&results
[i
], MDL
);
3392 /* Read the DHCPv6 FQDN option's contents into the FQDN virtual space.
3395 fqdn6_universe_decode(struct option_state
*options
,
3396 const unsigned char *buffer
, unsigned length
,
3399 struct buffer
*bp
= NULL
;
3400 unsigned char *first_dot
;
3401 int len
, hlen
, dlen
;
3403 /* The FQDN option has to be at least 1 byte long. */
3407 /* Save the contents of the option in a buffer. There are 3
3408 * one-byte values we record from the packet, so we go ahead
3409 * and allocate a bigger buffer to accommodate them. But the
3410 * 'length' we got (because it is a DNS encoded string) is
3411 * one longer than we need...so we only add two extra octets.
3413 if (!buffer_allocate(&bp
, length
+ 2, MDL
)) {
3414 log_error("No memory for dhcp6.fqdn option buffer.");
3418 /* The v6 FQDN is always 'encoded' per DNS. */
3420 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3421 bp
->data
, 1, FQDN_ENCODED
, 0))
3424 /* XXX: We need to process 'The "N" bit'. */
3426 if (buffer
[0] & 1) /* server-update. */
3431 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 2, 1,
3432 FQDN_SERVER_UPDATE
, 0))
3435 if (buffer
[0] & 2) /* no-client-update. */
3440 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 1, 1,
3441 FQDN_NO_CLIENT_UPDATE
, 0))
3444 /* Convert the domain name to textual representation for config. */
3445 len
= MRns_name_ntop(buffer
+ 1, (char *)bp
->data
+ 3, length
- 1);
3447 log_error("Unable to convert dhcp6.fqdn domain name to "
3452 /* Save the domain name. */
3454 unsigned char *fqdn_start
= bp
->data
+ 3;
3456 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3457 fqdn_start
, len
, FQDN_FQDN
, 1))
3460 first_dot
= (unsigned char *)strchr((char *)fqdn_start
, '.');
3462 if (first_dot
!= NULL
) {
3463 hlen
= first_dot
- fqdn_start
;
3470 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3471 fqdn_start
, len
, FQDN_FQDN
, 1) ||
3473 !save_option_buffer(&fqdn_universe
, options
, bp
,
3475 FQDN_HOSTNAME
, 0)) ||
3477 !save_option_buffer(&fqdn_universe
, options
, bp
,
3478 first_dot
, dlen
, FQDN_DOMAINNAME
, 0)))
3482 buffer_dereference(&bp
, MDL
);
3486 buffer_dereference(&bp
, MDL
);
3490 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3491 struct client_state
*client_state
,
3492 struct option_state
*in_options
,
3493 struct option_state
*cfg_options
,
3494 struct binding_scope
**scope
,
3495 struct universe
*u
, void *stuff
,
3496 void (*func
) (struct option_cache
*,
3498 struct lease
*, struct client_state
*,
3499 struct option_state
*,
3500 struct option_state
*,
3501 struct binding_scope
**,
3502 struct universe
*, void *))
3505 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
3506 cfg_options
, scope
, u
, stuff
, func
);
3509 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
3510 struct client_state
*client_state
,
3511 struct option_state
*in_options
,
3512 struct option_state
*cfg_options
,
3513 struct binding_scope
**scope
,
3514 struct universe
*u
, void *stuff
,
3515 void (*func
) (struct option_cache
*,
3517 struct lease
*, struct client_state
*,
3518 struct option_state
*,
3519 struct option_state
*,
3520 struct binding_scope
**,
3521 struct universe
*, void *),
3522 struct option_cache
*oc
,
3525 struct universe
*universe
= find_option_universe (oc
-> option
,
3527 if (universe
-> foreach
)
3528 (*universe
-> foreach
) (packet
, lease
, client_state
,
3529 in_options
, cfg_options
,
3530 scope
, universe
, stuff
, func
);
3533 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3534 struct client_state
*client_state
,
3535 struct option_state
*in_options
,
3536 struct option_state
*cfg_options
,
3537 struct binding_scope
**scope
,
3538 struct universe
*u
, void *stuff
,
3539 void (*func
) (struct option_cache
*,
3542 struct client_state
*,
3543 struct option_state
*,
3544 struct option_state
*,
3545 struct binding_scope
**,
3546 struct universe
*, void *))
3550 struct option_cache
*oc
;
3552 if (cfg_options
-> universe_count
<= u
-> index
)
3555 hash
= cfg_options
-> universes
[u
-> index
];
3558 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3560 /* XXX save _all_ options! XXX */
3561 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3562 oc
= (struct option_cache
*)p
-> car
;
3563 (*func
) (oc
, packet
, lease
, client_state
,
3564 in_options
, cfg_options
, scope
, u
, stuff
);
3570 save_linked_option(struct universe
*universe
, struct option_state
*options
,
3571 struct option_cache
*oc
, isc_boolean_t appendp
)
3574 struct option_chain_head
*head
;
3575 struct option_cache
**ocloc
;
3577 if (universe
-> index
>= options
-> universe_count
)
3579 head
= ((struct option_chain_head
*)
3580 options
-> universes
[universe
-> index
]);
3582 if (!option_chain_head_allocate (((struct option_chain_head
**)
3583 &options
-> universes
3584 [universe
-> index
]), MDL
))
3586 head
= ((struct option_chain_head
*)
3587 options
-> universes
[universe
-> index
]);
3590 /* Find the tail of the list. */
3591 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3592 ocloc
= (struct option_cache
**)&(*tail
)->car
;
3594 if (oc
->option
->code
== (*ocloc
)->option
->code
) {
3597 ocloc
= &(*ocloc
)->next
;
3598 } while (*ocloc
!= NULL
);
3600 option_cache_dereference(ocloc
, MDL
);
3602 option_cache_reference(ocloc
, oc
, MDL
);
3607 *tail
= cons (0, 0);
3609 option_cache_reference ((struct option_cache
**)
3610 (&(*tail
) -> car
), oc
, MDL
);
3614 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
3615 in_options
, cfg_options
, scope
, universe
)
3616 struct data_string
*result
;
3617 struct packet
*packet
;
3618 struct lease
*lease
;
3619 struct client_state
*client_state
;
3620 struct option_state
*in_options
;
3621 struct option_state
*cfg_options
;
3622 struct binding_scope
**scope
;
3623 struct universe
*universe
;
3627 struct option_chain_head
*head
;
3629 if (universe
-> index
>= cfg_options
-> universe_count
)
3631 head
= ((struct option_chain_head
*)
3632 cfg_options
-> universes
[universe
-> index
]);
3636 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3637 if (store_option (result
, universe
, packet
,
3638 lease
, client_state
, in_options
, cfg_options
,
3639 scope
, (struct option_cache
*)(oc
-> car
)))
3643 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3644 in_options
, cfg_options
, scope
, universe
))
3650 void delete_linked_option (universe
, options
, code
)
3651 struct universe
*universe
;
3652 struct option_state
*options
;
3655 pair
*tail
, tmp
= (pair
)0;
3656 struct option_chain_head
*head
;
3658 if (universe
-> index
>= options
-> universe_count
)
3660 head
= ((struct option_chain_head
*)
3661 options
-> universes
[universe
-> index
]);
3665 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3667 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
3669 tmp
= (*tail
) -> cdr
;
3670 option_cache_dereference ((struct option_cache
**)
3671 (&(*tail
) -> car
), MDL
);
3679 struct option_cache
*lookup_linked_option (universe
, options
, code
)
3680 struct universe
*universe
;
3681 struct option_state
*options
;
3685 struct option_chain_head
*head
;
3687 if (universe
-> index
>= options
-> universe_count
)
3689 head
= ((struct option_chain_head
*)
3690 options
-> universes
[universe
-> index
]);
3694 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3696 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
3697 return (struct option_cache
*)(oc
-> car
);
3701 return (struct option_cache
*)0;
3704 int linked_option_state_dereference (universe
, state
, file
, line
)
3705 struct universe
*universe
;
3706 struct option_state
*state
;
3710 return (option_chain_head_dereference
3711 ((struct option_chain_head
**)
3712 (&state
-> universes
[universe
-> index
]), MDL
));
3715 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3716 struct client_state
*client_state
,
3717 struct option_state
*in_options
,
3718 struct option_state
*cfg_options
,
3719 struct binding_scope
**scope
,
3720 struct universe
*u
, void *stuff
,
3721 void (*func
) (struct option_cache
*,
3724 struct client_state
*,
3725 struct option_state
*,
3726 struct option_state
*,
3727 struct binding_scope
**,
3728 struct universe
*, void *))
3731 struct option_chain_head
*head
;
3733 if (u
-> index
>= cfg_options
-> universe_count
)
3735 head
= ((struct option_chain_head
*)
3736 cfg_options
-> universes
[u
-> index
]);
3739 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
3740 (*func
) ((struct option_cache
*)(car
-> car
),
3741 packet
, lease
, client_state
,
3742 in_options
, cfg_options
, scope
, u
, stuff
);
3746 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
3747 struct interface_info
*interface
;
3748 struct dhcp_packet
*packet
;
3750 unsigned int from_port
;
3752 struct hardware
*hfrom
;
3754 struct option_cache
*op
;
3755 struct packet
*decoded_packet
;
3756 #if defined (DEBUG_MEMORY_LEAKAGE)
3757 unsigned long previous_outstanding
= dmalloc_outstanding
;
3760 #if defined (TRACING)
3761 trace_inpacket_stash(interface
, packet
, len
, from_port
, from
, hfrom
);
3764 decoded_packet
= NULL
;
3765 if (!packet_allocate(&decoded_packet
, MDL
)) {
3766 log_error("do_packet: no memory for incoming packet!");
3769 decoded_packet
->raw
= packet
;
3770 decoded_packet
->packet_length
= len
;
3771 decoded_packet
->client_port
= from_port
;
3772 decoded_packet
->client_addr
= from
;
3773 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
3774 decoded_packet
->haddr
= hfrom
;
3776 if (packet
->hlen
> sizeof packet
->chaddr
) {
3777 packet_dereference(&decoded_packet
, MDL
);
3778 log_info("Discarding packet with bogus hlen.");
3782 /* If there's an option buffer, try to parse it. */
3783 if (decoded_packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
3784 if (!parse_options(decoded_packet
)) {
3785 if (decoded_packet
->options
)
3786 option_state_dereference
3787 (&decoded_packet
->options
, MDL
);
3788 packet_dereference (&decoded_packet
, MDL
);
3792 if (decoded_packet
->options_valid
&&
3793 (op
= lookup_option(&dhcp_universe
,
3794 decoded_packet
->options
,
3795 DHO_DHCP_MESSAGE_TYPE
))) {
3796 struct data_string dp
;
3797 memset(&dp
, 0, sizeof dp
);
3798 evaluate_option_cache(&dp
, decoded_packet
, NULL
, NULL
,
3799 decoded_packet
->options
, NULL
,
3802 decoded_packet
->packet_type
= dp
.data
[0];
3804 decoded_packet
->packet_type
= 0;
3805 data_string_forget(&dp
, MDL
);
3809 if (validate_packet(decoded_packet
) != 0) {
3810 if (decoded_packet
->packet_type
)
3811 dhcp(decoded_packet
);
3813 bootp(decoded_packet
);
3816 /* If the caller kept the packet, they'll have upped the refcnt. */
3817 packet_dereference(&decoded_packet
, MDL
);
3819 #if defined (DEBUG_MEMORY_LEAKAGE)
3820 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
3822 dmalloc_outstanding
- previous_outstanding
,
3823 dmalloc_outstanding
, dmalloc_longterm
);
3824 dmalloc_dump_outstanding();
3826 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
3832 packet6_len_okay(const char *packet
, int len
) {
3836 if ((packet
[0] == DHCPV6_RELAY_FORW
) ||
3837 (packet
[0] == DHCPV6_RELAY_REPL
)) {
3838 if (len
>= offsetof(struct dhcpv6_relay_packet
, options
)) {
3844 if (len
>= offsetof(struct dhcpv6_packet
, options
)) {
3854 do_packet6(struct interface_info
*interface
, const char *packet
,
3855 int len
, int from_port
, const struct iaddr
*from
,
3856 isc_boolean_t was_unicast
) {
3857 unsigned char msg_type
;
3858 const struct dhcpv6_packet
*msg
;
3859 const struct dhcpv6_relay_packet
*relay
;
3860 struct packet
*decoded_packet
;
3861 #if defined (DEBUG_MEMORY_LEAKAGE)
3862 unsigned long previous_outstanding
= dmalloc_outstanding
;
3865 if (!packet6_len_okay(packet
, len
)) {
3866 log_info("do_packet6: "
3867 "short packet from %s port %d, len %d, dropped",
3868 piaddr(*from
), from_port
, len
);
3872 decoded_packet
= NULL
;
3873 if (!packet_allocate(&decoded_packet
, MDL
)) {
3874 log_error("do_packet6: no memory for incoming packet.");
3878 if (!option_state_allocate(&decoded_packet
->options
, MDL
)) {
3879 log_error("do_packet6: no memory for options.");
3880 packet_dereference(&decoded_packet
, MDL
);
3884 /* IPv4 information, already set to 0 */
3885 /* decoded_packet->packet_type = 0; */
3886 /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
3887 /* decoded_packet->circuit_id = NULL; */
3888 /* decoded_packet->circuit_id_len = 0; */
3889 /* decoded_packet->remote_id = NULL; */
3890 /* decoded_packet->remote_id_len = 0; */
3891 decoded_packet
->raw
= (struct dhcp_packet
*)packet
;
3892 decoded_packet
->packet_length
= (unsigned)len
;
3893 decoded_packet
->client_port
= from_port
;
3894 decoded_packet
->client_addr
= *from
;
3895 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
3897 decoded_packet
->unicast
= was_unicast
;
3899 msg_type
= packet
[0];
3900 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
3901 (msg_type
== DHCPV6_RELAY_REPL
)) {
3902 int relaylen
= (int)(offsetof(struct dhcpv6_relay_packet
, options
));
3903 relay
= (const struct dhcpv6_relay_packet
*)packet
;
3904 decoded_packet
->dhcpv6_msg_type
= relay
->msg_type
;
3906 /* relay-specific data */
3907 decoded_packet
->dhcpv6_hop_count
= relay
->hop_count
;
3908 memcpy(&decoded_packet
->dhcpv6_link_address
,
3909 relay
->link_address
, sizeof(relay
->link_address
));
3910 memcpy(&decoded_packet
->dhcpv6_peer_address
,
3911 relay
->peer_address
, sizeof(relay
->peer_address
));
3913 if (!parse_option_buffer(decoded_packet
->options
,
3914 relay
->options
, len
- relaylen
,
3915 &dhcpv6_universe
)) {
3916 /* no logging here, as parse_option_buffer() logs all
3917 cases where it fails */
3918 packet_dereference(&decoded_packet
, MDL
);
3922 int msglen
= (int)(offsetof(struct dhcpv6_packet
, options
));
3923 msg
= (const struct dhcpv6_packet
*)packet
;
3924 decoded_packet
->dhcpv6_msg_type
= msg
->msg_type
;
3926 /* message-specific data */
3927 memcpy(decoded_packet
->dhcpv6_transaction_id
,
3928 msg
->transaction_id
,
3929 sizeof(decoded_packet
->dhcpv6_transaction_id
));
3931 if (!parse_option_buffer(decoded_packet
->options
,
3932 msg
->options
, len
- msglen
,
3933 &dhcpv6_universe
)) {
3934 /* no logging here, as parse_option_buffer() logs all
3935 cases where it fails */
3936 packet_dereference(&decoded_packet
, MDL
);
3941 dhcpv6(decoded_packet
);
3943 packet_dereference(&decoded_packet
, MDL
);
3945 #if defined (DEBUG_MEMORY_LEAKAGE)
3946 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
3948 dmalloc_outstanding
- previous_outstanding
,
3949 dmalloc_outstanding
, dmalloc_longterm
);
3950 dmalloc_dump_outstanding();
3952 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
3959 pretty_escape(char **dst
, char *dend
, const unsigned char **src
,
3960 const unsigned char *send
)
3964 /* If there aren't as many bytes left as there are in the source
3965 * buffer, don't even bother entering the loop.
3967 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3968 *dst
== NULL
|| *src
== NULL
|| (*dst
>= dend
) || (*src
> send
) ||
3969 ((send
- *src
) > (dend
- *dst
)))
3972 for ( ; *src
< send
; (*src
)++) {
3973 if (!isascii (**src
) || !isprint (**src
)) {
3974 /* Skip trailing NUL. */
3975 if ((*src
+ 1) != send
|| **src
!= '\0') {
3976 if (*dst
+ 4 > dend
)
3979 sprintf(*dst
, "\\%03o",
3984 } else if (**src
== '"' || **src
== '\'' || **src
== '$' ||
3985 **src
== '`' || **src
== '\\' || **src
== '|' ||
3987 if (*dst
+ 2 > dend
)
3996 if (*dst
+ 1 > dend
)
4009 pretty_text(char **dst
, char *dend
, const unsigned char **src
,
4010 const unsigned char *send
, int emit_quotes
)
4014 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4015 *dst
== NULL
|| *src
== NULL
||
4016 ((*dst
+ (emit_quotes
? 2 : 0)) > dend
) || (*src
> send
))
4024 /* dend-1 leaves 1 byte for the closing quote. */
4025 count
= pretty_escape(dst
, dend
- (emit_quotes
? 1 : 0), src
, send
);
4030 if (emit_quotes
&& (*dst
< dend
)) {
4034 /* Includes quote prior to pretty_escape(); */
4042 pretty_domain(char **dst
, char *dend
, const unsigned char **src
,
4043 const unsigned char *send
)
4045 const unsigned char *tend
;
4049 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4050 *dst
== NULL
|| *src
== NULL
||
4051 ((*dst
+ 2) > dend
) || (*src
>= send
))
4058 /* Continue loop until end of src buffer. */
4062 /* Consume tag size. */
4066 /* At root, finis. */
4070 tend
= (*src
) + tsiz
;
4072 /* If the tag exceeds the source buffer, it's illegal.
4073 * This should also trap compression pointers (which should
4074 * not be in these buffers).
4079 /* dend-2 leaves room for a trailing dot and quote. */
4080 status
= pretty_escape(dst
, dend
-2, src
, tend
);
4082 if ((status
== -1) || ((*dst
+ 2) > dend
))
4087 count
+= status
+ 1;
4098 * Add the option identified with the option number and data to the
4102 add_option(struct option_state
*options
,
4103 unsigned int option_num
,
4105 unsigned int data_len
)
4107 struct option_cache
*oc
;
4108 struct option
*option
;
4110 /* INSIST(options != NULL); */
4111 /* INSIST(data != NULL); */
4114 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
4115 &option_num
, 0, MDL
)) {
4116 log_error("Attempting to add unknown option %d.", option_num
);
4121 if (!option_cache_allocate(&oc
, MDL
)) {
4122 log_error("No memory for option cache adding %s (option %d).",
4123 option
->name
, option_num
);
4127 if (!make_const_data(&oc
->expression
,
4133 log_error("No memory for constant data adding %s (option %d).",
4134 option
->name
, option_num
);
4135 option_cache_dereference(&oc
, MDL
);
4139 option_reference(&(oc
->option
), option
, MDL
);
4140 save_option(&dhcp_universe
, options
, oc
);
4141 option_cache_dereference(&oc
, MDL
);
4147 * Checks if received BOOTP/DHCPv4 packet is sane
4149 * @param packet received, decoded packet
4151 * @return 1 if packet is sane, 0 if it is not
4153 int validate_packet(struct packet
*packet
)
4155 struct option_cache
*oc
= NULL
;
4157 oc
= lookup_option (&dhcp_universe
, packet
->options
,
4158 DHO_DHCP_CLIENT_IDENTIFIER
);
4160 /* Let's check if client-identifier is sane */
4161 if (oc
->data
.len
== 0) {
4162 log_debug("Dropped DHCPv4 packet with zero-length client-id");
4165 } else if (oc
->data
.len
== 1) {
4167 * RFC2132, section 9.14 states that minimum length of client-id
4168 * is 2. We will allow single-character client-ids for now (for
4169 * backwards compatibility), but warn the user that support for
4170 * this is against the standard.
4172 log_debug("Accepted DHCPv4 packet with one-character client-id - "
4173 "a future version of ISC DHCP will reject this");
4177 * If hlen is 0 we don't have any identifier, we warn the user
4178 * but continue processing the packet as we can.
4180 if (packet
->raw
->hlen
== 0) {
4181 log_debug("Received DHCPv4 packet without client-id"
4182 " option and empty hlen field.");
4186 /* @todo: Add checks for other received options */