3 DHCP options parsing and reassembly. */
6 * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Newmarket, NH 03857 USA
25 * https://www.isc.org/
29 #define DHCP_OPTION_DATA
31 #include <omapip/omapip_p.h>
34 struct option
*vendor_cfg_option
;
36 static int pretty_text(char **, char *, const unsigned char **,
37 const unsigned char *, int);
38 static int pretty_dname(char **, char *, const unsigned char *,
39 const unsigned char *);
40 static int pretty_domain(char **, char *, const unsigned char **,
41 const unsigned char *);
42 static int prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
43 unsigned char *buffer
, unsigned length
,
44 unsigned code
, int terminatep
,
45 struct option_cache
**opp
);
47 /* Parse all available options out of the specified packet. */
48 /* Note, the caller is responsible for allocating packet->options. */
49 int parse_options (packet
)
50 struct packet
*packet
;
52 struct option_cache
*op
= NULL
;
54 /* If we don't see the magic cookie, there's nothing to parse. */
55 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
56 packet
-> options_valid
= 0;
60 /* Go through the options field, up to the end of the packet
62 if (!parse_option_buffer (packet
-> options
,
63 &packet
-> raw
-> options
[4],
64 (packet
-> packet_length
-
65 DHCP_FIXED_NON_UDP
- 4),
68 /* STSN servers have a bug where they send a mangled
69 domain-name option, and whatever is beyond that in
70 the packet is junk. Microsoft clients accept this,
71 which is probably why whoever implemented the STSN
72 server isn't aware of the problem yet. To work around
73 this, we will accept corrupt packets from the server if
74 they contain a valid DHCP_MESSAGE_TYPE option, but
75 will not accept any corrupt client packets (the ISC DHCP
76 server is sufficiently widely used that it is probably
77 beneficial for it to be picky) and will not accept
78 packets whose type can't be determined. */
80 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
81 DHO_DHCP_MESSAGE_TYPE
))) {
82 if (!op
-> data
.data
||
83 (op
-> data
.data
[0] != DHCPOFFER
&&
84 op
-> data
.data
[0] != DHCPACK
&&
85 op
-> data
.data
[0] != DHCPNAK
))
91 /* If we parsed a DHCP Option Overload option, parse more
92 options out of the buffer(s) containing them. */
93 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
94 DHO_DHCP_OPTION_OVERLOAD
))) {
95 if (op
-> data
.data
[0] & 1) {
96 if (!parse_option_buffer
98 (unsigned char *)packet
-> raw
-> file
,
99 sizeof packet
-> raw
-> file
,
103 if (op
-> data
.data
[0] & 2) {
104 if (!parse_option_buffer
106 (unsigned char *)packet
-> raw
-> sname
,
107 sizeof packet
-> raw
-> sname
,
112 packet
-> options_valid
= 1;
116 /* Parse options out of the specified buffer, storing addresses of option
117 * values in packet->options.
119 int parse_option_buffer (options
, buffer
, length
, universe
)
120 struct option_state
*options
;
121 const unsigned char *buffer
;
123 struct universe
*universe
;
125 unsigned len
, offset
;
127 struct option_cache
*op
= NULL
, *nop
= NULL
;
128 struct buffer
*bp
= (struct buffer
*)0;
129 struct option
*option
= NULL
;
130 char *reason
= "general failure";
132 if (!buffer_allocate (&bp
, length
, MDL
)) {
133 log_error ("no memory for option buffer.");
136 memcpy (bp
-> data
, buffer
, length
);
139 (offset
+ universe
->tag_size
) <= length
&&
140 (code
= universe
->get_tag(buffer
+ offset
)) != universe
->end
; ) {
141 offset
+= universe
->tag_size
;
143 /* Pad options don't have a length - just skip them. */
147 /* Don't look for length if the buffer isn't that big. */
148 if ((offset
+ universe
->length_size
) > length
) {
149 reason
= "code tag at end of buffer - missing "
154 /* All other fields (except PAD and END handled above)
155 * have a length field, unless it's a DHCPv6 zero-length
156 * options space (eg any of the enterprise-id'd options).
158 * Zero-length-size option spaces basically consume the
159 * entire options buffer, so have at it.
161 if (universe
->get_length
!= NULL
)
162 len
= universe
->get_length(buffer
+ offset
);
163 else if (universe
->length_size
== 0)
164 len
= length
- universe
->tag_size
;
166 log_fatal("Improperly configured option space(%s): "
167 "may not have a nonzero length size "
168 "AND a NULL get_length function.",
171 /* Silence compiler warnings. */
175 offset
+= universe
->length_size
;
177 option_code_hash_lookup(&option
, universe
->code_hash
, &code
,
180 /* If the length is outrageous, the options are bad. */
181 if (offset
+ len
> length
) {
182 /* Avoid reference count overflow */
183 option_dereference(&option
, MDL
);
184 reason
= "option length exceeds option buffer length";
186 log_error("parse_option_buffer: malformed option "
187 "%s.%s (code %u): %s.", universe
->name
,
188 option
? option
->name
: "<unknown>",
190 buffer_dereference (&bp
, MDL
);
194 /* If the option contains an encapsulation, parse it. In
195 any case keep the raw data as well. (Previous to 4.4.0
196 we only kept the raw data if the parse failed, the option
197 wasn't an encapsulation (by far the most common case), or
198 the option wasn't entirely an encapsulation
202 (option
->format
[0] == 'e' || option
->format
[0] == 'E')) {
203 (void) parse_encapsulated_suboptions(options
, option
,
209 if (universe
== &dhcp_universe
&& code
== DHO_HOST_NAME
&&
211 /* non-compliant clients can send it
212 * we'll just drop it and go on */
213 log_debug ("Ignoring empty DHO_HOST_NAME option");
214 option_dereference(&option
, MDL
);
219 op
= lookup_option(universe
, options
, code
);
221 /* If we don't have an option create one */
222 if (save_option_buffer(universe
, options
, bp
,
223 bp
->data
+ offset
, len
,
225 log_error("parse_option_buffer: "
226 "save_option_buffer failed");
227 buffer_dereference(&bp
, MDL
);
228 option_dereference(&option
, MDL
);
231 } else if (universe
->concat_duplicates
) {
232 /* If we do have an option either concat with
234 struct data_string
new;
235 memset(&new, 0, sizeof new);
236 if (!buffer_allocate(&new.buffer
, op
->data
.len
+ len
,
238 log_error("parse_option_buffer: No memory.");
239 buffer_dereference(&bp
, MDL
);
240 option_dereference(&option
, MDL
);
243 /* Copy old option to new data object. */
244 memcpy(new.buffer
->data
, op
->data
.data
,
246 /* Concat new option behind old. */
247 memcpy(new.buffer
->data
+ op
->data
.len
,
248 bp
->data
+ offset
, len
);
249 new.len
= op
->data
.len
+ len
;
250 new.data
= new.buffer
->data
;
251 /* Save new concat'd object. */
252 data_string_forget(&op
->data
, MDL
);
253 data_string_copy(&op
->data
, &new, MDL
);
254 data_string_forget(&new, MDL
);
256 /* ... or we must append this statement onto the
259 while (op
->next
!= NULL
)
262 if (!option_cache_allocate(&nop
, MDL
)) {
263 log_error("parse_option_buffer: No memory.");
264 buffer_dereference(&bp
, MDL
);
265 option_dereference(&option
, MDL
);
269 option_reference(&nop
->option
, op
->option
, MDL
);
271 nop
->data
.buffer
= NULL
;
272 buffer_reference(&nop
->data
.buffer
, bp
, MDL
);
273 nop
->data
.data
= bp
->data
+ offset
;
276 option_cache_reference(&op
->next
, nop
, MDL
);
277 option_cache_dereference(&nop
, MDL
);
280 option_dereference(&option
, MDL
);
283 buffer_dereference (&bp
, MDL
);
287 /* If an option in an option buffer turns out to be an encapsulation,
288 figure out what to do. If we don't know how to de-encapsulate it,
289 or it's not well-formed, return zero; otherwise, return 1, indicating
290 that we succeeded in de-encapsulating it. */
292 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
296 struct universe
*universe
= (struct universe
*)0;
298 /* Look for the E option in the option format. */
299 s
= strchr (eopt
-> format
, 'E');
301 log_error ("internal encapsulation format error 1.");
304 /* Look for the universe name in the option format. */
305 t
= strchr (++s
, '.');
306 /* If there was no trailing '.', or there's something after the
307 trailing '.', the option is bogus and we can't use it. */
309 log_error ("internal encapsulation format error 2.");
312 if (t
== s
&& uname
) {
313 for (i
= 0; i
< universe_count
; i
++) {
314 if (!strcmp (universes
[i
] -> name
, uname
)) {
315 universe
= universes
[i
];
320 for (i
= 0; i
< universe_count
; i
++) {
321 if (strlen (universes
[i
] -> name
) == t
- s
&&
322 !memcmp (universes
[i
] -> name
,
323 s
, (unsigned)(t
- s
))) {
324 universe
= universes
[i
];
332 /* If an option in an option buffer turns out to be an encapsulation,
333 figure out what to do. If we don't know how to de-encapsulate it,
334 or it's not well-formed, return zero; otherwise, return 1, indicating
335 that we succeeded in de-encapsulating it. */
337 int parse_encapsulated_suboptions (struct option_state
*options
,
339 const unsigned char *buffer
,
340 unsigned len
, struct universe
*eu
,
344 struct universe
*universe
= find_option_universe (eopt
, uname
);
346 /* If we didn't find the universe, we can't do anything with it
347 right now (e.g., we can't decode vendor options until we've
348 decoded the packet and executed the scopes that it matches). */
352 /* If we don't have a decoding function for it, we can't decode
354 if (!universe
-> decode
)
357 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
359 /* If there is stuff before the suboptions, we have to keep it. */
360 if (eopt
-> format
[0] != 'E')
362 /* Otherwise, return the status of the decode function. */
366 int fqdn_universe_decode (struct option_state
*options
,
367 const unsigned char *buffer
,
368 unsigned length
, struct universe
*u
)
370 struct buffer
*bp
= (struct buffer
*)0;
372 /* FQDN options have to be at least four bytes long. */
376 /* Save the contents of the option in a buffer. */
377 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
378 log_error ("no memory for option buffer.");
381 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
383 if (buffer
[0] & 4) /* encoded */
387 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
388 bp
->data
, 1, FQDN_ENCODED
, 0)) {
390 buffer_dereference (&bp
, MDL
);
394 if (buffer
[0] & 1) /* server-update */
398 if (buffer
[0] & 2) /* no-client-update */
403 /* XXX Ideally we should store the name in DNS format, so if the
404 XXX label isn't in DNS format, we convert it to DNS format,
405 XXX rather than converting labels specified in DNS format to
406 XXX the plain ASCII representation. But that's hard, so
409 /* Not encoded using DNS format? */
410 if (!bp
-> data
[0]) {
413 /* Some broken clients NUL-terminate this option. */
414 if (buffer
[length
- 1] == 0) {
419 /* Determine the length of the hostname component of the
420 name. If the name contains no '.' character, it
421 represents a non-qualified label. */
422 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
425 /* Note: If the client sends a FQDN, the first '.' will
426 be used as a NUL terminator for the hostname. */
427 if (i
&& (!save_option_buffer(&fqdn_universe
, options
, bp
,
431 /* Note: If the client sends a single label, the
432 FQDN_DOMAINNAME option won't be set. */
433 if (length
> 4 + i
&&
434 (!save_option_buffer(&fqdn_universe
, options
, bp
,
435 &bp
-> data
[6 + i
], length
- 4 - i
,
436 FQDN_DOMAINNAME
, 1)))
438 /* Also save the whole name. */
440 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
441 &bp
-> data
[5], length
- 3,
447 unsigned total_len
= 0;
448 unsigned first_len
= 0;
454 while (s
< &bp
-> data
[0] + length
+ 2) {
457 log_info ("fancy bits in fqdn option");
464 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
465 log_info ("fqdn tag longer than buffer");
469 if (first_len
== 0) {
475 total_len
+= len
+ 1;
478 /* We wind up with a length that's one too many because
479 we shouldn't increment for the last label, but there's
480 no way to tell we're at the last label until we exit
486 first_len
= total_len
;
490 !save_option_buffer(&fqdn_universe
, options
, bp
,
491 &bp
-> data
[6], first_len
,
494 if (total_len
> 0 && first_len
!= total_len
) {
495 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
496 &bp
->data
[6 + first_len
],
497 total_len
- first_len
,
502 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
503 &bp
-> data
[6], total_len
,
508 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
510 FQDN_NO_CLIENT_UPDATE
, 0))
512 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
514 FQDN_SERVER_UPDATE
, 0))
517 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
521 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
526 buffer_dereference (&bp
, MDL
);
531 * Load all options into a buffer, and then split them out into the three
532 * separate fields in the dhcp packet (options, file, and sname) where
533 * options can be stored.
535 * returns 0 on error, length of packet on success
538 cons_options(struct packet
*inpacket
, struct dhcp_packet
*outpacket
,
539 struct lease
*lease
, struct client_state
*client_state
,
540 int mms
, struct option_state
*in_options
,
541 struct option_state
*cfg_options
,
542 struct binding_scope
**scope
,
543 int overload_avail
, int terminate
, int bootpp
,
544 struct data_string
*prl
, const char *vuname
)
546 #define PRIORITY_COUNT 300
547 unsigned priority_list
[PRIORITY_COUNT
];
549 unsigned char buffer
[4096], agentopts
[1024];
551 unsigned mb_size
= 0, mb_max
= 0;
552 unsigned option_size
= 0, agent_size
= 0;
555 struct option_cache
*op
;
556 struct data_string ds
;
558 int overload_used
= 0;
559 int of1
= 0, of2
= 0;
561 memset(&ds
, 0, sizeof ds
);
564 * If there's a Maximum Message Size option in the incoming packet
565 * and no alternate maximum message size has been specified, or
566 * if the one specified in the packet is shorter than the
567 * alternative, take the one in the packet.
571 (op
= lookup_option(&dhcp_universe
, inpacket
->options
,
572 DHO_DHCP_MAX_MESSAGE_SIZE
)) &&
573 (evaluate_option_cache(&ds
, inpacket
, lease
,
574 client_state
, in_options
,
575 cfg_options
, scope
, op
, MDL
) != 0)) {
576 if (ds
.len
>= sizeof (u_int16_t
)) {
577 i
= getUShort(ds
.data
);
578 if(!mms
|| (i
< mms
))
581 data_string_forget(&ds
, MDL
);
585 * If the client has provided a maximum DHCP message size,
586 * use that, up to the MTU limit. Otherwise, if it's BOOTP,
587 * only 64 bytes; otherwise use up to the minimum IP MTU size
590 * XXX if a BOOTP client specifies a max message size, we will
594 if (mms
< DHCP_MTU_MIN
)
595 /* Enforce minimum packet size, per RFC 2132 */
596 mb_size
= DHCP_MIN_OPTION_LEN
;
597 else if (mms
> DHCP_MTU_MAX
)
599 * TODO: Packets longer than 1500 bytes really
600 * should be allowed, but it requires upstream
601 * changes to the way the packet is allocated. For
602 * now, we forbid them. They won't be needed very
605 mb_size
= DHCP_MAX_OPTION_LEN
;
607 mb_size
= mms
- DHCP_FIXED_LEN
;
610 if (inpacket
!= NULL
&&
611 (inpacket
->packet_length
>= 64 + DHCP_FIXED_NON_UDP
))
612 mb_size
= inpacket
->packet_length
- DHCP_FIXED_NON_UDP
;
614 mb_size
= DHCP_MIN_OPTION_LEN
;
617 * If answering a client message, see whether any relay agent
618 * options were included with the message. If so, save them
619 * to copy back in later, and make space in the main buffer
620 * to accommodate them
622 if (client_state
== NULL
) {
623 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
625 agent_size
= store_options(NULL
, agentopts
, 0,
627 inpacket
, lease
, client_state
,
628 in_options
, cfg_options
, scope
,
629 priority_list
, priority_len
,
632 mb_size
+= agent_size
;
633 if (mb_size
> DHCP_MAX_OPTION_LEN
)
634 mb_size
= DHCP_MAX_OPTION_LEN
;
638 * Set offsets for buffer data to be copied into filename
639 * and servername fields
641 if (mb_size
> agent_size
)
642 mb_max
= mb_size
- agent_size
;
646 if (overload_avail
& 1) {
648 mb_max
+= DHCP_FILE_LEN
;
651 if (overload_avail
& 2) {
653 mb_max
+= DHCP_SNAME_LEN
;
657 * Preload the option priority list with protocol-mandatory options.
658 * This effectively gives these options the highest priority.
659 * This provides the order for any available options, the option
660 * must be in the option cache in order to actually be included.
663 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
664 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
665 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
666 priority_list
[priority_len
++] = DHO_DHCP_RENEWAL_TIME
;
667 priority_list
[priority_len
++] = DHO_DHCP_REBINDING_TIME
;
668 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
669 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
670 priority_list
[priority_len
++] = DHO_ASSOCIATED_IP
;
672 if (prl
!= NULL
&& prl
->len
> 0) {
673 if ((op
= lookup_option(&dhcp_universe
, cfg_options
,
674 DHO_SUBNET_SELECTION
))) {
675 if (priority_len
< PRIORITY_COUNT
)
676 priority_list
[priority_len
++] =
677 DHO_SUBNET_SELECTION
;
680 /* If echo-client-id is on, then we add client identifier to
681 * the priority_list. This way we'll send it whether or not it
683 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
684 (inpacket
->sv_echo_client_id
== ISC_TRUE
)) {
685 priority_list
[priority_len
++] =
686 DHO_DHCP_CLIENT_IDENTIFIER
;
689 data_string_truncate(prl
, (PRIORITY_COUNT
- priority_len
));
692 * Copy the client's PRL onto the priority_list after our high
695 for (i
= 0; i
< prl
->len
; i
++) {
697 * Prevent client from changing order of delivery
698 * of relay agent information option.
700 if (prl
->data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
701 priority_list
[priority_len
++] = prl
->data
[i
];
705 * If the client doesn't request the FQDN option explicitly,
706 * to indicate priority, consider it lowest priority. Fit
707 * in the packet if there is space. Note that the option
708 * may only be included if the client supplied one.
710 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
711 (lookup_option(&fqdn_universe
, inpacket
->options
,
712 FQDN_ENCODED
) != NULL
))
713 priority_list
[priority_len
++] = DHO_FQDN
;
716 * Some DHCP Servers will give the subnet-mask option if
717 * it is not on the parameter request list - so some client
718 * implementations have come to rely on this - so we will
719 * also make sure we supply this, at lowest priority.
721 * This is only done in response to DHCPDISCOVER or
722 * DHCPREQUEST messages, to avoid providing the option on
723 * DHCPINFORM or DHCPLEASEQUERY responses (if the client
724 * didn't request it).
726 if ((inpacket
!= NULL
) && (priority_len
< PRIORITY_COUNT
) &&
727 ((inpacket
->packet_type
== DHCPDISCOVER
) ||
728 (inpacket
->packet_type
== DHCPREQUEST
)))
729 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
732 * First, hardcode some more options that ought to be
733 * sent first...these are high priority to have in the
736 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
737 priority_list
[priority_len
++] = DHO_ROUTERS
;
738 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
739 priority_list
[priority_len
++] = DHO_HOST_NAME
;
740 priority_list
[priority_len
++] = DHO_FQDN
;
743 * Append a list of the standard DHCP options from the
744 * standard DHCP option space. Actually, if a site
745 * option space hasn't been specified, we wind up
746 * treating the dhcp option space as the site option
747 * space, and the first for loop is skipped, because
748 * it's slightly more general to do it this way,
749 * taking the 1Q99 DHCP futures work into account.
751 if (cfg_options
->site_code_min
) {
752 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
753 hash
= cfg_options
->universes
[dhcp_universe
.index
];
755 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
756 op
= (struct option_cache
*)(pp
->car
);
757 if (op
->option
->code
<
758 cfg_options
->site_code_min
&&
759 priority_len
< PRIORITY_COUNT
&&
760 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
761 priority_list
[priority_len
++] =
769 * Now cycle through the site option space, or if there
770 * is no site option space, we'll be cycling through the
773 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
774 hash
= cfg_options
->universes
[cfg_options
->site_universe
];
776 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
777 op
= (struct option_cache
*)(pp
->car
);
778 if (op
->option
->code
>=
779 cfg_options
->site_code_min
&&
780 priority_len
< PRIORITY_COUNT
&&
781 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
782 priority_list
[priority_len
++] =
788 * Put any spaces that are encapsulated on the list,
789 * sort out whether they contain values later.
791 for (i
= 0; i
< cfg_options
->universe_count
; i
++) {
792 if (universes
[i
]->enc_opt
&&
793 priority_len
< PRIORITY_COUNT
&&
794 universes
[i
]->enc_opt
->universe
== &dhcp_universe
) {
795 if (universes
[i
]->enc_opt
->code
!=
796 DHO_DHCP_AGENT_OPTIONS
)
797 priority_list
[priority_len
++] =
798 universes
[i
]->enc_opt
->code
;
803 * The vendor option space can't stand on its own, so always
804 * add it to the list.
806 if (priority_len
< PRIORITY_COUNT
)
807 priority_list
[priority_len
++] =
808 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
811 /* Put the cookie up front... */
812 memcpy(buffer
, DHCP_OPTIONS_COOKIE
, 4);
815 /* Copy the options into the big buffer... */
816 option_size
= store_options(&overload_used
, buffer
, index
, mb_max
,
817 inpacket
, lease
, client_state
,
818 in_options
, cfg_options
, scope
,
819 priority_list
, priority_len
,
820 of1
, of2
, terminate
, vuname
);
822 /* If store_options() failed */
823 if (option_size
== 0)
826 /* How much was stored in the main buffer? */
827 index
+= option_size
;
830 * If we're going to have to overload, store the overload
834 if (mb_size
- agent_size
- index
< 3)
837 buffer
[index
++] = DHO_DHCP_OPTION_OVERLOAD
;
839 buffer
[index
++] = overload_used
;
841 if (overload_used
& 1)
842 memcpy(outpacket
->file
, &buffer
[of1
], DHCP_FILE_LEN
);
844 if (overload_used
& 2)
845 memcpy(outpacket
->sname
, &buffer
[of2
], DHCP_SNAME_LEN
);
848 /* Now copy in preserved agent options, if any */
850 if (mb_size
- index
>= agent_size
) {
851 memcpy(&buffer
[index
], agentopts
, agent_size
);
854 log_error("Unable to store relay agent information "
858 /* Tack a DHO_END option onto the packet if we need to. */
860 buffer
[index
++] = DHO_END
;
862 /* Copy main buffer into the options buffer of the packet */
863 memcpy(outpacket
->options
, buffer
, index
);
865 /* Figure out the length. */
866 length
= DHCP_FIXED_NON_UDP
+ index
;
871 * XXX: We currently special case collecting VSIO options.
872 * We should be able to handle this in a more generic fashion, by
873 * including any encapsulated options that are present and desired.
874 * This will look something like the VSIO handling VSIO code.
875 * We may also consider handling the ORO-like options within
876 * encapsulated spaces.
886 vsio_options(struct option_cache
*oc
,
887 struct packet
*packet
,
888 struct lease
*dummy_lease
,
889 struct client_state
*dummy_client_state
,
890 struct option_state
*dummy_opt_state
,
891 struct option_state
*opt_state
,
892 struct binding_scope
**dummy_binding_scope
,
893 struct universe
*universe
,
894 void *void_vsio_state
) {
895 struct vsio_state
*vs
= (struct vsio_state
*)void_vsio_state
;
896 struct data_string ds
;
899 memset(&ds
, 0, sizeof(ds
));
900 if (evaluate_option_cache(&ds
, packet
, NULL
,
901 NULL
, opt_state
, NULL
,
902 &global_scope
, oc
, MDL
)) {
903 total_len
= ds
.len
+ universe
->tag_size
+ universe
->length_size
;
904 if (total_len
<= (vs
->buflen
- vs
->bufpos
)) {
905 if (universe
->tag_size
== 1) {
906 vs
->buf
[vs
->bufpos
++] = oc
->option
->code
;
907 } else if (universe
->tag_size
== 2) {
908 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
911 } else if (universe
->tag_size
== 4) {
912 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
916 if (universe
->length_size
== 1) {
917 vs
->buf
[vs
->bufpos
++] = ds
.len
;
918 } else if (universe
->length_size
== 2) {
919 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
922 } else if (universe
->length_size
== 4) {
923 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
927 memcpy(vs
->buf
+ vs
->bufpos
, ds
.data
, ds
.len
);
928 vs
->bufpos
+= ds
.len
;
930 log_debug("No space for option %d in VSIO space %s.",
931 oc
->option
->code
, universe
->name
);
933 data_string_forget(&ds
, MDL
);
935 log_error("Error evaluating option %d in VSIO space %s.",
936 oc
->option
->code
, universe
->name
);
942 * \brief Add a v6 option to the buffer
944 * Put the requested v6 option including tag, length and value
945 * into the specified buffer. If there isn't enough space for
946 * the entire option it is skipped.
948 * \param buf buffer to put the option
949 * \param buflen total length of buffer
950 * \param bufpos on input where to start putting the option
951 * on output the starting point for the next option
952 * \param code the option code number
953 * \param ds the string to put into the option
958 add_option6_data(char *buf
, int buflen
, int* bufpos
, uint16_t code
,
959 struct data_string
* ds
) {
960 if ((ds
->len
+ 4) > (buflen
- *bufpos
)) {
961 log_debug("No space for option %d", code
);
963 unsigned char* tmp
= (unsigned char *)buf
+ *bufpos
;
965 putUShort(tmp
, code
);
967 putUShort(tmp
+2, ds
->len
);
969 memcpy(tmp
+4, ds
->data
, ds
->len
);
970 /* update position */
971 *bufpos
+= 4 + ds
->len
;
977 * \brief Add a v6 encapsulated option to a buffer
979 * Find the universe for the requested option and if it exists
980 * call it's encapsualtion routine to produce a data string which
981 * can then be added to the current buffer.
983 * Note 1: currently we only do simple encapsulations, where the
984 * entire value of the option is in the option universe. This is
985 * the 'E' format, we don't handle the 'e' format as we haven't
986 * defined any such universes yet. This means that if there is
987 * a simple value for the option store_options6 should handle it
988 * directly and not call this routine.
990 * \param buf buffer to put the option
991 * \param buflen total length of buffer
992 * \param bufpos on input where to start putting the option
993 * on output the starting point for the next option
994 * \param opt_state information about option values to use
995 * \param packet structure containing what we know about the packet
996 * \param encap_opt information about the structure of the option
997 * \param code the option code number
1002 store_encap6 (char *buf
, int buflen
, int* bufpos
,
1003 struct option_state
*opt_state
, struct packet
*packet
,
1004 struct option
* encap_opt
, uint16_t code
) {
1005 /* We need to extract the name of the universe
1006 * to use for this option. We expect a format string
1007 * of the form "Ename.". If we don't find a name we bail. */
1008 struct data_string ds
;
1009 struct data_string name
;
1010 char* s
= (char*)encap_opt
->format
;
1012 if ((s
== NULL
) || (*s
!= 'E') || (strlen(s
) <= 2)) {
1016 t
= strchr(++s
, '.');
1017 if ((t
== NULL
) || (t
== s
)) {
1021 memset(&ds
, 0, sizeof(ds
));
1022 memset(&name
, 0, sizeof(name
));
1023 name
.data
= (unsigned char *)s
;
1026 /* Now we call the routine to find and encapsulate the requested
1027 * option/universe. A return of 0 means no option information was
1028 * available and nothing is added to the buffer */
1029 if (option_space_encapsulate(&ds
, packet
, NULL
, NULL
, NULL
, opt_state
,
1030 &global_scope
, &name
) != 0) {
1031 add_option6_data(buf
, buflen
, bufpos
, code
, &ds
);
1032 data_string_forget(&ds
, MDL
);
1037 * Stores the options from the DHCPv6 universe into the buffer given.
1039 * Required options are given as a 0-terminated list of option codes.
1040 * Once those are added, the ORO is consulted.
1044 store_options6(char *buf
, int buflen
,
1045 struct option_state
*opt_state
,
1046 struct packet
*packet
,
1047 const int *required_opts
,
1048 struct data_string
*oro
) {
1050 struct option_cache
*oc
;
1052 struct data_string ds
;
1056 int in_required_opts
;
1057 int vsio_option_code
;
1059 struct vsio_state vs
;
1066 * Find the option code for the VSIO universe.
1068 vsio_option_code
= 0;
1069 o
= vsio_universe
.enc_opt
;
1071 if (o
->universe
== &dhcpv6_universe
) {
1072 vsio_option_code
= o
->code
;
1075 o
= o
->universe
->enc_opt
;
1077 if (vsio_option_code
== 0) {
1078 log_fatal("No VSIO option code found.");
1081 if (required_opts
!= NULL
) {
1082 for (i
=0; required_opts
[i
] != 0; i
++) {
1083 if (required_opts
[i
] == vsio_option_code
) {
1087 oc
= lookup_option(&dhcpv6_universe
,
1088 opt_state
, required_opts
[i
]);
1092 memset(&ds
, 0, sizeof(ds
));
1093 for (; oc
!= NULL
; oc
= oc
->next
) {
1094 if (evaluate_option_cache(&ds
, packet
, NULL
,
1096 NULL
, &global_scope
,
1098 add_option6_data(buf
, buflen
, &bufpos
,
1099 (uint16_t)required_opts
[i
], &ds
);
1100 data_string_forget(&ds
, MDL
);
1102 log_error("Error evaluating option %d",
1112 oro_size
= oro
->len
/ 2;
1114 for (i
=0; i
<oro_size
; i
++) {
1115 memcpy(&code
, oro
->data
+(i
*2), 2);
1119 * See if we've already included this option because
1122 in_required_opts
= 0;
1123 if (required_opts
!= NULL
) {
1124 for (j
=0; required_opts
[j
] != 0; j
++) {
1125 if (required_opts
[j
] == code
) {
1126 in_required_opts
= 1;
1131 if (in_required_opts
) {
1136 * If this is the VSIO option flag it so we'll know to
1137 * check the vsio space later on. However we still need
1138 * to check for the existence of any defined via
1139 * dhcp6.vendor-opts. Those are stored as simple values.
1141 if (code
== vsio_option_code
) {
1146 * Not already added, find this option.
1148 oc
= lookup_option(&dhcpv6_universe
, opt_state
, code
);
1149 memset(&ds
, 0, sizeof(ds
));
1151 /* We have a simple value for the option */
1152 for (; oc
!= NULL
; oc
= oc
->next
) {
1153 if (evaluate_option_cache(&ds
, packet
, NULL
,
1154 NULL
, opt_state
, NULL
,
1157 add_option6_data(buf
, buflen
, &bufpos
,
1159 data_string_forget(&ds
, MDL
);
1161 log_error("Error evaluating option %d",
1167 * We don't have a simple value, check to see if we
1168 * have an universe to encapsulate into an option.
1170 struct option
*encap_opt
= NULL
;
1171 unsigned int code_int
= code
;
1173 option_code_hash_lookup(&encap_opt
,
1174 dhcpv6_universe
.code_hash
,
1176 if (encap_opt
!= NULL
) {
1177 store_encap6(buf
, buflen
, &bufpos
, opt_state
,
1178 packet
, encap_opt
, code
);
1179 option_dereference(&encap_opt
, MDL
);
1185 for (i
=0; i
< opt_state
->universe_count
; i
++) {
1186 if (opt_state
->universes
[i
] != NULL
) {
1187 o
= universes
[i
]->enc_opt
;
1189 (o
->universe
== &vsio_universe
)) {
1191 * Add the data from this VSIO option.
1195 vs
.bufpos
= bufpos
+8;
1196 option_space_foreach(packet
, NULL
,
1205 * If there was actually data here,
1208 if (vs
.bufpos
> bufpos
+8) {
1209 tmp
= (unsigned char *)buf
+
1214 vs
.bufpos
-bufpos
-4);
1215 putULong(tmp
+4, o
->code
);
1228 * Store all the requested options into the requested buffer.
1229 * XXX: ought to be static
1232 store_options(int *ocount
,
1233 unsigned char *buffer
, unsigned index
, unsigned buflen
,
1234 struct packet
*packet
, struct lease
*lease
,
1235 struct client_state
*client_state
,
1236 struct option_state
*in_options
,
1237 struct option_state
*cfg_options
,
1238 struct binding_scope
**scope
,
1239 unsigned *priority_list
, int priority_len
,
1240 unsigned first_cutoff
, int second_cutoff
, int terminate
,
1243 int bufix
= 0, six
= 0, tix
= 0;
1247 int bufend
, sbufend
;
1248 struct data_string od
;
1249 struct option_cache
*oc
;
1250 struct option
*option
= NULL
;
1254 * These arguments are relative to the start of the buffer, so
1255 * reduce them by the current buffer index, and advance the
1256 * buffer pointer to where we're going to start writing.
1258 buffer
= &buffer
[index
];
1261 first_cutoff
-= index
;
1263 second_cutoff
-= index
;
1265 /* Calculate the start and end of each section of the buffer */
1266 bufend
= sbufend
= buflen
;
1268 if (first_cutoff
>= buflen
)
1269 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
1270 bufend
= first_cutoff
;
1272 if (second_cutoff
) {
1273 if (second_cutoff
>= buflen
)
1274 log_fatal("%s:%d:store_options: Invalid second cutoff.",
1276 sbufend
= second_cutoff
;
1278 } else if (second_cutoff
) {
1279 if (second_cutoff
>= buflen
)
1280 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
1281 bufend
= second_cutoff
;
1284 memset (&od
, 0, sizeof od
);
1286 /* Eliminate duplicate options from the parameter request list.
1287 * Enforce RFC-mandated ordering of options that are present.
1289 for (i
= 0; i
< priority_len
; i
++) {
1290 /* Eliminate duplicates. */
1292 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
1294 priority_list
[ix
- tto
] =
1296 if (priority_list
[i
] == priority_list
[ix
]) {
1302 /* Enforce ordering of SUBNET_MASK options, according to
1303 * RFC2132 Section 3.3:
1305 * If both the subnet mask and the router option are
1306 * specified in a DHCP reply, the subnet mask option MUST
1309 * This guidance does not specify what to do if the client
1310 * PRL explicitly requests the options out of order, it is
1311 * a general statement.
1313 if (priority_list
[i
] == DHO_SUBNET_MASK
) {
1314 for (ix
= i
- 1 ; ix
>= 0 ; ix
--) {
1315 if (priority_list
[ix
] == DHO_ROUTERS
) {
1317 priority_list
[ix
] = DHO_SUBNET_MASK
;
1318 priority_list
[i
] = DHO_ROUTERS
;
1325 /* Copy out the options in the order that they appear in the
1327 for (i
= 0; i
< priority_len
; i
++) {
1328 /* Number of bytes left to store (some may already
1329 have been stored by a previous pass). */
1331 int optstart
, soptstart
, toptstart
;
1333 int have_encapsulation
= 0;
1334 struct data_string encapsulation
;
1337 memset (&encapsulation
, 0, sizeof encapsulation
);
1338 have_encapsulation
= 0;
1341 option_dereference(&option
, MDL
);
1343 /* Code for next option to try to store. */
1344 code
= priority_list
[i
];
1346 /* Look up the option in the site option space if the code
1347 is above the cutoff, otherwise in the DHCP option space. */
1348 if (code
>= cfg_options
-> site_code_min
)
1349 u
= universes
[cfg_options
-> site_universe
];
1353 oc
= lookup_option (u
, cfg_options
, code
);
1355 if (oc
&& oc
->option
)
1356 option_reference(&option
, oc
->option
, MDL
);
1358 option_code_hash_lookup(&option
, u
->code_hash
, &code
, 0, MDL
);
1360 /* If it's a straight encapsulation, and the user supplied a
1361 * value for the entire option, use that. Otherwise, search
1362 * the encapsulated space.
1364 * If it's a limited encapsulation with preceding data, and the
1365 * user supplied values for the preceding bytes, search the
1366 * encapsulated space.
1368 if ((option
!= NULL
) &&
1369 (((oc
== NULL
) && (option
->format
[0] == 'E')) ||
1370 ((oc
!= NULL
) && (option
->format
[0] == 'e')))) {
1372 struct option_cache
*tmp
;
1373 struct data_string name
;
1375 s
= strchr (option
->format
, 'E');
1377 t
= strchr (++s
, '.');
1379 memset (&name
, 0, sizeof name
);
1381 /* A zero-length universe name means the vendor
1382 option space, if one is defined. */
1384 if (vendor_cfg_option
) {
1385 tmp
= lookup_option (vendor_cfg_option
-> universe
,
1387 vendor_cfg_option
-> code
);
1389 /* No need to check the return as we check name.len below */
1390 (void) evaluate_option_cache (&name
, packet
, lease
,
1395 } else if (vuname
) {
1396 name
.data
= (unsigned char *)s
;
1397 name
.len
= strlen (s
);
1400 name
.data
= (unsigned char *)s
;
1404 /* If we found a universe, and there are options configured
1405 for that universe, try to encapsulate it. */
1407 have_encapsulation
=
1408 (option_space_encapsulate
1409 (&encapsulation
, packet
, lease
, client_state
,
1410 in_options
, cfg_options
, scope
, &name
));
1413 data_string_forget (&name
, MDL
);
1417 /* In order to avoid memory leaks, we have to get to here
1418 with any option cache that we allocated in tmp not being
1419 referenced by tmp, and whatever option cache is referenced
1420 by oc being an actual reference. lookup_option doesn't
1421 generate a reference (this needs to be fixed), so the
1422 preceding goop ensures that if we *didn't* generate a new
1423 option cache, oc still winds up holding an actual reference. */
1425 /* If no data is available for this option, skip it. */
1426 if (!oc
&& !have_encapsulation
) {
1430 /* Find the value of the option... */
1433 /* No need to check the return as we check od.len below */
1434 (void) evaluate_option_cache (&od
, packet
,
1435 lease
, client_state
, in_options
,
1436 cfg_options
, scope
, oc
, MDL
);
1438 /* If we have encapsulation for this option, and an oc
1439 * lookup succeeded, but the evaluation failed, it is
1440 * either because this is a complex atom (atoms before
1441 * E on format list) and the top half of the option is
1442 * not configured, or this is a simple encapsulated
1443 * space and the evaluator is giving us a NULL. Prefer
1444 * the evaluator's opinion over the subspace.
1447 data_string_forget (&encapsulation
, MDL
);
1448 data_string_forget (&od
, MDL
);
1453 /* We should now have a constant length for the option. */
1455 if (have_encapsulation
) {
1456 length
+= encapsulation
.len
;
1458 /* od.len can be nonzero if we got here without an
1459 * oc (cache lookup failed), but did have an encapsulated
1460 * simple encapsulation space.
1463 data_string_copy (&od
, &encapsulation
, MDL
);
1464 data_string_forget (&encapsulation
, MDL
);
1466 struct buffer
*bp
= (struct buffer
*)0;
1467 if (!buffer_allocate (&bp
, length
, MDL
)) {
1468 option_cache_dereference (&oc
, MDL
);
1469 data_string_forget (&od
, MDL
);
1470 data_string_forget (&encapsulation
, MDL
);
1473 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
1474 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
1476 data_string_forget (&od
, MDL
);
1477 data_string_forget (&encapsulation
, MDL
);
1478 od
.data
= &bp
-> data
[0];
1479 buffer_reference (&od
.buffer
, bp
, MDL
);
1480 buffer_dereference (&bp
, MDL
);
1486 /* Do we add a NUL? */
1487 if (terminate
&& option
&& format_has_text(option
->format
)) {
1494 /* Try to store the option. */
1496 /* If the option's length is more than 255, we must store it
1497 in multiple hunks. Store 255-byte hunks first. However,
1498 in any case, if the option data will cross a buffer
1499 boundary, split it across that boundary. */
1511 unsigned incr
= length
;
1513 unsigned char *base
;
1515 /* Try to fit it in the options buffer. */
1517 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
1518 (bufix
+ 2 + length
< bufend
)) ||
1519 (bufix
+ 5 + length
< bufend
))) {
1522 /* Try to fit it in the second buffer. */
1523 } else if (!splitup
&& first_cutoff
&&
1524 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
1525 base
= &buffer
[first_cutoff
];
1527 /* Try to fit it in the third buffer. */
1528 } else if (!splitup
&& second_cutoff
&&
1529 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
1530 base
= &buffer
[second_cutoff
];
1532 /* Split the option up into the remaining space. */
1536 /* Use any remaining options space. */
1537 if (bufix
+ 6 < bufend
) {
1538 incr
= bufend
- bufix
- 5;
1541 /* Use any remaining first_cutoff space. */
1542 } else if (first_cutoff
&&
1543 (first_cutoff
+ six
+ 4 < sbufend
)) {
1544 incr
= sbufend
- (first_cutoff
+ six
) - 3;
1545 base
= &buffer
[first_cutoff
];
1547 /* Use any remaining second_cutoff space. */
1548 } else if (second_cutoff
&&
1549 (second_cutoff
+ tix
+ 4 < buflen
)) {
1550 incr
= buflen
- (second_cutoff
+ tix
) - 3;
1551 base
= &buffer
[second_cutoff
];
1553 /* Give up, roll back this option. */
1567 /* Everything looks good - copy it in! */
1569 base
[*pix
+ 1] = (unsigned char)incr
;
1570 if (tto
&& incr
== length
) {
1572 memcpy (base
+ *pix
+ 2,
1573 od
.data
+ ix
, (unsigned)(incr
- 1));
1574 base
[*pix
+ 2 + incr
- 1] = 0;
1576 memcpy (base
+ *pix
+ 2,
1577 od
.data
+ ix
, (unsigned)incr
);
1583 data_string_forget (&od
, MDL
);
1587 option_dereference(&option
, MDL
);
1589 /* If we can overload, and we have, then PAD and END those spaces. */
1590 if (first_cutoff
&& six
) {
1591 if ((first_cutoff
+ six
+ 1) < sbufend
)
1592 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1593 sbufend
- (first_cutoff
+ six
+ 1));
1594 else if (first_cutoff
+ six
>= sbufend
)
1595 log_fatal("Second buffer overflow in overloaded options.");
1597 buffer
[first_cutoff
+ six
] = DHO_END
;
1599 *ocount
|= 1; /* So that caller knows there's data there. */
1602 if (second_cutoff
&& tix
) {
1603 if (second_cutoff
+ tix
+ 1 < buflen
) {
1604 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1605 buflen
- (second_cutoff
+ tix
+ 1));
1606 } else if (second_cutoff
+ tix
>= buflen
)
1607 log_fatal("Third buffer overflow in overloaded options.");
1609 buffer
[second_cutoff
+ tix
] = DHO_END
;
1611 *ocount
|= 2; /* So that caller knows there's data there. */
1614 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1615 log_fatal("Not enough space for option overload option.");
1620 /* Return true if the format string has a variable length text option
1621 * ("t"), return false otherwise.
1625 format_has_text(format
)
1631 while (*p
!= '\0') {
1637 /* These symbols are arbitrary, not fixed or
1638 * determinable length...text options with them is
1639 * invalid (whatever the case, they are never NULL
1651 /* 'c' only follows 'D' atoms, and indicates that
1652 * compression may be used. If there was a 'D'
1653 * atom already, we would have returned. So this
1654 * is an error, but continue looking for 't' anyway.
1656 log_error("format_has_text(%s): 'c' atoms are illegal "
1657 "except after 'D' atoms.", format
);
1660 /* 'E' is variable length, but not arbitrary...you
1661 * can find its length if you can find an END option.
1662 * N is (n)-byte in length but trails a name of a
1663 * space defining the enumeration values. So treat
1664 * both the same - valid, fixed-length fields.
1668 /* Consume the space name. */
1669 while ((*p
!= '\0') && (*p
++ != '.'))
1681 /* Determine the minimum length of a DHCP option prior to any variable
1682 * or inconsistent length formats, according to its configured format
1683 * variable (and possibly from supplied option cache contents for variable
1684 * length format symbols).
1688 format_min_length(format
, oc
)
1690 struct option_cache
*oc
;
1692 const char *p
, *name
;
1695 struct enumeration
*espace
;
1698 while (*p
!= '\0') {
1700 case '6': /* IPv6 Address */
1705 case 'I': /* IPv4 Address */
1706 case 'l': /* int32_t */
1707 case 'L': /* uint32_t */
1708 case 'T': /* Lease Time, uint32_t equivalent */
1713 case 's': /* int16_t */
1714 case 'S': /* uint16_t */
1719 case 'N': /* Enumeration value. */
1720 /* Consume space name. */
1724 log_fatal("Corrupt format: %s", format
);
1726 espace
= find_enumeration(name
, p
- name
);
1727 if (espace
== NULL
) {
1728 log_error("Unknown enumeration: %s", format
);
1729 /* Max is safest value to return. */
1733 min_len
+= espace
->width
;
1734 last_size
= espace
->width
;
1739 case 'b': /* int8_t */
1740 case 'B': /* uint8_t */
1741 case 'F': /* Flag that is always true. */
1742 case 'f': /* Flag */
1747 case 'o': /* Last argument is optional. */
1748 min_len
-= last_size
;
1750 /* XXX: It MAY be possible to sense the end of an
1751 * encapsulated space, but right now this is too
1752 * hard to support. Return a safe value.
1754 case 'e': /* Encapsulation hint (there is an 'E' later). */
1755 case 'E': /* Encapsulated options. */
1758 case 'd': /* "Domain name" */
1759 case 'D': /* "rfc1035 formatted names" */
1760 case 't': /* "ASCII Text" */
1761 case 'X': /* "ASCII or Hex Conditional */
1762 case 'x': /* "Hex" */
1763 case 'A': /* Array of all that precedes. */
1764 case 'a': /* Array of preceding symbol. */
1765 case 'Z': /* nothing. */
1766 case 'k': /* key name */
1769 case 'c': /* Compress flag for D atom. */
1770 log_error("format_min_length(%s): 'c' atom is illegal "
1771 "except after 'D' atom.", format
);
1775 /* No safe value is known. */
1776 log_error("format_min_length(%s): No safe value "
1777 "for unknown format symbols.", format
);
1786 /* Format the specified option so that a human can easily read it. */
1787 /* Maximum pretty printed size */
1788 #define MAX_OUTPUT_SIZE 32*1024
1789 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1790 struct option
*option
;
1791 const unsigned char *data
;
1796 /* We add 128 byte pad so we don't have to add checks everywhere. */
1797 static char optbuf
[MAX_OUTPUT_SIZE
+ 128]; /* XXX */
1798 static char *endbuf
= optbuf
+ MAX_OUTPUT_SIZE
;
1806 char fmtbuf
[32] = "";
1808 struct enumeration
*enumbuf
[32]; /* MUST be same as fmtbuf */
1810 const unsigned char *dp
= data
;
1813 isc_boolean_t a_array
= ISC_FALSE
;
1821 memset (enumbuf
, 0, sizeof enumbuf
);
1823 /* Figure out the size of the data. */
1824 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1825 if (l
>= sizeof(fmtbuf
) - 1)
1826 log_fatal("Bounds failure on internal buffer at "
1830 log_error ("%s: Extra codes in format string: %s",
1832 &(option
-> format
[i
]));
1836 fmtbuf
[l
] = option
-> format
[i
];
1837 switch (option
-> format
[i
]) {
1847 /* Skip the universe name. */
1848 while (option
-> format
[i
] &&
1849 option
-> format
[i
] != '.')
1853 for (k
= 0; k
< len
; k
++) {
1854 if (!isascii (data
[k
]) ||
1855 !isprint (data
[k
]))
1858 /* If we found no bogus characters, or the bogus
1859 character we found is a trailing NUL, it's
1860 okay to print this option as text. */
1861 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1875 /* The 'c' atom is a 'D' modifier only. */
1876 log_error("'c' atom not following D atom in format "
1877 "string: %s", option
->format
);
1881 * Skip the 'c' atom, if present. It does not affect
1882 * how we convert wire->text format (if compression is
1883 * present either way, we still process it).
1885 if (option
->format
[i
+1] == 'c')
1891 /* Should not be optional, array or compressed */
1892 if ((option
->format
[i
+1] == 'o') ||
1893 (option
->format
[i
+1] == 'a') ||
1894 (option
->format
[i
+1] == 'A') ||
1895 (option
->format
[i
+1] == 'c')) {
1896 log_error("%s: Illegal use of domain name: %s",
1898 &(option
->format
[i
-1]));
1901 k
= MRns_name_len(data
+ len
, data
+ hunksize
);
1903 log_error("Invalid domain name.");
1916 while (option
-> format
[i
] &&
1917 option
-> format
[i
] != '.')
1920 find_enumeration (&option
-> format
[k
] + 1,
1922 if (enumbuf
[l
] == NULL
) {
1926 hunksize
+= enumbuf
[l
]->width
;
1927 hunkinc
= enumbuf
[l
]->width
;
1960 log_error ("%s: garbage in format string: %s",
1962 &(option
-> format
[i
]));
1967 /* Check for too few bytes... */
1968 if (hunksize
- opthunk
> len
) {
1969 log_error ("%s: expecting at least %d bytes; got %d",
1974 /* Check for too many bytes... */
1975 if (numhunk
== -1 && hunksize
< len
)
1976 log_error ("%s: %d extra bytes",
1980 /* If this is an array, compute its size. */
1982 if (a_array
== ISC_TRUE
) {
1984 * It is an 'a' type array - we repeat the
1985 * last format type. A binary string for 'X'
1986 * is also like this. hunkinc is the size
1987 * of the last format type and we add 1 to
1988 * cover the entire first record.
1991 /* If format string had no valid entries prior to
1992 * 'a' hunkinc will be 0. Ex: "a", "oa", "aA" */
1994 log_error ("%s: invalid 'a' format: %s",
1995 option
->name
, option
->format
);
1999 numhunk
= ((len
- hunksize
) / hunkinc
) + 1;
2000 len_used
= hunksize
+ ((numhunk
- 1) * hunkinc
);
2003 * It is an 'A' type array - we repeat the
2007 /* If format string had no valid entries prior to
2008 * 'A' hunksize will be 0. Ex: "A", "oA", "foA" */
2009 if (hunksize
== 0) {
2010 log_error ("%s: invalid 'A' format: %s",
2011 option
->name
, option
->format
);
2015 numhunk
= len
/ hunksize
;
2016 len_used
= numhunk
* hunksize
;
2019 /* See if we got an exact number of hunks. */
2020 if (len_used
< len
) {
2021 log_error ("%s: %d extra bytes at end of array\n",
2028 /* A one-hunk array prints the same as a single hunk. */
2032 /* Cycle through the array (or hunk) printing the data. */
2033 for (i
= 0; i
< numhunk
; i
++) {
2034 if ((a_array
== ISC_TRUE
) && (i
!= 0) && (numelem
> 0)) {
2036 * For 'a' type of arrays we repeat
2037 * only the last format character
2038 * We should never hit the case of numelem == 0
2039 * but let's include the check to be safe.
2044 * for other types of arrays or the first
2045 * time through for 'a' types, we go through
2046 * the entire set of format characters.
2051 for (; j
< numelem
; j
++) {
2052 switch (fmtbuf
[j
]) {
2055 /* endbuf-1 leaves room for NULL. */
2056 k
= pretty_text(&op
, endbuf
- 1, &dp
,
2057 data
+ len
, emit_quotes
);
2059 log_error("Error printing text.");
2064 case 'd': /* RFC1035 format name */
2065 k
= MRns_name_len(data
+ len
, dp
);
2066 /* Already tested... */
2068 log_error("invalid domain name.");
2071 pretty_dname(&op
, endbuf
-1, dp
, data
+ len
);
2072 /* pretty_dname does not add the nul */
2076 case 'D': /* RFC1035 format name list */
2077 for( ; dp
< (data
+ len
) ; dp
+= k
) {
2078 unsigned char nbuff
[NS_MAXCDNAME
];
2079 const unsigned char *nbp
, *nend
;
2081 nend
= &nbuff
[sizeof(nbuff
)];
2083 /* If this is for ISC DHCP consumption
2084 * (emit_quotes), lay it out as a list
2085 * of STRING tokens. Otherwise, it is
2086 * a space-separated list of DNS-
2087 * escaped names as /etc/resolv.conf
2091 if (op
+ 2 > endbuf
)
2099 /* XXX: if fmtbuf[j+1] != 'c', we
2100 * should warn if the data was
2101 * compressed anyway.
2103 k
= MRns_name_unpack(data
,
2109 log_error("Invalid domain "
2114 /* If emit_quotes, then use ISC DHCP
2115 * escapes. Otherwise, rely only on
2120 pretty_domain(&op
, endbuf
-1,
2123 /* MRns_name_ntop() includes
2124 * a trailing NUL in its
2127 count
= MRns_name_ntop(
2132 log_error("Invalid "
2137 /* Consume all but the trailing
2142 /* Replace the trailing NUL
2143 * with the implicit root
2144 * (in the unlikely event the
2145 * domain name /is/ the root).
2152 /* pretty-printing an array of enums is
2153 going to get ugly. */
2160 switch (enumbuf
[j
]->width
) {
2162 tval
= getUChar(dp
);
2166 tval
= getUShort(dp
);
2170 tval
= getULong(dp
);
2174 log_fatal("Impossible case at %s:%d.",
2176 return "<double impossible condition>";
2180 if (!enumbuf
[j
] -> values
[i
].name
)
2182 if (enumbuf
[j
] -> values
[i
].value
==
2186 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
2187 dp
+= enumbuf
[j
]->width
;
2191 sprintf(op
, "%lu", tval
);
2196 memcpy(iaddr
.iabuf
, dp
, 4);
2197 strcpy(op
, piaddr(iaddr
));
2202 memcpy(iaddr
.iabuf
, dp
, 16);
2203 strcpy(op
, piaddr(iaddr
));
2207 sprintf (op
, "%ld", (long)getLong (dp
));
2211 tval
= getULong (dp
);
2213 sprintf (op
, "%s", "infinite");
2215 sprintf(op
, "%lu", tval
);
2219 (unsigned long)getULong(dp
));
2223 sprintf (op
, "%d", (int)getShort (dp
));
2227 sprintf(op
, "%u", (unsigned)getUShort(dp
));
2231 sprintf (op
, "%d", *(const char *)dp
++);
2234 sprintf (op
, "%d", *dp
++);
2238 sprintf (op
, "%x", *dp
++);
2241 strcpy (op
, *dp
++ ? "true" : "false");
2244 strcpy (op
, "true");
2251 log_error ("Unexpected format code %c",
2257 log_error ("Option data exceeds"
2258 " maximum size %d", MAX_OUTPUT_SIZE
);
2262 if (dp
== data
+ len
)
2264 if (j
+ 1 < numelem
&& comma
!= ':')
2267 if (i
+ 1 < numhunk
) {
2270 if (dp
== data
+ len
)
2276 int get_option (result
, universe
, packet
, lease
, client_state
,
2277 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2278 struct data_string
*result
;
2279 struct universe
*universe
;
2280 struct packet
*packet
;
2281 struct lease
*lease
;
2282 struct client_state
*client_state
;
2283 struct option_state
*in_options
;
2284 struct option_state
*cfg_options
;
2285 struct option_state
*options
;
2286 struct binding_scope
**scope
;
2291 struct option_cache
*oc
;
2293 if (!universe
-> lookup_func
)
2295 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
2298 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
2299 in_options
, cfg_options
, scope
, oc
,
2306 * Look for the option and dig out the value assoicated with it.
2307 * Currently this is used for 1 byte integers, it maybe expanded
2308 * in the future to handle other integers at which point it will
2309 * need a size argument.
2311 int get_option_int (result
, universe
, packet
, lease
, client_state
,
2312 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2314 struct universe
*universe
;
2315 struct packet
*packet
;
2316 struct lease
*lease
;
2317 struct client_state
*client_state
;
2318 struct option_state
*in_options
;
2319 struct option_state
*cfg_options
;
2320 struct option_state
*options
;
2321 struct binding_scope
**scope
;
2326 struct option_cache
*oc
;
2327 struct data_string d1
;
2330 /* basic sanity checks */
2331 if ((options
== NULL
) || (universe
->lookup_func
== NULL
))
2334 /* find the option cache */
2335 oc
= ((*universe
->lookup_func
)(universe
, options
, code
));
2339 /* if there is a value get it into the string */
2340 memset(&d1
, 0, sizeof(d1
));
2341 if (!evaluate_option_cache(&d1
, packet
, lease
, client_state
,
2342 in_options
, cfg_options
, scope
, oc
,
2346 /* If the length matches extract the value for the return */
2348 *result
= d1
.data
[0];
2351 data_string_forget(&d1
, MDL
);
2356 void set_option (universe
, options
, option
, op
)
2357 struct universe
*universe
;
2358 struct option_state
*options
;
2359 struct option_cache
*option
;
2360 enum statement_op op
;
2362 struct option_cache
*oc
, *noc
;
2367 case eval_statement
:
2368 case break_statement
:
2370 log_error ("bogus statement type in set_option.");
2373 case default_option_statement
:
2374 oc
= lookup_option (universe
, options
,
2375 option
-> option
-> code
);
2378 save_option (universe
, options
, option
);
2381 case supersede_option_statement
:
2382 case send_option_statement
:
2383 /* Install the option, replacing any existing version. */
2384 save_option (universe
, options
, option
);
2387 case append_option_statement
:
2388 case prepend_option_statement
:
2389 oc
= lookup_option (universe
, options
,
2390 option
-> option
-> code
);
2392 save_option (universe
, options
, option
);
2395 /* If it's not an expression, make it into one. */
2396 if (!oc
-> expression
&& oc
-> data
.len
) {
2397 if (!expression_allocate (&oc
-> expression
, MDL
)) {
2398 log_error ("Can't allocate const expression.");
2401 oc
-> expression
-> op
= expr_const_data
;
2403 (&oc
-> expression
-> data
.const_data
,
2405 data_string_forget (&oc
-> data
, MDL
);
2407 noc
= (struct option_cache
*)0;
2408 if (!option_cache_allocate (&noc
, MDL
))
2410 if (op
== append_option_statement
) {
2411 if (!make_concat (&noc
-> expression
,
2413 option
-> expression
)) {
2414 option_cache_dereference (&noc
, MDL
);
2418 if (!make_concat (&noc
-> expression
,
2419 option
-> expression
,
2420 oc
-> expression
)) {
2421 option_cache_dereference (&noc
, MDL
);
2426 /* If we are trying to combine compressed domain-lists then
2427 * we need to change the expression opcode. The lists must
2428 * be decompressed, combined, and then recompressed to work
2429 * correctly. You cannot simply add two compressed lists
2431 switch (((memcmp(option
->option
->format
, "Dc", 2) == 0) +
2432 (memcmp(oc
->option
->format
, "Dc", 2) == 0))) {
2434 /* Only one is "Dc", this won't work
2435 * Not sure if you can make this occur, but just
2437 log_error ("Both options must be Dc format");
2438 option_cache_dereference (&noc
, MDL
);
2441 /* Both are "Dc", change the code */
2442 noc
->expression
->op
= expr_concat_dclist
;
2445 /* Neither are "Dc", so as you were */
2449 option_reference(&(noc
->option
), oc
->option
, MDL
);
2450 save_option (universe
, options
, noc
);
2451 option_cache_dereference (&noc
, MDL
);
2456 struct option_cache
*lookup_option (universe
, options
, code
)
2457 struct universe
*universe
;
2458 struct option_state
*options
;
2462 return (struct option_cache
*)0;
2463 if (universe
-> lookup_func
)
2464 return (*universe
-> lookup_func
) (universe
, options
, code
);
2466 log_error ("can't look up options in %s space.",
2468 return (struct option_cache
*)0;
2471 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
2472 struct universe
*universe
;
2473 struct option_state
*options
;
2480 /* Make sure there's a hash table. */
2481 if (universe
-> index
>= options
-> universe_count
||
2482 !(options
-> universes
[universe
-> index
]))
2483 return (struct option_cache
*)0;
2485 hash
= options
-> universes
[universe
-> index
];
2487 hashix
= compute_option_hash (code
);
2488 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2489 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
2491 return (struct option_cache
*)(bptr
-> car
);
2493 return (struct option_cache
*)0;
2496 /* Save a specified buffer into an option cache. */
2498 save_option_buffer(struct universe
*universe
, struct option_state
*options
,
2499 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2500 unsigned code
, int terminatep
)
2502 struct option_cache
*op
= NULL
;
2505 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2511 save_option(universe
, options
, op
);
2515 option_cache_dereference(&op
, MDL
);
2520 /* Append a specified buffer onto the tail of an option cache. */
2522 append_option_buffer(struct universe
*universe
, struct option_state
*options
,
2523 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2524 unsigned code
, int terminatep
)
2526 struct option_cache
*op
= NULL
;
2529 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2535 also_save_option(universe
, options
, op
);
2539 option_cache_dereference(&op
, MDL
);
2544 /* Create/copy a buffer into a new option cache. */
2546 prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
2547 unsigned char *buffer
, unsigned length
, unsigned code
,
2548 int terminatep
, struct option_cache
**opp
)
2550 struct buffer
*lbp
= NULL
;
2551 struct option
*option
= NULL
;
2552 struct option_cache
*op
;
2555 /* Code sizes of 8, 16, and 32 bits are allowed. */
2556 switch(universe
->tag_size
) {
2566 if (code
> 0xffffffff)
2571 log_fatal("Inconsistent universe tag size at %s:%d.", MDL
);
2574 option_code_hash_lookup(&option
, universe
->code_hash
, &code
, 0, MDL
);
2576 /* If we created an option structure for each option a client
2577 * supplied, it's possible we may create > 2^32 option structures.
2578 * That's not feasible. So by failing to enter these option
2579 * structures into the code and name hash tables, references will
2580 * never be more than 1 - when the option cache is destroyed, this
2581 * will be cleaned up.
2584 char nbuf
[sizeof("unknown-4294967295")];
2586 sprintf(nbuf
, "unknown-%u", code
);
2588 option
= new_option(nbuf
, MDL
);
2593 option
->format
= default_option_format
;
2594 option
->universe
= universe
;
2595 option
->code
= code
;
2597 /* new_option() doesn't set references, pretend. */
2601 if (!option_cache_allocate (opp
, MDL
)) {
2602 log_error("No memory for option code %s.%s.",
2603 universe
->name
, option
->name
);
2608 /* Pointer rather than double pointer makes for less parens. */
2611 option_reference(&op
->option
, option
, MDL
);
2613 /* If we weren't passed a buffer in which the data are saved and
2614 refcounted, allocate one now. */
2616 if (!buffer_allocate (&lbp
, length
+ terminatep
, MDL
)) {
2617 log_error ("no memory for option buffer.");
2622 memcpy (lbp
-> data
, buffer
, length
+ terminatep
);
2624 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
2627 /* Reference buffer copy to option cache. */
2628 op
-> data
.buffer
= (struct buffer
*)0;
2629 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
2631 /* Point option cache into buffer. */
2632 op
-> data
.data
= buffer
;
2633 op
-> data
.len
= length
;
2636 /* NUL terminate (we can get away with this because we (or
2637 the caller!) allocated one more than the buffer size, and
2638 because the byte following the end of an option is always
2639 the code of the next option, which the caller is getting
2640 out of the *original* buffer. */
2641 buffer
[length
] = 0;
2642 op
-> data
.terminated
= 1;
2644 op
-> data
.terminated
= 0;
2646 /* If this option is ultimately a text option, null determinate to
2647 * comply with RFC2132 section 2. Mark a flag so this can be sensed
2648 * later to echo NULLs back to clients that supplied them (they
2649 * probably expect them).
2651 if (format_has_text(option
->format
)) {
2652 int min_len
= format_min_length(option
->format
, op
);
2654 while ((op
->data
.len
> min_len
) &&
2655 (op
->data
.data
[op
->data
.len
-1] == '\0')) {
2657 op
->flags
|= OPTION_HAD_NULLS
;
2661 /* And let go of our references. */
2664 buffer_dereference(&lbp
, MDL
);
2665 option_dereference(&option
, MDL
);
2671 count_options(struct option_cache
*dummy_oc
,
2672 struct packet
*dummy_packet
,
2673 struct lease
*dummy_lease
,
2674 struct client_state
*dummy_client_state
,
2675 struct option_state
*dummy_opt_state
,
2676 struct option_state
*opt_state
,
2677 struct binding_scope
**dummy_binding_scope
,
2678 struct universe
*dummy_universe
,
2679 void *void_accumulator
) {
2680 int *accumulator
= (int *)void_accumulator
;
2686 collect_oro(struct option_cache
*oc
,
2687 struct packet
*dummy_packet
,
2688 struct lease
*dummy_lease
,
2689 struct client_state
*dummy_client_state
,
2690 struct option_state
*dummy_opt_state
,
2691 struct option_state
*opt_state
,
2692 struct binding_scope
**dummy_binding_scope
,
2693 struct universe
*dummy_universe
,
2695 struct data_string
*oro
= (struct data_string
*)void_oro
;
2697 putUShort(oro
->buffer
->data
+ oro
->len
, oc
->option
->code
);
2701 /* build_server_oro() is presently unusued, but may be used at a future date
2702 * with support for Reconfigure messages (as a hint to the client about new
2703 * option value contents).
2706 build_server_oro(struct data_string
*server_oro
,
2707 struct option_state
*options
,
2708 const char *file
, int line
) {
2714 * Count the number of options, so we can allocate enough memory.
2715 * We want to mention sub-options too, so check all universes.
2718 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2719 NULL
, &dhcpv6_universe
, (void *)&num_opts
,
2721 for (i
=0; i
< options
->universe_count
; i
++) {
2722 if (options
->universes
[i
] != NULL
) {
2723 o
= universes
[i
]->enc_opt
;
2725 if (o
->universe
== &dhcpv6_universe
) {
2729 o
= o
->universe
->enc_opt
;
2737 memset(server_oro
, 0, sizeof(*server_oro
));
2738 if (!buffer_allocate(&server_oro
->buffer
, num_opts
* 2, MDL
)) {
2739 log_fatal("no memory to build server ORO");
2741 server_oro
->data
= server_oro
->buffer
->data
;
2745 * We want to mention sub-options too, so check all universes.
2747 server_oro
->len
= 0; /* gets set in collect_oro */
2748 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2749 NULL
, &dhcpv6_universe
, (void *)server_oro
,
2751 for (i
=0; i
< options
->universe_count
; i
++) {
2752 if (options
->universes
[i
] != NULL
) {
2753 o
= universes
[i
]->enc_opt
;
2755 if (o
->universe
== &dhcpv6_universe
) {
2757 tmp
= server_oro
->buffer
->data
;
2758 putUShort(tmp
+ server_oro
->len
,
2760 server_oro
->len
+= 2;
2763 o
= o
->universe
->enc_opt
;
2769 /* Wrapper function to put an option cache into an option state. */
2771 save_option(struct universe
*universe
, struct option_state
*options
,
2772 struct option_cache
*oc
)
2774 if (universe
->save_func
)
2775 (*universe
->save_func
)(universe
, options
, oc
, ISC_FALSE
);
2777 log_error("can't store options in %s space.", universe
->name
);
2780 /* Wrapper function to append an option cache into an option state's list. */
2782 also_save_option(struct universe
*universe
, struct option_state
*options
,
2783 struct option_cache
*oc
)
2785 if (universe
->save_func
)
2786 (*universe
->save_func
)(universe
, options
, oc
, ISC_TRUE
);
2788 log_error("can't store options in %s space.", universe
->name
);
2792 save_hashed_option(struct universe
*universe
, struct option_state
*options
,
2793 struct option_cache
*oc
, isc_boolean_t appendp
)
2797 pair
*hash
= options
-> universes
[universe
-> index
];
2798 struct option_cache
**ocloc
;
2800 if (oc
-> refcnt
== 0)
2803 /* Compute the hash. */
2804 hashix
= compute_option_hash (oc
-> option
-> code
);
2806 /* If there's no hash table, make one. */
2808 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
2810 log_error ("no memory to store %s.%s",
2811 universe
-> name
, oc
-> option
-> name
);
2814 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
2815 options
-> universes
[universe
-> index
] = (void *)hash
;
2817 /* Try to find an existing option matching the new one. */
2818 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2819 if (((struct option_cache
*)
2820 (bptr
-> car
)) -> option
-> code
==
2821 oc
-> option
-> code
)
2825 /* Deal with collisions on the hash list. */
2827 ocloc
= (struct option_cache
**)&bptr
->car
;
2830 * If appendp is set, append it onto the tail of the
2831 * ->next list. If it is not set, rotate it into
2832 * position at the head of the list.
2836 ocloc
= &(*ocloc
)->next
;
2837 } while (*ocloc
!= NULL
);
2839 option_cache_dereference(ocloc
, MDL
);
2842 option_cache_reference(ocloc
, oc
, MDL
);
2847 /* Otherwise, just put the new one at the head of the list. */
2848 bptr
= new_pair (MDL
);
2850 log_error ("No memory for option_cache reference.");
2853 bptr
-> cdr
= hash
[hashix
];
2855 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
2856 hash
[hashix
] = bptr
;
2859 void delete_option (universe
, options
, code
)
2860 struct universe
*universe
;
2861 struct option_state
*options
;
2864 if (universe
-> delete_func
)
2865 (*universe
-> delete_func
) (universe
, options
, code
);
2867 log_error ("can't delete options from %s space.",
2871 void delete_hashed_option (universe
, options
, code
)
2872 struct universe
*universe
;
2873 struct option_state
*options
;
2877 pair bptr
, prev
= (pair
)0;
2878 pair
*hash
= options
-> universes
[universe
-> index
];
2880 /* There may not be any options in this space. */
2884 /* Try to find an existing option matching the new one. */
2885 hashix
= compute_option_hash (code
);
2886 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2887 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
2892 /* If we found one, wipe it out... */
2895 prev
-> cdr
= bptr
-> cdr
;
2897 hash
[hashix
] = bptr
-> cdr
;
2898 option_cache_dereference
2899 ((struct option_cache
**)(&bptr
-> car
), MDL
);
2900 free_pair (bptr
, MDL
);
2904 extern struct option_cache
*free_option_caches
; /* XXX */
2906 int option_cache_dereference (ptr
, file
, line
)
2907 struct option_cache
**ptr
;
2911 if (!ptr
|| !*ptr
) {
2912 log_error ("Null pointer in option_cache_dereference: %s(%d)",
2914 #if defined (POINTER_DEBUG)
2922 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
2923 if (!(*ptr
) -> refcnt
) {
2924 if ((*ptr
) -> data
.buffer
)
2925 data_string_forget (&(*ptr
) -> data
, file
, line
);
2927 option_dereference(&(*ptr
)->option
, MDL
);
2928 if ((*ptr
) -> expression
)
2929 expression_dereference (&(*ptr
) -> expression
,
2932 option_cache_dereference (&((*ptr
) -> next
),
2934 /* Put it back on the free list... */
2935 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
2936 free_option_caches
= *ptr
;
2937 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
2939 if ((*ptr
) -> refcnt
< 0) {
2940 log_error ("%s(%d): negative refcnt!", file
, line
);
2941 #if defined (DEBUG_RC_HISTORY)
2942 dump_rc_history (*ptr
);
2944 #if defined (POINTER_DEBUG)
2947 *ptr
= (struct option_cache
*)0;
2951 *ptr
= (struct option_cache
*)0;
2956 int hashed_option_state_dereference (universe
, state
, file
, line
)
2957 struct universe
*universe
;
2958 struct option_state
*state
;
2966 /* Get the pointer to the array of hash table bucket heads. */
2967 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
2971 /* For each non-null head, loop through all the buckets dereferencing
2972 the attached option cache structures and freeing the buckets. */
2973 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2974 for (cp
= heads
[i
]; cp
; cp
= next
) {
2976 option_cache_dereference
2977 ((struct option_cache
**)&cp
-> car
,
2979 free_pair (cp
, file
, line
);
2983 dfree (heads
, file
, line
);
2984 state
-> universes
[universe
-> index
] = (void *)0;
2988 /* The 'data_string' primitive doesn't have an appension mechanism.
2989 * This function must then append a new option onto an existing buffer
2990 * by first duplicating the original buffer and appending the desired
2991 * values, followed by coping the new value into place.
2994 append_option(struct data_string
*dst
, struct universe
*universe
,
2995 struct option
*option
, struct data_string
*src
)
2997 struct data_string tmp
;
2999 if (src
->len
== 0 && option
->format
[0] != 'Z')
3002 memset(&tmp
, 0, sizeof(tmp
));
3004 /* Allocate a buffer to hold existing data, the current option's
3005 * tag and length, and the option's content.
3007 if (!buffer_allocate(&tmp
.buffer
,
3008 (dst
->len
+ universe
->length_size
+
3009 universe
->tag_size
+ src
->len
), MDL
)) {
3010 /* XXX: This kills all options presently stored in the
3011 * destination buffer. This is the way the original code
3012 * worked, and assumes an 'all or nothing' approach to
3013 * eg encapsulated option spaces. It may or may not be
3016 data_string_forget(dst
, MDL
);
3019 tmp
.data
= tmp
.buffer
->data
;
3021 /* Copy the existing data off the destination. */
3023 memcpy(tmp
.buffer
->data
, dst
->data
, dst
->len
);
3026 /* Place the new option tag and length. */
3027 (*universe
->store_tag
)(tmp
.buffer
->data
+ tmp
.len
, option
->code
);
3028 tmp
.len
+= universe
->tag_size
;
3029 (*universe
->store_length
)(tmp
.buffer
->data
+ tmp
.len
, src
->len
);
3030 tmp
.len
+= universe
->length_size
;
3032 /* Copy the option contents onto the end. */
3033 memcpy(tmp
.buffer
->data
+ tmp
.len
, src
->data
, src
->len
);
3034 tmp
.len
+= src
->len
;
3036 /* Play the shell game. */
3037 data_string_forget(dst
, MDL
);
3038 data_string_copy(dst
, &tmp
, MDL
);
3039 data_string_forget(&tmp
, MDL
);
3044 store_option(struct data_string
*result
, struct universe
*universe
,
3045 struct packet
*packet
, struct lease
*lease
,
3046 struct client_state
*client_state
,
3047 struct option_state
*in_options
, struct option_state
*cfg_options
,
3048 struct binding_scope
**scope
, struct option_cache
*oc
)
3050 struct data_string tmp
;
3051 struct universe
*subu
=NULL
;
3055 memset(&tmp
, 0, sizeof(tmp
));
3057 if (evaluate_option_cache(&tmp
, packet
, lease
, client_state
,
3058 in_options
, cfg_options
, scope
, oc
, MDL
)) {
3059 /* If the option is an extended 'e'ncapsulation (not a
3060 * direct 'E'ncapsulation), append the encapsulated space
3061 * onto the currently prepared value.
3064 if (oc
->option
->format
&&
3065 oc
->option
->format
[0] == 'e') {
3066 /* Skip forward to the universe name. */
3067 start
= strchr(oc
->option
->format
, 'E');
3071 /* Locate the name-terminating '.'. */
3072 end
= strchr(++start
, '.');
3074 /* A zero-length name is not allowed in
3075 * these kinds of encapsulations.
3077 if (end
== NULL
|| start
== end
)
3080 universe_hash_lookup(&subu
, universe_hash
,
3081 start
, end
- start
, MDL
);
3084 log_error("store_option: option %d "
3085 "refers to unknown "
3086 "option space '%.*s'.",
3088 (int)(end
- start
), start
);
3092 /* Append encapsulations, if any. We
3093 * already have the prepended values, so
3094 * we send those even if there are no
3095 * encapsulated options (and ->encapsulate()
3098 subu
->encapsulate(&tmp
, packet
, lease
,
3099 client_state
, in_options
,
3100 cfg_options
, scope
, subu
);
3103 } while (ISC_FALSE
);
3105 status
= append_option(result
, universe
, oc
->option
, &tmp
);
3106 data_string_forget(&tmp
, MDL
);
3114 int option_space_encapsulate (result
, packet
, lease
, client_state
,
3115 in_options
, cfg_options
, scope
, name
)
3116 struct data_string
*result
;
3117 struct packet
*packet
;
3118 struct lease
*lease
;
3119 struct client_state
*client_state
;
3120 struct option_state
*in_options
;
3121 struct option_state
*cfg_options
;
3122 struct binding_scope
**scope
;
3123 struct data_string
*name
;
3125 struct universe
*u
= NULL
;
3128 universe_hash_lookup(&u
, universe_hash
,
3129 (const char *)name
->data
, name
->len
, MDL
);
3131 log_error("option_space_encapsulate: option space '%.*s' does "
3132 "not exist, but is configured.",
3133 (int)name
->len
, name
->data
);
3137 if (u
->encapsulate
!= NULL
) {
3138 if (u
->encapsulate(result
, packet
, lease
, client_state
,
3139 in_options
, cfg_options
, scope
, u
))
3142 log_error("encapsulation requested for '%s' with no support.",
3148 /* Attempt to store any 'E'ncapsulated options that have not yet been
3149 * placed on the option buffer by the above (configuring a value in
3150 * the space over-rides any values in the child universe).
3152 * Note that there are far fewer universes than there will ever be
3153 * options in any universe. So it is faster to traverse the
3154 * configured universes, checking if each is encapsulated in the
3155 * current universe, and if so attempting to do so.
3157 * For each configured universe for this configuration option space,
3158 * which is encapsulated within the current universe, can not be found
3159 * by the lookup function (the universe-specific encapsulation
3160 * functions would already have stored such a value), and encapsulates
3161 * at least one option, append it.
3164 search_subencapsulation(struct data_string
*result
, struct packet
*packet
,
3165 struct lease
*lease
, struct client_state
*client_state
,
3166 struct option_state
*in_options
,
3167 struct option_state
*cfg_options
,
3168 struct binding_scope
**scope
,
3169 struct universe
*universe
)
3171 struct data_string sub
;
3172 struct universe
*subu
;
3175 memset(&sub
, 0, sizeof(sub
));
3176 for (i
= 0 ; i
< cfg_options
->universe_count
; i
++) {
3177 subu
= universes
[i
];
3180 log_fatal("Impossible condition at %s:%d.", MDL
);
3182 if (subu
->enc_opt
!= NULL
&&
3183 subu
->enc_opt
->universe
== universe
&&
3184 subu
->enc_opt
->format
!= NULL
&&
3185 subu
->enc_opt
->format
[0] == 'E' &&
3186 lookup_option(universe
, cfg_options
,
3187 subu
->enc_opt
->code
) == NULL
&&
3188 subu
->encapsulate(&sub
, packet
, lease
, client_state
,
3189 in_options
, cfg_options
,
3191 if (append_option(result
, universe
,
3192 subu
->enc_opt
, &sub
))
3195 data_string_forget(&sub
, MDL
);
3202 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
3203 in_options
, cfg_options
, scope
, universe
)
3204 struct data_string
*result
;
3205 struct packet
*packet
;
3206 struct lease
*lease
;
3207 struct client_state
*client_state
;
3208 struct option_state
*in_options
;
3209 struct option_state
*cfg_options
;
3210 struct binding_scope
**scope
;
3211 struct universe
*universe
;
3217 if (universe
-> index
>= cfg_options
-> universe_count
)
3220 hash
= cfg_options
-> universes
[universe
-> index
];
3224 /* For each hash bucket, and each configured option cache within
3225 * that bucket, append the option onto the buffer in encapsulated
3226 * format appropriate to the universe.
3229 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3230 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3231 if (store_option(result
, universe
, packet
, lease
,
3232 client_state
, in_options
, cfg_options
,
3233 scope
, (struct option_cache
*)p
->car
))
3238 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3239 in_options
, cfg_options
, scope
, universe
))
3245 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
3246 in_options
, cfg_options
, scope
, universe
)
3247 struct data_string
*result
;
3248 struct packet
*packet
;
3249 struct lease
*lease
;
3250 struct client_state
*client_state
;
3251 struct option_state
*in_options
;
3252 struct option_state
*cfg_options
;
3253 struct binding_scope
**scope
;
3254 struct universe
*universe
;
3258 static struct option_cache
*no_nwip
;
3259 struct data_string ds
;
3260 struct option_chain_head
*head
;
3262 if (universe
-> index
>= cfg_options
-> universe_count
)
3264 head
= ((struct option_chain_head
*)
3265 cfg_options
-> universes
[nwip_universe
.index
]);
3270 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3271 if (store_option (result
, universe
, packet
,
3272 lease
, client_state
, in_options
,
3274 (struct option_cache
*)ocp
-> car
))
3278 /* If there's no data, the nwip suboption is supposed to contain
3279 a suboption saying there's no data. */
3283 static unsigned char nni
[] = { 1, 0 };
3285 memset (&ds
, 0, sizeof ds
);
3288 if (option_cache_allocate (&no_nwip
, MDL
))
3289 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
3290 if (!option_code_hash_lookup(&no_nwip
->option
,
3291 nwip_universe
.code_hash
,
3293 log_fatal("Nwip option hash does not contain "
3297 if (store_option (result
, universe
, packet
, lease
,
3298 client_state
, in_options
,
3299 cfg_options
, scope
, no_nwip
))
3303 memset (&ds
, 0, sizeof ds
);
3305 /* If we have nwip options, the first one has to be the
3306 nwip-exists-in-option-area option. */
3307 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
3308 data_string_forget (result
, MDL
);
3311 ds
.data
= &ds
.buffer
-> data
[0];
3312 ds
.buffer
-> data
[0] = 2;
3313 ds
.buffer
-> data
[1] = 0;
3314 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
3315 data_string_forget (result
, MDL
);
3316 data_string_copy (result
, &ds
, MDL
);
3317 data_string_forget (&ds
, MDL
);
3323 /* We don't want to use MRns_name_pton()...it doesn't tell us how many bytes
3324 * it has consumed, and it plays havoc with our escapes.
3326 * So this function does DNS encoding, and returns either the number of
3327 * octects consumed (on success), or -1 on failure.
3330 fqdn_encode(unsigned char *dst
, int dstlen
, const unsigned char *src
,
3334 int i
, j
, len
, outlen
=0;
3337 for (i
= 0, j
= 0 ; i
< srclen
; i
= j
) {
3338 while ((j
< srclen
) && (src
[j
] != '.') && (src
[j
] != '\0'))
3342 if ((outlen
+ 1 + len
) > dstlen
)
3348 /* We only do one FQDN, ending in one root label. */
3352 memcpy(out
, src
+ i
, len
);
3356 /* Advance past the root label. */
3360 if ((outlen
+ 1) > dstlen
)
3363 /* Place the root label. */
3370 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
3371 in_options
, cfg_options
, scope
, universe
)
3372 struct data_string
*result
;
3373 struct packet
*packet
;
3374 struct lease
*lease
;
3375 struct client_state
*client_state
;
3376 struct option_state
*in_options
;
3377 struct option_state
*cfg_options
;
3378 struct binding_scope
**scope
;
3379 struct universe
*universe
;
3382 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3386 struct buffer
*bp
= (struct buffer
*)0;
3387 struct option_chain_head
*head
;
3389 /* If there's no FQDN universe, don't encapsulate. */
3390 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
3392 head
= ((struct option_chain_head
*)
3393 cfg_options
-> universes
[fqdn_universe
.index
]);
3397 /* Figure out the values of all the suboptions. */
3398 memset (results
, 0, sizeof results
);
3399 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3400 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
3401 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
3403 /* No need to check the return code, we check the length later */
3404 (void) evaluate_option_cache (&results
[oc
->option
->code
],
3405 packet
, lease
, client_state
,
3406 in_options
, cfg_options
, scope
,
3409 /* We add a byte for the flags field.
3410 * We add two bytes for the two RCODE fields.
3411 * We add a byte because we will prepend a label count.
3412 * We add a byte because the input len doesn't count null termination,
3413 * and we will add a root label.
3415 len
= 5 + results
[FQDN_FQDN
].len
;
3416 /* Save the contents of the option in a buffer. */
3417 if (!buffer_allocate (&bp
, len
, MDL
)) {
3418 log_error ("no memory for option buffer.");
3422 buffer_reference (&result
-> buffer
, bp
, MDL
);
3424 result
-> data
= &bp
-> data
[0];
3426 memset (&bp
-> data
[0], 0, len
);
3427 /* XXX: The server should set bit 4 (yes, 4, not 3) to 1 if it is
3428 * not going to perform any ddns updates. The client should set the
3429 * bit if it doesn't want the server to perform any updates.
3430 * The problem is at this layer of abstraction we have no idea if
3431 * the caller is a client or server.
3433 * See RFC4702, Section 3.1, 'The "N" bit'.
3438 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3439 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3440 bp
-> data
[0] |= 2;
3441 if (results
[FQDN_SERVER_UPDATE
].len
&&
3442 results
[FQDN_SERVER_UPDATE
].data
[0])
3443 bp
-> data
[0] |= 1;
3444 if (results
[FQDN_RCODE1
].len
)
3445 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
3446 if (results
[FQDN_RCODE2
].len
)
3447 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
3449 if (results
[FQDN_ENCODED
].len
&&
3450 results
[FQDN_ENCODED
].data
[0]) {
3452 if (results
[FQDN_FQDN
].len
) {
3453 i
= fqdn_encode(&bp
->data
[3], len
- 3,
3454 results
[FQDN_FQDN
].data
,
3455 results
[FQDN_FQDN
].len
);
3463 result
->terminated
= 0;
3466 if (results
[FQDN_FQDN
].len
) {
3467 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
3468 results
[FQDN_FQDN
].len
);
3469 result
-> len
+= results
[FQDN_FQDN
].len
;
3470 result
-> terminated
= 0;
3474 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3475 data_string_forget (&results
[i
], MDL
);
3477 buffer_dereference (&bp
, MDL
);
3479 data_string_forget(result
, MDL
);
3484 * Trap invalid attempts to inspect FQND6 contents.
3486 struct option_cache
*
3487 lookup_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3490 log_fatal("Impossible condition at %s:%d.", MDL
);
3495 * Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
3498 save_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3499 struct option_cache
*oc
, isc_boolean_t appendp
)
3501 log_fatal("Impossible condition at %s:%d.", MDL
);
3505 * Trap invalid attempts to delete an option out of the FQDN6 universe.
3508 delete_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3511 log_fatal("Impossible condition at %s:%d.", MDL
);
3514 /* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
3515 * V6's option cache entry.
3517 * This function is called speculatively by dhclient to setup
3518 * environment variables. But it would have already called the
3519 * foreach on the normal fqdn universe, so this is superfluous.
3522 fqdn6_option_space_foreach(struct packet
*packet
, struct lease
*lease
,
3523 struct client_state
*client_state
,
3524 struct option_state
*in_options
,
3525 struct option_state
*cfg_options
,
3526 struct binding_scope
**scope
,
3527 struct universe
*u
, void *stuff
,
3528 void (*func
)(struct option_cache
*,
3531 struct client_state
*,
3532 struct option_state
*,
3533 struct option_state
*,
3534 struct binding_scope
**,
3535 struct universe
*, void *))
3537 /* Pretend it is empty. */
3541 /* Turn the FQDN option space into a DHCPv6 FQDN option buffer.
3544 fqdn6_option_space_encapsulate(struct data_string
*result
,
3545 struct packet
*packet
, struct lease
*lease
,
3546 struct client_state
*client_state
,
3547 struct option_state
*in_options
,
3548 struct option_state
*cfg_options
,
3549 struct binding_scope
**scope
,
3550 struct universe
*universe
)
3553 struct option_chain_head
*head
;
3554 struct option_cache
*oc
;
3555 unsigned char *data
;
3556 int i
, len
, rval
= 0, count
;
3557 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3559 if (fqdn_universe
.index
>= cfg_options
->universe_count
)
3561 head
= ((struct option_chain_head
*)
3562 cfg_options
->universes
[fqdn_universe
.index
]);
3566 memset(results
, 0, sizeof(results
));
3567 for (ocp
= head
->first
; ocp
!= NULL
; ocp
= ocp
->cdr
) {
3568 oc
= (struct option_cache
*)(ocp
->car
);
3569 if (oc
->option
->code
> FQDN_SUBOPTION_COUNT
)
3570 log_fatal("Impossible condition at %s:%d.", MDL
);
3571 /* No need to check the return code, we check the length later */
3572 (void) evaluate_option_cache(&results
[oc
->option
->code
], packet
,
3573 lease
, client_state
, in_options
,
3574 cfg_options
, scope
, oc
, MDL
);
3577 /* We add a byte for the flags field at the start of the option.
3578 * We add a byte because we will prepend a label count.
3579 * We add a byte because the input length doesn't include a trailing
3580 * NULL, and we will add a root label.
3582 len
= results
[FQDN_FQDN
].len
+ 3;
3583 if (!buffer_allocate(&result
->buffer
, len
, MDL
)) {
3584 log_error("No memory for virtual option buffer.");
3587 data
= result
->buffer
->data
;
3588 result
->data
= data
;
3590 /* The first byte is the flags field. */
3593 /* XXX: The server should set bit 3 (yes, 3, not 4) to 1 if we
3594 * are not going to perform any DNS updates. The problem is
3595 * that at this layer of abstraction, we do not know if the caller
3596 * is the client or the server.
3598 * See RFC4704 Section 4.1, 'The "N" bit'.
3603 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3604 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3606 if (results
[FQDN_SERVER_UPDATE
].len
&&
3607 results
[FQDN_SERVER_UPDATE
].data
[0])
3610 /* If there is no name, we're done. */
3611 if (results
[FQDN_FQDN
].len
== 0) {
3616 /* Convert textual representation to DNS format. */
3617 count
= fqdn_encode(data
+ 1, len
- 1,
3618 results
[FQDN_FQDN
].data
, results
[FQDN_FQDN
].len
);
3622 data_string_forget(result
, MDL
);
3626 result
->len
+= count
;
3627 result
->terminated
= 0;
3633 for (i
= 1 ; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3634 data_string_forget(&results
[i
], MDL
);
3640 /* Read the DHCPv6 FQDN option's contents into the FQDN virtual space.
3643 fqdn6_universe_decode(struct option_state
*options
,
3644 const unsigned char *buffer
, unsigned length
,
3647 struct buffer
*bp
= NULL
;
3648 unsigned char *first_dot
;
3649 int len
, hlen
, dlen
;
3651 /* The FQDN option has to be at least 1 byte long. */
3655 /* Save the contents of the option in a buffer. There are 3
3656 * one-byte values we record from the packet. The input is
3657 * DNS encoded and to be safe we'll assume that each character
3658 * is non-printable and will be converted to an escaped number:
3659 * "\\nnn". Yes, we'll have dead space pretty much all the time
3660 * but the alternative is to basically dry run the conversion
3661 * first to calculate the precise size or reallocate to a smaller
3662 * buffer later, either of which is a bigger performance hit than
3663 * just doing a generous allocation. */
3664 unsigned bp_size
= 3 + (length
* 4);
3666 if (!buffer_allocate(&bp
, bp_size
, MDL
)) {
3667 log_error("No memory for dhcp6.fqdn option buffer.");
3671 /* The v6 FQDN is always 'encoded' per DNS. */
3673 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3674 bp
->data
, 1, FQDN_ENCODED
, 0))
3677 /* XXX: We need to process 'The "N" bit'. */
3678 if (buffer
[0] & 1) /* server-update. */
3683 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 2, 1,
3684 FQDN_SERVER_UPDATE
, 0))
3687 if (buffer
[0] & 2) /* no-client-update. */
3692 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 1, 1,
3693 FQDN_NO_CLIENT_UPDATE
, 0))
3696 /* Convert the domain name to textual representation for config. */
3697 len
= MRns_name_ntop(buffer
+ 1, (char *)bp
->data
+ 3, bp_size
- 3);
3699 log_error("Unable to convert dhcp6.fqdn domain name to "
3704 /* Save the domain name. */
3706 unsigned char *fqdn_start
= bp
->data
+ 3;
3708 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3709 fqdn_start
, len
, FQDN_FQDN
, 1))
3712 first_dot
= (unsigned char *)strchr((char *)fqdn_start
, '.');
3714 if (first_dot
!= NULL
) {
3715 hlen
= first_dot
- fqdn_start
;
3722 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3723 fqdn_start
, len
, FQDN_FQDN
, 1) ||
3725 !save_option_buffer(&fqdn_universe
, options
, bp
,
3727 FQDN_HOSTNAME
, 0)) ||
3729 !save_option_buffer(&fqdn_universe
, options
, bp
,
3730 first_dot
, dlen
, FQDN_DOMAINNAME
, 0)))
3734 buffer_dereference(&bp
, MDL
);
3738 buffer_dereference(&bp
, MDL
);
3742 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3743 struct client_state
*client_state
,
3744 struct option_state
*in_options
,
3745 struct option_state
*cfg_options
,
3746 struct binding_scope
**scope
,
3747 struct universe
*u
, void *stuff
,
3748 void (*func
) (struct option_cache
*,
3750 struct lease
*, struct client_state
*,
3751 struct option_state
*,
3752 struct option_state
*,
3753 struct binding_scope
**,
3754 struct universe
*, void *))
3757 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
3758 cfg_options
, scope
, u
, stuff
, func
);
3761 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
3762 struct client_state
*client_state
,
3763 struct option_state
*in_options
,
3764 struct option_state
*cfg_options
,
3765 struct binding_scope
**scope
,
3766 struct universe
*u
, void *stuff
,
3767 void (*func
) (struct option_cache
*,
3769 struct lease
*, struct client_state
*,
3770 struct option_state
*,
3771 struct option_state
*,
3772 struct binding_scope
**,
3773 struct universe
*, void *),
3774 struct option_cache
*oc
,
3777 struct universe
*universe
= find_option_universe (oc
-> option
,
3779 if (universe
-> foreach
)
3780 (*universe
-> foreach
) (packet
, lease
, client_state
,
3781 in_options
, cfg_options
,
3782 scope
, universe
, stuff
, func
);
3785 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3786 struct client_state
*client_state
,
3787 struct option_state
*in_options
,
3788 struct option_state
*cfg_options
,
3789 struct binding_scope
**scope
,
3790 struct universe
*u
, void *stuff
,
3791 void (*func
) (struct option_cache
*,
3794 struct client_state
*,
3795 struct option_state
*,
3796 struct option_state
*,
3797 struct binding_scope
**,
3798 struct universe
*, void *))
3802 struct option_cache
*oc
;
3804 if (cfg_options
-> universe_count
<= u
-> index
)
3807 hash
= cfg_options
-> universes
[u
-> index
];
3810 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3812 /* XXX save _all_ options! XXX */
3813 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3814 oc
= (struct option_cache
*)p
-> car
;
3815 (*func
) (oc
, packet
, lease
, client_state
,
3816 in_options
, cfg_options
, scope
, u
, stuff
);
3822 save_linked_option(struct universe
*universe
, struct option_state
*options
,
3823 struct option_cache
*oc
, isc_boolean_t appendp
)
3826 struct option_chain_head
*head
;
3827 struct option_cache
**ocloc
;
3829 if (universe
-> index
>= options
-> universe_count
)
3831 head
= ((struct option_chain_head
*)
3832 options
-> universes
[universe
-> index
]);
3834 if (!option_chain_head_allocate (((struct option_chain_head
**)
3835 &options
-> universes
3836 [universe
-> index
]), MDL
))
3838 head
= ((struct option_chain_head
*)
3839 options
-> universes
[universe
-> index
]);
3842 /* Find the tail of the list. */
3843 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3844 ocloc
= (struct option_cache
**)&(*tail
)->car
;
3846 if (oc
->option
->code
== (*ocloc
)->option
->code
) {
3849 ocloc
= &(*ocloc
)->next
;
3850 } while (*ocloc
!= NULL
);
3852 option_cache_dereference(ocloc
, MDL
);
3854 option_cache_reference(ocloc
, oc
, MDL
);
3859 *tail
= cons (0, 0);
3861 option_cache_reference ((struct option_cache
**)
3862 (&(*tail
) -> car
), oc
, MDL
);
3866 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
3867 in_options
, cfg_options
, scope
, universe
)
3868 struct data_string
*result
;
3869 struct packet
*packet
;
3870 struct lease
*lease
;
3871 struct client_state
*client_state
;
3872 struct option_state
*in_options
;
3873 struct option_state
*cfg_options
;
3874 struct binding_scope
**scope
;
3875 struct universe
*universe
;
3879 struct option_chain_head
*head
;
3881 if (universe
-> index
>= cfg_options
-> universe_count
)
3883 head
= ((struct option_chain_head
*)
3884 cfg_options
-> universes
[universe
-> index
]);
3888 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3889 if (store_option (result
, universe
, packet
,
3890 lease
, client_state
, in_options
, cfg_options
,
3891 scope
, (struct option_cache
*)(oc
-> car
)))
3895 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3896 in_options
, cfg_options
, scope
, universe
))
3902 void delete_linked_option (universe
, options
, code
)
3903 struct universe
*universe
;
3904 struct option_state
*options
;
3907 pair
*tail
, tmp
= (pair
)0;
3908 struct option_chain_head
*head
;
3910 if (universe
-> index
>= options
-> universe_count
)
3912 head
= ((struct option_chain_head
*)
3913 options
-> universes
[universe
-> index
]);
3917 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3919 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
3921 tmp
= (*tail
) -> cdr
;
3922 option_cache_dereference ((struct option_cache
**)
3923 (&(*tail
) -> car
), MDL
);
3931 struct option_cache
*lookup_linked_option (universe
, options
, code
)
3932 struct universe
*universe
;
3933 struct option_state
*options
;
3937 struct option_chain_head
*head
;
3939 if (universe
-> index
>= options
-> universe_count
)
3941 head
= ((struct option_chain_head
*)
3942 options
-> universes
[universe
-> index
]);
3946 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3948 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
3949 return (struct option_cache
*)(oc
-> car
);
3953 return (struct option_cache
*)0;
3956 int linked_option_state_dereference (universe
, state
, file
, line
)
3957 struct universe
*universe
;
3958 struct option_state
*state
;
3962 return (option_chain_head_dereference
3963 ((struct option_chain_head
**)
3964 (&state
-> universes
[universe
-> index
]), MDL
));
3967 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3968 struct client_state
*client_state
,
3969 struct option_state
*in_options
,
3970 struct option_state
*cfg_options
,
3971 struct binding_scope
**scope
,
3972 struct universe
*u
, void *stuff
,
3973 void (*func
) (struct option_cache
*,
3976 struct client_state
*,
3977 struct option_state
*,
3978 struct option_state
*,
3979 struct binding_scope
**,
3980 struct universe
*, void *))
3983 struct option_chain_head
*head
;
3985 if (u
-> index
>= cfg_options
-> universe_count
)
3987 head
= ((struct option_chain_head
*)
3988 cfg_options
-> universes
[u
-> index
]);
3991 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
3992 (*func
) ((struct option_cache
*)(car
-> car
),
3993 packet
, lease
, client_state
,
3994 in_options
, cfg_options
, scope
, u
, stuff
);
3998 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
3999 struct interface_info
*interface
;
4000 struct dhcp_packet
*packet
;
4002 unsigned int from_port
;
4004 struct hardware
*hfrom
;
4006 struct option_cache
*op
;
4007 struct packet
*decoded_packet
;
4008 #if defined (DEBUG_MEMORY_LEAKAGE)
4009 unsigned long previous_outstanding
= dmalloc_outstanding
;
4012 #if defined (TRACING)
4013 trace_inpacket_stash(interface
, packet
, len
, from_port
, from
, hfrom
);
4016 decoded_packet
= NULL
;
4017 if (!packet_allocate(&decoded_packet
, MDL
)) {
4018 log_error("do_packet: no memory for incoming packet!");
4021 decoded_packet
->raw
= packet
;
4022 decoded_packet
->packet_length
= len
;
4023 decoded_packet
->client_port
= from_port
;
4024 decoded_packet
->client_addr
= from
;
4025 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
4026 decoded_packet
->haddr
= hfrom
;
4028 if (packet
->hlen
> sizeof packet
->chaddr
) {
4029 packet_dereference(&decoded_packet
, MDL
);
4030 log_info("Discarding packet with bogus hlen.");
4034 /* Allocate packet->options now so it is non-null for all packets */
4035 decoded_packet
->options_valid
= 0;
4036 if (!option_state_allocate (&decoded_packet
->options
, MDL
)) {
4037 packet_dereference(&decoded_packet
, MDL
);
4041 /* If there's an option buffer, try to parse it. */
4042 if (decoded_packet
->packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
4043 if (!parse_options(decoded_packet
)) {
4044 packet_dereference (&decoded_packet
, MDL
);
4048 if (decoded_packet
->options_valid
&&
4049 (op
= lookup_option(&dhcp_universe
,
4050 decoded_packet
->options
,
4051 DHO_DHCP_MESSAGE_TYPE
))) {
4052 struct data_string dp
;
4053 memset(&dp
, 0, sizeof dp
);
4054 evaluate_option_cache(&dp
, decoded_packet
, NULL
, NULL
,
4055 decoded_packet
->options
, NULL
,
4058 decoded_packet
->packet_type
= dp
.data
[0];
4060 decoded_packet
->packet_type
= 0;
4061 data_string_forget(&dp
, MDL
);
4065 if (validate_packet(decoded_packet
) != 0) {
4066 if (decoded_packet
->packet_type
)
4067 dhcp(decoded_packet
);
4069 bootp(decoded_packet
);
4072 /* If the caller kept the packet, they'll have upped the refcnt. */
4073 packet_dereference(&decoded_packet
, MDL
);
4075 #if defined (DEBUG_MEMORY_LEAKAGE)
4076 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4078 dmalloc_outstanding
- previous_outstanding
,
4079 dmalloc_outstanding
, dmalloc_longterm
);
4080 dmalloc_dump_outstanding();
4082 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4088 packet6_len_okay(const char *packet
, int len
) {
4092 if ((packet
[0] == DHCPV6_RELAY_FORW
) ||
4093 (packet
[0] == DHCPV6_RELAY_REPL
)) {
4094 if (len
>= offsetof(struct dhcpv6_relay_packet
, options
)) {
4100 if (len
>= offsetof(struct dhcpv6_packet
, options
)) {
4110 do_packet6(struct interface_info
*interface
, const char *packet
,
4111 int len
, int from_port
, const struct iaddr
*from
,
4112 isc_boolean_t was_unicast
) {
4113 unsigned char msg_type
;
4114 const struct dhcpv6_packet
*msg
;
4115 const struct dhcpv6_relay_packet
*relay
;
4117 const struct dhcpv4_over_dhcpv6_packet
*msg46
;
4119 struct packet
*decoded_packet
;
4120 #if defined (DEBUG_MEMORY_LEAKAGE)
4121 unsigned long previous_outstanding
= dmalloc_outstanding
;
4124 if (!packet6_len_okay(packet
, len
)) {
4125 log_info("do_packet6: "
4126 "short packet from %s port %d, len %d, dropped",
4127 piaddr(*from
), from_port
, len
);
4131 decoded_packet
= NULL
;
4132 if (!packet_allocate(&decoded_packet
, MDL
)) {
4133 log_error("do_packet6: no memory for incoming packet.");
4137 if (!option_state_allocate(&decoded_packet
->options
, MDL
)) {
4138 log_error("do_packet6: no memory for options.");
4139 packet_dereference(&decoded_packet
, MDL
);
4143 /* IPv4 information, already set to 0 */
4144 /* decoded_packet->packet_type = 0; */
4145 /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
4146 /* decoded_packet->circuit_id = NULL; */
4147 /* decoded_packet->circuit_id_len = 0; */
4148 /* decoded_packet->remote_id = NULL; */
4149 /* decoded_packet->remote_id_len = 0; */
4150 decoded_packet
->raw
= (struct dhcp_packet
*)packet
;
4151 decoded_packet
->packet_length
= (unsigned)len
;
4152 decoded_packet
->client_port
= from_port
;
4153 decoded_packet
->client_addr
= *from
;
4154 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
4156 decoded_packet
->unicast
= was_unicast
;
4158 msg_type
= packet
[0];
4159 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
4160 (msg_type
== DHCPV6_RELAY_REPL
)) {
4161 int relaylen
= (int)(offsetof(struct dhcpv6_relay_packet
, options
));
4162 relay
= (const struct dhcpv6_relay_packet
*)packet
;
4163 decoded_packet
->dhcpv6_msg_type
= relay
->msg_type
;
4165 /* relay-specific data */
4166 decoded_packet
->dhcpv6_hop_count
= relay
->hop_count
;
4167 memcpy(&decoded_packet
->dhcpv6_link_address
,
4168 relay
->link_address
, sizeof(relay
->link_address
));
4169 memcpy(&decoded_packet
->dhcpv6_peer_address
,
4170 relay
->peer_address
, sizeof(relay
->peer_address
));
4172 if (!parse_option_buffer(decoded_packet
->options
,
4173 relay
->options
, len
- relaylen
,
4174 &dhcpv6_universe
)) {
4175 /* no logging here, as parse_option_buffer() logs all
4176 cases where it fails */
4177 packet_dereference(&decoded_packet
, MDL
);
4181 } else if ((msg_type
== DHCPV6_DHCPV4_QUERY
) ||
4182 (msg_type
== DHCPV6_DHCPV4_RESPONSE
)) {
4184 (int)(offsetof(struct dhcpv4_over_dhcpv6_packet
, options
));
4185 msg46
= (struct dhcpv4_over_dhcpv6_packet
*)packet
;
4186 decoded_packet
->dhcpv6_msg_type
= msg46
->msg_type
;
4188 /* message-specific data */
4189 memcpy(decoded_packet
->dhcp4o6_flags
,
4191 sizeof(decoded_packet
->dhcp4o6_flags
));
4193 if (!parse_option_buffer(decoded_packet
->options
,
4194 msg46
->options
, len
- msglen
,
4195 &dhcpv6_universe
)) {
4196 /* no logging here, as parse_option_buffer() logs all
4197 cases where it fails */
4198 packet_dereference(&decoded_packet
, MDL
);
4203 int msglen
= (int)(offsetof(struct dhcpv6_packet
, options
));
4204 msg
= (const struct dhcpv6_packet
*)packet
;
4205 decoded_packet
->dhcpv6_msg_type
= msg
->msg_type
;
4207 /* message-specific data */
4208 memcpy(decoded_packet
->dhcpv6_transaction_id
,
4209 msg
->transaction_id
,
4210 sizeof(decoded_packet
->dhcpv6_transaction_id
));
4212 if (!parse_option_buffer(decoded_packet
->options
,
4213 msg
->options
, len
- msglen
,
4214 &dhcpv6_universe
)) {
4215 /* no logging here, as parse_option_buffer() logs all
4216 cases where it fails */
4217 packet_dereference(&decoded_packet
, MDL
);
4222 dhcpv6(decoded_packet
);
4224 packet_dereference(&decoded_packet
, MDL
);
4226 #if defined (DEBUG_MEMORY_LEAKAGE)
4227 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4229 dmalloc_outstanding
- previous_outstanding
,
4230 dmalloc_outstanding
, dmalloc_longterm
);
4231 dmalloc_dump_outstanding();
4233 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4240 pretty_escape(char **dst
, char *dend
, const unsigned char **src
,
4241 const unsigned char *send
)
4245 /* If there aren't as many bytes left as there are in the source
4246 * buffer, don't even bother entering the loop.
4248 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4249 *dst
== NULL
|| *src
== NULL
|| (*dst
>= dend
) || (*src
> send
) ||
4250 ((send
- *src
) > (dend
- *dst
)))
4253 for ( ; *src
< send
; (*src
)++) {
4254 if (!isascii (**src
) || !isprint (**src
)) {
4255 /* Skip trailing NUL. */
4256 if ((*src
+ 1) != send
|| **src
!= '\0') {
4257 if (*dst
+ 4 > dend
)
4260 sprintf(*dst
, "\\%03o",
4265 } else if (**src
== '"' || **src
== '\'' || **src
== '$' ||
4266 **src
== '`' || **src
== '\\' || **src
== '|' ||
4268 if (*dst
+ 2 > dend
)
4277 if (*dst
+ 1 > dend
)
4290 pretty_text(char **dst
, char *dend
, const unsigned char **src
,
4291 const unsigned char *send
, int emit_quotes
)
4295 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4296 *dst
== NULL
|| *src
== NULL
||
4297 ((*dst
+ (emit_quotes
? 2 : 0)) > dend
) || (*src
> send
))
4305 /* dend-1 leaves 1 byte for the closing quote. */
4306 count
= pretty_escape(dst
, dend
- (emit_quotes
? 1 : 0), src
, send
);
4311 if (emit_quotes
&& (*dst
< dend
)) {
4315 /* Includes quote prior to pretty_escape(); */
4323 pretty_dname(char **dst
, char *dend
, const unsigned char *src
,
4324 const unsigned char *send
)
4326 const unsigned char *tend
;
4327 const unsigned char *srcp
= src
;
4331 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4332 *dst
== NULL
|| ((*dst
+ 1) > dend
) || (src
>= send
))
4336 /* Continue loop until end of src buffer. */
4340 /* Consume tag size. */
4344 /* At root, finis. */
4350 /* If the tag exceeds the source buffer, it's illegal.
4351 * This should also trap compression pointers (which should
4352 * not be in these buffers).
4357 /* dend-1 leaves room for a trailing dot and quote. */
4358 status
= pretty_escape(dst
, dend
-1, &srcp
, tend
);
4360 if ((status
== -1) || ((*dst
+ 1) > dend
))
4365 count
+= status
+ 1;
4373 pretty_domain(char **dst
, char *dend
, const unsigned char **src
,
4374 const unsigned char *send
)
4376 const unsigned char *tend
;
4380 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
4381 *dst
== NULL
|| *src
== NULL
||
4382 ((*dst
+ 2) > dend
) || (*src
>= send
))
4389 /* Continue loop until end of src buffer. */
4393 /* Consume tag size. */
4397 /* At root, finis. */
4401 tend
= (*src
) + tsiz
;
4403 /* If the tag exceeds the source buffer, it's illegal.
4404 * This should also trap compression pointers (which should
4405 * not be in these buffers).
4410 /* dend-2 leaves room for a trailing dot and quote. */
4411 status
= pretty_escape(dst
, dend
-2, src
, tend
);
4413 if ((status
== -1) || ((*dst
+ 2) > dend
))
4418 count
+= status
+ 1;
4429 * Add the option identified with the option number and data to the
4433 add_option(struct option_state
*options
,
4434 unsigned int option_num
,
4436 unsigned int data_len
)
4438 struct option_cache
*oc
;
4439 struct option
*option
;
4441 /* INSIST(options != NULL); */
4442 /* INSIST(data != NULL); */
4445 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
4446 &option_num
, 0, MDL
)) {
4447 log_error("Attempting to add unknown option %d.", option_num
);
4452 if (!option_cache_allocate(&oc
, MDL
)) {
4453 log_error("No memory for option cache adding %s (option %d).",
4454 option
->name
, option_num
);
4458 if (!make_const_data(&oc
->expression
,
4464 log_error("No memory for constant data adding %s (option %d).",
4465 option
->name
, option_num
);
4466 option_cache_dereference(&oc
, MDL
);
4470 option_reference(&(oc
->option
), option
, MDL
);
4471 save_option(&dhcp_universe
, options
, oc
);
4472 option_cache_dereference(&oc
, MDL
);
4478 * Checks if received BOOTP/DHCPv4 packet is sane
4480 * @param packet received, decoded packet
4482 * @return 1 if packet is sane, 0 if it is not
4484 int validate_packet(struct packet
*packet
)
4486 struct option_cache
*oc
= NULL
;
4488 oc
= lookup_option (&dhcp_universe
, packet
->options
,
4489 DHO_DHCP_CLIENT_IDENTIFIER
);
4491 /* Let's check if client-identifier is sane */
4492 if (oc
->data
.len
== 0) {
4493 log_debug("Dropped DHCPv4 packet with zero-length client-id");
4496 } else if (oc
->data
.len
== 1) {
4498 * RFC2132, section 9.14 states that minimum length of client-id
4499 * is 2. We will allow single-character client-ids for now (for
4500 * backwards compatibility), but warn the user that support for
4501 * this is against the standard.
4503 log_debug("Accepted DHCPv4 packet with one-character client-id - "
4504 "a future version of ISC DHCP will reject this");
4508 * If hlen is 0 we don't have any identifier, we warn the user
4509 * but continue processing the packet as we can.
4511 if (packet
->raw
->hlen
== 0) {
4512 log_debug("Received DHCPv4 packet without client-id"
4513 " option and empty hlen field.");
4517 /* @todo: Add checks for other received options */
4523 * \brief Parse a vendor option (option 43)
4525 * After the server has parsed most of the options and presented the result
4526 * to the user the user can set the proper vendor option space using
4527 * vendor-option-space in the config file and then cause this routine to be
4528 * called via parse-vendor-option in the config file. This routine will
4529 * then try and find the proper universe for the vendor-option-space and
4530 * parse the vendor option string based on that universe.
4532 * If the information isn't available (no vendor space, no universe for the
4533 * vendor space, no vendor option in the options) or the decode fails we
4534 * simply ignore the option and continue processing.
4536 * \param packet - structure to hold information about the packet being
4538 * \param lease - lease structure
4539 * \param client_state
4540 * \param in_options - The incoming options, we expect to find the
4541 * vendor-option (option 43, containing the string
4542 * to parse) there. We shall attach decoded options
4544 * \param out_options - The options we have added as we process the packet.
4545 * We expect to find the vendor-option-space there and
4546 * use that to find the name of the vendor universe to use
4549 * \return - void as there isn't much we can do about failures.
4551 void parse_vendor_option(packet
, lease
, client_state
, in_options
,
4553 struct packet
*packet
;
4554 struct lease
*lease
;
4555 struct client_state
*client_state
;
4556 struct option_state
*in_options
;
4557 struct option_state
*out_options
;
4558 struct binding_scope
**scope
;
4560 struct option_cache
*oc
= NULL
;
4561 struct data_string name
;
4562 struct option
*option
= NULL
;
4563 unsigned int code
= DHO_VENDOR_ENCAPSULATED_OPTIONS
;
4565 /* check if we are processing a packet, if not we can return */
4566 if ((packet
== NULL
) || (in_options
== NULL
) || (out_options
== NULL
))
4569 /* Do we have any vendor option spaces? */
4570 if (vendor_cfg_option
== NULL
)
4573 /* See if the admin has set a vendor option space name */
4574 oc
= lookup_option(vendor_cfg_option
->universe
,
4575 out_options
, vendor_cfg_option
->code
);
4579 memset(&name
, 0, sizeof(name
));
4580 (void) evaluate_option_cache(&name
, packet
, lease
, client_state
,
4581 in_options
, out_options
, scope
, oc
, MDL
);
4583 /* No name, all done */
4584 if (name
.len
== 0) {
4585 data_string_forget(&name
, MDL
);
4589 /* Get any vendor option information from the request */
4590 oc
= lookup_option(&dhcp_universe
, in_options
, code
);
4592 /* No vendor option, all done */
4593 if ((oc
== NULL
) || (oc
->data
.len
== 0)) {
4594 data_string_forget(&name
, MDL
);
4598 /* Get the proper option to pass to the parse routine */
4599 option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
4602 /* Now that we have the data from the vendor option and a vendor
4603 * option space try to parse things. On success the parsed options
4604 * will be added to the in_options list for future use. A return
4605 * return of 1 indicates success, but not much we can do on error */
4606 (void) parse_encapsulated_suboptions(in_options
, option
,
4607 oc
->data
.data
, oc
->data
.len
,
4609 (const char *)name
.data
);
4611 /* Lastly clean up any left overs */
4612 data_string_forget(&name
, MDL
);
4613 option_dereference(&option
, MDL
);