3 DHCP options parsing and reassembly. */
6 * Copyright (c) 2004-2008 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #define DHCP_OPTION_DATA
37 #include <omapip/omapip_p.h>
40 struct option
*vendor_cfg_option
;
42 static int pretty_text(char **, char *, const unsigned char **,
43 const unsigned char *, int);
44 static int pretty_domain(char **, char *, const unsigned char **,
45 const unsigned char *);
46 static int prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
47 unsigned char *buffer
, unsigned length
,
48 unsigned code
, int terminatep
,
49 struct option_cache
**opp
);
51 /* Parse all available options out of the specified packet. */
53 int parse_options (packet
)
54 struct packet
*packet
;
56 struct option_cache
*op
= (struct option_cache
*)0;
58 /* Allocate a new option state. */
59 if (!option_state_allocate (&packet
-> options
, MDL
)) {
60 packet
-> options_valid
= 0;
64 /* If we don't see the magic cookie, there's nothing to parse. */
65 if (memcmp (packet
-> raw
-> options
, DHCP_OPTIONS_COOKIE
, 4)) {
66 packet
-> options_valid
= 0;
70 /* Go through the options field, up to the end of the packet
72 if (!parse_option_buffer (packet
-> options
,
73 &packet
-> raw
-> options
[4],
74 (packet
-> packet_length
-
75 DHCP_FIXED_NON_UDP
- 4),
78 /* STSN servers have a bug where they send a mangled
79 domain-name option, and whatever is beyond that in
80 the packet is junk. Microsoft clients accept this,
81 which is probably why whoever implemented the STSN
82 server isn't aware of the problem yet. To work around
83 this, we will accept corrupt packets from the server if
84 they contain a valid DHCP_MESSAGE_TYPE option, but
85 will not accept any corrupt client packets (the ISC DHCP
86 server is sufficiently widely used that it is probably
87 beneficial for it to be picky) and will not accept
88 packets whose type can't be determined. */
90 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
91 DHO_DHCP_MESSAGE_TYPE
))) {
92 if (!op
-> data
.data
||
93 (op
-> data
.data
[0] != DHCPOFFER
&&
94 op
-> data
.data
[0] != DHCPACK
&&
95 op
-> data
.data
[0] != DHCPNAK
))
101 /* If we parsed a DHCP Option Overload option, parse more
102 options out of the buffer(s) containing them. */
103 if ((op
= lookup_option (&dhcp_universe
, packet
-> options
,
104 DHO_DHCP_OPTION_OVERLOAD
))) {
105 if (op
-> data
.data
[0] & 1) {
106 if (!parse_option_buffer
108 (unsigned char *)packet
-> raw
-> file
,
109 sizeof packet
-> raw
-> file
,
113 if (op
-> data
.data
[0] & 2) {
114 if (!parse_option_buffer
116 (unsigned char *)packet
-> raw
-> sname
,
117 sizeof packet
-> raw
-> sname
,
122 packet
-> options_valid
= 1;
126 /* Parse options out of the specified buffer, storing addresses of option
127 * values in packet->options.
129 int parse_option_buffer (options
, buffer
, length
, universe
)
130 struct option_state
*options
;
131 const unsigned char *buffer
;
133 struct universe
*universe
;
135 unsigned len
, offset
;
137 struct option_cache
*op
= NULL
, *nop
= NULL
;
138 struct buffer
*bp
= (struct buffer
*)0;
139 struct option
*option
= NULL
;
141 if (!buffer_allocate (&bp
, length
, MDL
)) {
142 log_error ("no memory for option buffer.");
145 memcpy (bp
-> data
, buffer
, length
);
148 (offset
+ universe
->tag_size
) <= length
&&
149 (code
= universe
->get_tag(buffer
+ offset
)) != universe
->end
; ) {
150 offset
+= universe
->tag_size
;
152 /* Pad options don't have a length - just skip them. */
156 /* Don't look for length if the buffer isn't that big. */
157 if ((offset
+ universe
->length_size
) > length
) {
162 /* All other fields (except PAD and END handled above)
163 * have a length field, unless it's a DHCPv6 zero-length
164 * options space (eg any of the enterprise-id'd options).
166 * Zero-length-size option spaces basically consume the
167 * entire options buffer, so have at it.
169 if (universe
->get_length
!= NULL
)
170 len
= universe
->get_length(buffer
+ offset
);
171 else if (universe
->length_size
== 0)
172 len
= length
- universe
->tag_size
;
174 log_fatal("Improperly configured option space(%s): "
175 "may not have a nonzero length size "
176 "AND a NULL get_length function.",
179 /* Silence compiler warnings. */
183 offset
+= universe
->length_size
;
185 option_code_hash_lookup(&option
, universe
->code_hash
, &code
,
188 /* If the length is outrageous, the options are bad. */
189 if (offset
+ len
> length
) {
191 log_error ("parse_option_buffer: option %s (%u:%u) %s.",
192 option
? option
->name
: "<unknown>",
193 code
, len
, "larger than buffer");
194 buffer_dereference (&bp
, MDL
);
198 /* If the option contains an encapsulation, parse it. If
199 the parse fails, or the option isn't an encapsulation (by
200 far the most common case), or the option isn't entirely
201 an encapsulation, keep the raw data as well. */
203 (option
->format
[0] == 'e' ||
204 option
->format
[0] == 'E') &&
205 (parse_encapsulated_suboptions(options
, option
,
206 bp
->data
+ offset
, len
,
208 op
= lookup_option(universe
, options
, code
);
210 if (op
!= NULL
&& universe
->concat_duplicates
) {
211 struct data_string
new;
212 memset(&new, 0, sizeof new);
213 if (!buffer_allocate(&new.buffer
,
216 log_error("parse_option_buffer: "
218 buffer_dereference(&bp
, MDL
);
221 /* Copy old option to new data object. */
222 memcpy(new.buffer
->data
, op
->data
.data
,
224 /* Concat new option behind old. */
225 memcpy(new.buffer
->data
+ op
->data
.len
,
226 bp
->data
+ offset
, len
);
227 new.len
= op
->data
.len
+ len
;
228 new.data
= new.buffer
->data
;
229 /* Save new concat'd object. */
230 data_string_forget(&op
->data
, MDL
);
231 data_string_copy(&op
->data
, &new, MDL
);
232 data_string_forget(&new, MDL
);
233 } else if (op
!= NULL
) {
234 /* We must append this statement onto the
237 while (op
->next
!= NULL
)
240 if (!option_cache_allocate(&nop
, MDL
)) {
241 log_error("parse_option_buffer: "
243 buffer_dereference(&bp
, MDL
);
247 option_reference(&nop
->option
, op
->option
, MDL
);
249 nop
->data
.buffer
= NULL
;
250 buffer_reference(&nop
->data
.buffer
, bp
, MDL
);
251 nop
->data
.data
= bp
->data
+ offset
;
254 option_cache_reference(&op
->next
, nop
, MDL
);
255 option_cache_dereference(&nop
, MDL
);
257 save_option_buffer(universe
, options
, bp
,
258 bp
->data
+ offset
, len
,
262 option_dereference(&option
, MDL
);
265 buffer_dereference (&bp
, MDL
);
269 /* If an option in an option buffer turns out to be an encapsulation,
270 figure out what to do. If we don't know how to de-encapsulate it,
271 or it's not well-formed, return zero; otherwise, return 1, indicating
272 that we succeeded in de-encapsulating it. */
274 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
278 struct universe
*universe
= (struct universe
*)0;
280 /* Look for the E option in the option format. */
281 s
= strchr (eopt
-> format
, 'E');
283 log_error ("internal encapsulation format error 1.");
286 /* Look for the universe name in the option format. */
287 t
= strchr (++s
, '.');
288 /* If there was no trailing '.', or there's something after the
289 trailing '.', the option is bogus and we can't use it. */
291 log_error ("internal encapsulation format error 2.");
294 if (t
== s
&& uname
) {
295 for (i
= 0; i
< universe_count
; i
++) {
296 if (!strcmp (universes
[i
] -> name
, uname
)) {
297 universe
= universes
[i
];
302 for (i
= 0; i
< universe_count
; i
++) {
303 if (strlen (universes
[i
] -> name
) == t
- s
&&
304 !memcmp (universes
[i
] -> name
,
305 s
, (unsigned)(t
- s
))) {
306 universe
= universes
[i
];
314 /* If an option in an option buffer turns out to be an encapsulation,
315 figure out what to do. If we don't know how to de-encapsulate it,
316 or it's not well-formed, return zero; otherwise, return 1, indicating
317 that we succeeded in de-encapsulating it. */
319 int parse_encapsulated_suboptions (struct option_state
*options
,
321 const unsigned char *buffer
,
322 unsigned len
, struct universe
*eu
,
326 struct universe
*universe
= find_option_universe (eopt
, uname
);
328 /* If we didn't find the universe, we can't do anything with it
329 right now (e.g., we can't decode vendor options until we've
330 decoded the packet and executed the scopes that it matches). */
334 /* If we don't have a decoding function for it, we can't decode
336 if (!universe
-> decode
)
339 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
341 /* If there is stuff before the suboptions, we have to keep it. */
342 if (eopt
-> format
[0] != 'E')
344 /* Otherwise, return the status of the decode function. */
348 int fqdn_universe_decode (struct option_state
*options
,
349 const unsigned char *buffer
,
350 unsigned length
, struct universe
*u
)
352 struct buffer
*bp
= (struct buffer
*)0;
354 /* FQDN options have to be at least four bytes long. */
358 /* Save the contents of the option in a buffer. */
359 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
360 log_error ("no memory for option buffer.");
363 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
365 if (buffer
[0] & 4) /* encoded */
369 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
370 bp
->data
, 1, FQDN_ENCODED
, 0)) {
372 buffer_dereference (&bp
, MDL
);
376 if (buffer
[0] & 1) /* server-update */
380 if (buffer
[0] & 2) /* no-client-update */
385 /* XXX Ideally we should store the name in DNS format, so if the
386 XXX label isn't in DNS format, we convert it to DNS format,
387 XXX rather than converting labels specified in DNS format to
388 XXX the plain ASCII representation. But that's hard, so
391 /* Not encoded using DNS format? */
392 if (!bp
-> data
[0]) {
395 /* Some broken clients NUL-terminate this option. */
396 if (buffer
[length
- 1] == 0) {
401 /* Determine the length of the hostname component of the
402 name. If the name contains no '.' character, it
403 represents a non-qualified label. */
404 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
407 /* Note: If the client sends a FQDN, the first '.' will
408 be used as a NUL terminator for the hostname. */
409 if (i
&& (!save_option_buffer(&fqdn_universe
, options
, bp
,
413 /* Note: If the client sends a single label, the
414 FQDN_DOMAINNAME option won't be set. */
415 if (length
> 4 + i
&&
416 (!save_option_buffer(&fqdn_universe
, options
, bp
,
417 &bp
-> data
[6 + i
], length
- 4 - i
,
418 FQDN_DOMAINNAME
, 1)))
420 /* Also save the whole name. */
422 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
423 &bp
-> data
[5], length
- 3,
429 unsigned total_len
= 0;
430 unsigned first_len
= 0;
436 while (s
< &bp
-> data
[0] + length
+ 2) {
439 log_info ("fancy bits in fqdn option");
446 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
447 log_info ("fqdn tag longer than buffer");
451 if (first_len
== 0) {
457 total_len
+= len
+ 1;
460 /* We wind up with a length that's one too many because
461 we shouldn't increment for the last label, but there's
462 no way to tell we're at the last label until we exit
468 first_len
= total_len
;
472 !save_option_buffer(&fqdn_universe
, options
, bp
,
473 &bp
-> data
[6], first_len
,
476 if (total_len
> 0 && first_len
!= total_len
) {
477 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
478 &bp
->data
[6 + first_len
],
479 total_len
- first_len
,
484 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
485 &bp
-> data
[6], total_len
,
490 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
492 FQDN_NO_CLIENT_UPDATE
, 0))
494 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
496 FQDN_SERVER_UPDATE
, 0))
499 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
503 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
508 buffer_dereference (&bp
, MDL
);
513 * Load all options into a buffer, and then split them out into the three
514 * separate fields in the dhcp packet (options, file, and sname) where
515 * options can be stored.
518 cons_options(struct packet
*inpacket
, struct dhcp_packet
*outpacket
,
519 struct lease
*lease
, struct client_state
*client_state
,
520 int mms
, struct option_state
*in_options
,
521 struct option_state
*cfg_options
,
522 struct binding_scope
**scope
,
523 int overload_avail
, int terminate
, int bootpp
,
524 struct data_string
*prl
, const char *vuname
)
526 #define PRIORITY_COUNT 300
527 unsigned priority_list
[PRIORITY_COUNT
];
529 unsigned char buffer
[4096], agentopts
[1024];
531 unsigned mb_size
= 0, mb_max
= 0;
532 unsigned option_size
= 0, agent_size
= 0;
535 struct option_cache
*op
;
536 struct data_string ds
;
538 int overload_used
= 0;
539 int of1
= 0, of2
= 0;
541 memset(&ds
, 0, sizeof ds
);
544 * If there's a Maximum Message Size option in the incoming packet
545 * and no alternate maximum message size has been specified, or
546 * if the one specified in the packet is shorter than the
547 * alternative, take the one in the packet.
551 (op
= lookup_option(&dhcp_universe
, inpacket
->options
,
552 DHO_DHCP_MAX_MESSAGE_SIZE
))) {
553 evaluate_option_cache(&ds
, inpacket
,
554 lease
, client_state
, in_options
,
555 cfg_options
, scope
, op
, MDL
);
556 if (ds
.len
>= sizeof (u_int16_t
)) {
557 i
= getUShort(ds
.data
);
558 if(!mms
|| (i
< mms
))
561 data_string_forget(&ds
, MDL
);
565 * If the client has provided a maximum DHCP message size,
566 * use that, up to the MTU limit. Otherwise, if it's BOOTP,
567 * only 64 bytes; otherwise use up to the minimum IP MTU size
570 * XXX if a BOOTP client specifies a max message size, we will
574 if (mms
< DHCP_MTU_MIN
)
575 /* Enforce minimum packet size, per RFC 2132 */
576 mb_size
= DHCP_MIN_OPTION_LEN
;
577 else if (mms
> DHCP_MTU_MAX
)
579 * TODO: Packets longer than 1500 bytes really
580 * should be allowed, but it requires upstream
581 * changes to the way the packet is allocated. For
582 * now, we forbid them. They won't be needed very
585 mb_size
= DHCP_MAX_OPTION_LEN
;
587 mb_size
= mms
- DHCP_FIXED_LEN
;
590 if (inpacket
!= NULL
&&
591 (inpacket
->packet_length
- DHCP_FIXED_LEN
>= 64))
592 mb_size
= inpacket
->packet_length
- DHCP_FIXED_LEN
;
594 mb_size
= DHCP_MIN_OPTION_LEN
;
597 * If answering a client message, see whether any relay agent
598 * options were included with the message. If so, save them
599 * to copy back in later, and make space in the main buffer
600 * to accommodate them
602 if (client_state
== NULL
) {
603 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
605 agent_size
= store_options(NULL
, agentopts
, 0,
607 inpacket
, lease
, client_state
,
608 in_options
, cfg_options
, scope
,
609 priority_list
, priority_len
,
612 mb_size
+= agent_size
;
613 if (mb_size
> DHCP_MAX_OPTION_LEN
)
614 mb_size
= DHCP_MAX_OPTION_LEN
;
618 * Set offsets for buffer data to be copied into filename
619 * and servername fields
623 if (overload_avail
& 1) {
625 mb_max
+= DHCP_FILE_LEN
;
628 if (overload_avail
& 2) {
630 mb_max
+= DHCP_SNAME_LEN
;
634 * Preload the option priority list with protocol-mandatory options.
635 * This effectively gives these options the highest priority.
638 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
639 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
640 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
641 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
642 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
643 priority_list
[priority_len
++] = DHO_ASSOCIATED_IP
;
645 if (prl
!= NULL
&& prl
->len
> 0) {
646 if ((op
= lookup_option(&dhcp_universe
, cfg_options
,
647 DHO_SUBNET_SELECTION
))) {
648 if (priority_len
< PRIORITY_COUNT
)
649 priority_list
[priority_len
++] =
650 DHO_SUBNET_SELECTION
;
653 data_string_truncate(prl
, (PRIORITY_COUNT
- priority_len
));
655 for (i
= 0; i
< prl
->len
; i
++) {
657 * Prevent client from changing order of delivery
658 * of relay agent information option.
660 if (prl
->data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
661 priority_list
[priority_len
++] = prl
->data
[i
];
665 * If the client doesn't request the FQDN option explicitly,
666 * to indicate priority, consider it lowest priority. Fit
667 * in the packet if there is space. Note that the option
668 * may only be included if the client supplied one.
670 if ((priority_len
< PRIORITY_COUNT
) &&
671 (lookup_option(&dhcp_universe
, inpacket
->options
,
673 priority_list
[priority_len
++] = DHO_FQDN
;
676 * Some DHCP Servers will give the subnet-mask option if
677 * it is not on the parameter request list - so some client
678 * implementations have come to rely on this - so we will
679 * also make sure we supply this, at lowest priority.
681 * This is only done in response to DHCPDISCOVER or
682 * DHCPREQUEST messages, to avoid providing the option on
683 * DHCPINFORM or DHCPLEASEQUERY responses (if the client
684 * didn't request it).
686 if ((priority_len
< PRIORITY_COUNT
) &&
687 ((inpacket
->packet_type
== DHCPDISCOVER
) ||
688 (inpacket
->packet_type
== DHCPREQUEST
)))
689 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
692 * First, hardcode some more options that ought to be
693 * sent first...these are high priority to have in the
696 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
697 priority_list
[priority_len
++] = DHO_ROUTERS
;
698 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
699 priority_list
[priority_len
++] = DHO_HOST_NAME
;
700 priority_list
[priority_len
++] = DHO_FQDN
;
703 * Append a list of the standard DHCP options from the
704 * standard DHCP option space. Actually, if a site
705 * option space hasn't been specified, we wind up
706 * treating the dhcp option space as the site option
707 * space, and the first for loop is skipped, because
708 * it's slightly more general to do it this way,
709 * taking the 1Q99 DHCP futures work into account.
711 if (cfg_options
->site_code_min
) {
712 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
713 hash
= cfg_options
->universes
[dhcp_universe
.index
];
715 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
716 op
= (struct option_cache
*)(pp
->car
);
717 if (op
->option
->code
<
718 cfg_options
->site_code_min
&&
719 priority_len
< PRIORITY_COUNT
&&
720 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
721 priority_list
[priority_len
++] =
729 * Now cycle through the site option space, or if there
730 * is no site option space, we'll be cycling through the
733 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
734 hash
= cfg_options
->universes
[cfg_options
->site_universe
];
736 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
737 op
= (struct option_cache
*)(pp
->car
);
738 if (op
->option
->code
>=
739 cfg_options
->site_code_min
&&
740 priority_len
< PRIORITY_COUNT
&&
741 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
742 priority_list
[priority_len
++] =
748 * Put any spaces that are encapsulated on the list,
749 * sort out whether they contain values later.
751 for (i
= 0; i
< cfg_options
->universe_count
; i
++) {
752 if (universes
[i
]->enc_opt
&&
753 priority_len
< PRIORITY_COUNT
&&
754 universes
[i
]->enc_opt
->universe
== &dhcp_universe
) {
755 if (universes
[i
]->enc_opt
->code
!=
756 DHO_DHCP_AGENT_OPTIONS
)
757 priority_list
[priority_len
++] =
758 universes
[i
]->enc_opt
->code
;
763 * The vendor option space can't stand on its own, so always
764 * add it to the list.
766 if (priority_len
< PRIORITY_COUNT
)
767 priority_list
[priority_len
++] =
768 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
771 /* Put the cookie up front... */
772 memcpy(buffer
, DHCP_OPTIONS_COOKIE
, 4);
775 /* Copy the options into the big buffer... */
776 option_size
= store_options(&overload_used
, buffer
, index
, mb_max
,
777 inpacket
, lease
, client_state
,
778 in_options
, cfg_options
, scope
,
779 priority_list
, priority_len
,
780 of1
, of2
, terminate
, vuname
);
782 /* If store_options() failed */
783 if (option_size
== 0)
786 /* How much was stored in the main buffer? */
787 index
+= option_size
;
790 * If we're going to have to overload, store the overload
794 if (mb_size
- agent_size
- index
< 3)
797 buffer
[index
++] = DHO_DHCP_OPTION_OVERLOAD
;
799 buffer
[index
++] = overload_used
;
801 if (overload_used
& 1)
802 memcpy(outpacket
->file
, &buffer
[of1
], DHCP_FILE_LEN
);
804 if (overload_used
& 2)
805 memcpy(outpacket
->sname
, &buffer
[of2
], DHCP_SNAME_LEN
);
808 /* Now copy in preserved agent options, if any */
810 if (mb_size
- index
>= agent_size
) {
811 memcpy(&buffer
[index
], agentopts
, agent_size
);
814 log_error("Unable to store relay agent information "
818 /* Tack a DHO_END option onto the packet if we need to. */
820 buffer
[index
++] = DHO_END
;
822 /* Copy main buffer into the options buffer of the packet */
823 memcpy(outpacket
->options
, buffer
, index
);
825 /* Figure out the length. */
826 length
= DHCP_FIXED_NON_UDP
+ index
;
831 * XXX: We currently special case collecting VSIO options.
832 * We should be able to handle this in a more generic fashion, by
833 * including any encapsulated options that are present and desired.
834 * This will look something like the VSIO handling VSIO code.
835 * We may also consider handling the ORO-like options within
836 * encapsulated spaces.
846 vsio_options(struct option_cache
*oc
,
847 struct packet
*packet
,
848 struct lease
*dummy_lease
,
849 struct client_state
*dummy_client_state
,
850 struct option_state
*dummy_opt_state
,
851 struct option_state
*opt_state
,
852 struct binding_scope
**dummy_binding_scope
,
853 struct universe
*universe
,
854 void *void_vsio_state
) {
855 struct vsio_state
*vs
= (struct vsio_state
*)void_vsio_state
;
856 struct data_string ds
;
859 memset(&ds
, 0, sizeof(ds
));
860 if (evaluate_option_cache(&ds
, packet
, NULL
,
861 NULL
, opt_state
, NULL
,
862 &global_scope
, oc
, MDL
)) {
863 total_len
= ds
.len
+ universe
->tag_size
+ universe
->length_size
;
864 if (total_len
<= (vs
->buflen
- vs
->bufpos
)) {
865 if (universe
->tag_size
== 1) {
866 vs
->buf
[vs
->bufpos
++] = oc
->option
->code
;
867 } else if (universe
->tag_size
== 2) {
868 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
871 } else if (universe
->tag_size
== 4) {
872 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
876 if (universe
->length_size
== 1) {
877 vs
->buf
[vs
->bufpos
++] = ds
.len
;
878 } else if (universe
->length_size
== 2) {
879 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
882 } else if (universe
->length_size
== 4) {
883 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
887 memcpy(vs
->buf
+ vs
->bufpos
, ds
.data
, ds
.len
);
888 vs
->bufpos
+= ds
.len
;
890 log_debug("No space for option %d in VSIO space %s.",
891 oc
->option
->code
, universe
->name
);
893 data_string_forget(&ds
, MDL
);
895 log_error("Error evaluating option %d in VSIO space %s.",
896 oc
->option
->code
, universe
->name
);
901 * Stores the options from the DHCPv6 universe into the buffer given.
903 * Required options are given as a 0-terminated list of option codes.
904 * Once those are added, the ORO is consulted.
908 store_options6(char *buf
, int buflen
,
909 struct option_state
*opt_state
,
910 struct packet
*packet
,
911 const int *required_opts
,
912 struct data_string
*oro
) {
914 struct option_cache
*oc
;
916 struct data_string ds
;
920 int in_required_opts
;
921 int vsio_option_code
;
923 struct vsio_state vs
;
930 * Find the option code for the VSIO universe.
932 vsio_option_code
= 0;
933 o
= vsio_universe
.enc_opt
;
935 if (o
->universe
== &dhcpv6_universe
) {
936 vsio_option_code
= o
->code
;
939 o
= o
->universe
->enc_opt
;
941 if (vsio_option_code
== 0) {
942 log_fatal("No VSIO option code found.");
945 if (required_opts
!= NULL
) {
946 for (i
=0; required_opts
[i
] != 0; i
++) {
947 if (required_opts
[i
] == vsio_option_code
) {
951 oc
= lookup_option(&dhcpv6_universe
,
952 opt_state
, required_opts
[i
]);
956 memset(&ds
, 0, sizeof(ds
));
957 for (; oc
!= NULL
; oc
= oc
->next
) {
958 if (evaluate_option_cache(&ds
, packet
, NULL
,
964 tmp
= (unsigned char *)buf
;
970 putUShort(tmp
+2, ds
.len
);
972 memcpy(tmp
+4, ds
.data
, ds
.len
);
973 /* update position */
974 bufpos
+= (4 + ds
.len
);
976 log_debug("No space for "
980 data_string_forget(&ds
, MDL
);
982 log_error("Error evaluating option %d",
992 oro_size
= oro
->len
/ 2;
994 for (i
=0; i
<oro_size
; i
++) {
995 memcpy(&code
, oro
->data
+(i
*2), 2);
999 * See if we've already included this option because
1002 in_required_opts
= 0;
1003 if (required_opts
!= NULL
) {
1004 for (j
=0; required_opts
[j
] != 0; j
++) {
1005 if (required_opts
[j
] == code
) {
1006 in_required_opts
= 1;
1011 if (in_required_opts
) {
1016 * See if this is the VSIO option.
1018 if (code
== vsio_option_code
) {
1023 * Not already added, find this option.
1025 oc
= lookup_option(&dhcpv6_universe
, opt_state
, code
);
1026 memset(&ds
, 0, sizeof(ds
));
1027 for (; oc
!= NULL
; oc
= oc
->next
) {
1028 if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1030 &global_scope
, oc
, MDL
)) {
1031 if ((ds
.len
+ 4) <= (buflen
- bufpos
)) {
1032 tmp
= (unsigned char *)buf
+ bufpos
;
1034 putUShort(tmp
, code
);
1036 putUShort(tmp
+2, ds
.len
);
1038 memcpy(tmp
+4, ds
.data
, ds
.len
);
1039 /* update position */
1040 bufpos
+= (4 + ds
.len
);
1042 log_debug("No space for option %d",
1045 data_string_forget(&ds
, MDL
);
1047 log_error("Error evaluating option %d", code
);
1053 for (i
=0; i
< opt_state
->universe_count
; i
++) {
1054 if (opt_state
->universes
[i
] != NULL
) {
1055 o
= universes
[i
]->enc_opt
;
1057 (o
->universe
== &vsio_universe
)) {
1059 * Add the data from this VSIO option.
1063 vs
.bufpos
= bufpos
+8;
1064 option_space_foreach(packet
, NULL
,
1073 * If there was actually data here,
1076 if (vs
.bufpos
> bufpos
+8) {
1077 tmp
= (unsigned char *)buf
+
1082 vs
.bufpos
-bufpos
-4);
1083 putULong(tmp
+4, o
->code
);
1096 * Store all the requested options into the requested buffer.
1097 * XXX: ought to be static
1100 store_options(int *ocount
,
1101 unsigned char *buffer
, unsigned index
, unsigned buflen
,
1102 struct packet
*packet
, struct lease
*lease
,
1103 struct client_state
*client_state
,
1104 struct option_state
*in_options
,
1105 struct option_state
*cfg_options
,
1106 struct binding_scope
**scope
,
1107 unsigned *priority_list
, int priority_len
,
1108 unsigned first_cutoff
, int second_cutoff
, int terminate
,
1111 int bufix
= 0, six
= 0, tix
= 0;
1115 int bufend
, sbufend
;
1116 struct data_string od
;
1117 struct option_cache
*oc
;
1118 struct option
*option
= NULL
;
1122 * These arguments are relative to the start of the buffer, so
1123 * reduce them by the current buffer index, and advance the
1124 * buffer pointer to where we're going to start writing.
1126 buffer
= &buffer
[index
];
1129 first_cutoff
-= index
;
1131 second_cutoff
-= index
;
1133 /* Calculate the start and end of each section of the buffer */
1134 bufend
= sbufend
= buflen
;
1136 if (first_cutoff
>= buflen
)
1137 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
1138 bufend
= first_cutoff
;
1140 if (second_cutoff
) {
1141 if (second_cutoff
>= buflen
)
1142 log_fatal("%s:%d:store_options: Invalid second cutoff.",
1144 sbufend
= second_cutoff
;
1146 } else if (second_cutoff
) {
1147 if (second_cutoff
>= buflen
)
1148 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
1149 bufend
= second_cutoff
;
1152 memset (&od
, 0, sizeof od
);
1154 /* Eliminate duplicate options from the parameter request list.
1155 * Enforce RFC-mandated ordering of options that are present.
1157 for (i
= 0; i
< priority_len
- 1; i
++) {
1158 /* Eliminate duplicates. */
1160 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
1162 priority_list
[ix
- tto
] =
1164 if (priority_list
[i
] == priority_list
[ix
]) {
1170 /* Enforce ordering of SUBNET_MASK options, according to
1171 * RFC2132 Section 3.3:
1173 * If both the subnet mask and the router option are
1174 * specified in a DHCP reply, the subnet mask option MUST
1177 * This guidance does not specify what to do if the client
1178 * PRL explicitly requests the options out of order, it is
1179 * a general statement.
1181 if (priority_list
[i
] == DHO_SUBNET_MASK
) {
1182 for (ix
= i
- 1 ; ix
>= 0 ; ix
--) {
1183 if (priority_list
[ix
] == DHO_ROUTERS
) {
1185 priority_list
[ix
] = DHO_SUBNET_MASK
;
1186 priority_list
[i
] = DHO_ROUTERS
;
1193 /* Copy out the options in the order that they appear in the
1195 for (i
= 0; i
< priority_len
; i
++) {
1196 /* Number of bytes left to store (some may already
1197 have been stored by a previous pass). */
1199 int optstart
, soptstart
, toptstart
;
1201 int have_encapsulation
= 0;
1202 struct data_string encapsulation
;
1205 memset (&encapsulation
, 0, sizeof encapsulation
);
1206 have_encapsulation
= 0;
1209 option_dereference(&option
, MDL
);
1211 /* Code for next option to try to store. */
1212 code
= priority_list
[i
];
1214 /* Look up the option in the site option space if the code
1215 is above the cutoff, otherwise in the DHCP option space. */
1216 if (code
>= cfg_options
-> site_code_min
)
1217 u
= universes
[cfg_options
-> site_universe
];
1221 oc
= lookup_option (u
, cfg_options
, code
);
1223 if (oc
&& oc
->option
)
1224 option_reference(&option
, oc
->option
, MDL
);
1226 option_code_hash_lookup(&option
, u
->code_hash
, &code
, 0, MDL
);
1228 /* If it's a straight encapsulation, and the user supplied a
1229 * value for the entire option, use that. Otherwise, search
1230 * the encapsulated space.
1232 * If it's a limited encapsulation with preceding data, and the
1233 * user supplied values for the preceding bytes, search the
1234 * encapsulated space.
1236 if ((option
!= NULL
) &&
1237 (((oc
== NULL
) && (option
->format
[0] == 'E')) ||
1238 ((oc
!= NULL
) && (option
->format
[0] == 'e')))) {
1240 struct option_cache
*tmp
;
1241 struct data_string name
;
1243 s
= strchr (option
->format
, 'E');
1245 t
= strchr (++s
, '.');
1247 memset (&name
, 0, sizeof name
);
1249 /* A zero-length universe name means the vendor
1250 option space, if one is defined. */
1252 if (vendor_cfg_option
) {
1253 tmp
= lookup_option (vendor_cfg_option
-> universe
,
1255 vendor_cfg_option
-> code
);
1257 evaluate_option_cache (&name
, packet
, lease
,
1262 } else if (vuname
) {
1263 name
.data
= (unsigned char *)s
;
1264 name
.len
= strlen (s
);
1267 name
.data
= (unsigned char *)s
;
1271 /* If we found a universe, and there are options configured
1272 for that universe, try to encapsulate it. */
1274 have_encapsulation
=
1275 (option_space_encapsulate
1276 (&encapsulation
, packet
, lease
, client_state
,
1277 in_options
, cfg_options
, scope
, &name
));
1278 data_string_forget (&name
, MDL
);
1283 /* In order to avoid memory leaks, we have to get to here
1284 with any option cache that we allocated in tmp not being
1285 referenced by tmp, and whatever option cache is referenced
1286 by oc being an actual reference. lookup_option doesn't
1287 generate a reference (this needs to be fixed), so the
1288 preceding goop ensures that if we *didn't* generate a new
1289 option cache, oc still winds up holding an actual reference. */
1291 /* If no data is available for this option, skip it. */
1292 if (!oc
&& !have_encapsulation
) {
1296 /* Find the value of the option... */
1299 evaluate_option_cache (&od
, packet
,
1300 lease
, client_state
, in_options
,
1301 cfg_options
, scope
, oc
, MDL
);
1303 /* If we have encapsulation for this option, and an oc
1304 * lookup succeeded, but the evaluation failed, it is
1305 * either because this is a complex atom (atoms before
1306 * E on format list) and the top half of the option is
1307 * not configured, or this is a simple encapsulated
1308 * space and the evaluator is giving us a NULL. Prefer
1309 * the evaluator's opinion over the subspace.
1312 data_string_forget (&encapsulation
, MDL
);
1313 data_string_forget (&od
, MDL
);
1318 /* We should now have a constant length for the option. */
1320 if (have_encapsulation
) {
1321 length
+= encapsulation
.len
;
1323 /* od.len can be nonzero if we got here without an
1324 * oc (cache lookup failed), but did have an encapsulated
1325 * simple encapsulation space.
1328 data_string_copy (&od
, &encapsulation
, MDL
);
1329 data_string_forget (&encapsulation
, MDL
);
1331 struct buffer
*bp
= (struct buffer
*)0;
1332 if (!buffer_allocate (&bp
, length
, MDL
)) {
1333 option_cache_dereference (&oc
, MDL
);
1334 data_string_forget (&od
, MDL
);
1335 data_string_forget (&encapsulation
, MDL
);
1338 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
1339 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
1341 data_string_forget (&od
, MDL
);
1342 data_string_forget (&encapsulation
, MDL
);
1343 od
.data
= &bp
-> data
[0];
1344 buffer_reference (&od
.buffer
, bp
, MDL
);
1345 buffer_dereference (&bp
, MDL
);
1351 /* Do we add a NUL? */
1352 if (terminate
&& option
&& format_has_text(option
->format
)) {
1359 /* Try to store the option. */
1361 /* If the option's length is more than 255, we must store it
1362 in multiple hunks. Store 255-byte hunks first. However,
1363 in any case, if the option data will cross a buffer
1364 boundary, split it across that boundary. */
1376 unsigned incr
= length
;
1378 unsigned char *base
;
1380 /* Try to fit it in the options buffer. */
1382 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
1383 (bufix
+ 2 + length
< bufend
)) ||
1384 (bufix
+ 5 + length
< bufend
))) {
1387 /* Try to fit it in the second buffer. */
1388 } else if (!splitup
&& first_cutoff
&&
1389 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
1390 base
= &buffer
[first_cutoff
];
1392 /* Try to fit it in the third buffer. */
1393 } else if (!splitup
&& second_cutoff
&&
1394 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
1395 base
= &buffer
[second_cutoff
];
1397 /* Split the option up into the remaining space. */
1401 /* Use any remaining options space. */
1402 if (bufix
+ 6 < bufend
) {
1403 incr
= bufend
- bufix
- 5;
1406 /* Use any remaining first_cutoff space. */
1407 } else if (first_cutoff
&&
1408 (first_cutoff
+ six
+ 4 < sbufend
)) {
1409 incr
= sbufend
- (first_cutoff
+ six
) - 3;
1410 base
= &buffer
[first_cutoff
];
1412 /* Use any remaining second_cutoff space. */
1413 } else if (second_cutoff
&&
1414 (second_cutoff
+ tix
+ 4 < buflen
)) {
1415 incr
= buflen
- (second_cutoff
+ tix
) - 3;
1416 base
= &buffer
[second_cutoff
];
1418 /* Give up, roll back this option. */
1432 /* Everything looks good - copy it in! */
1434 base
[*pix
+ 1] = (unsigned char)incr
;
1435 if (tto
&& incr
== length
) {
1437 memcpy (base
+ *pix
+ 2,
1438 od
.data
+ ix
, (unsigned)(incr
- 1));
1439 base
[*pix
+ 2 + incr
- 1] = 0;
1441 memcpy (base
+ *pix
+ 2,
1442 od
.data
+ ix
, (unsigned)incr
);
1448 data_string_forget (&od
, MDL
);
1452 option_dereference(&option
, MDL
);
1454 /* If we can overload, and we have, then PAD and END those spaces. */
1455 if (first_cutoff
&& six
) {
1456 if ((first_cutoff
+ six
+ 1) < sbufend
)
1457 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1458 sbufend
- (first_cutoff
+ six
+ 1));
1459 else if (first_cutoff
+ six
>= sbufend
)
1460 log_fatal("Second buffer overflow in overloaded options.");
1462 buffer
[first_cutoff
+ six
] = DHO_END
;
1464 *ocount
|= 1; /* So that caller knows there's data there. */
1467 if (second_cutoff
&& tix
) {
1468 if (second_cutoff
+ tix
+ 1 < buflen
) {
1469 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1470 buflen
- (second_cutoff
+ tix
+ 1));
1471 } else if (second_cutoff
+ tix
>= buflen
)
1472 log_fatal("Third buffer overflow in overloaded options.");
1474 buffer
[second_cutoff
+ tix
] = DHO_END
;
1476 *ocount
|= 2; /* So that caller knows there's data there. */
1479 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1480 log_fatal("Not enough space for option overload option.");
1485 /* Return true if the format string has a variable length text option
1486 * ("t"), return false otherwise.
1490 format_has_text(format
)
1496 while (*p
!= '\0') {
1502 /* These symbols are arbitrary, not fixed or
1503 * determinable length...text options with them is
1504 * invalid (whatever the case, they are never NULL
1515 /* 'c' only follows 'D' atoms, and indicates that
1516 * compression may be used. If there was a 'D'
1517 * atom already, we would have returned. So this
1518 * is an error, but continue looking for 't' anyway.
1520 log_error("format_has_text(%s): 'c' atoms are illegal "
1521 "except after 'D' atoms.", format
);
1524 /* 'E' is variable length, but not arbitrary...you
1525 * can find its length if you can find an END option.
1526 * N is (n)-byte in length but trails a name of a
1527 * space defining the enumeration values. So treat
1528 * both the same - valid, fixed-length fields.
1532 /* Consume the space name. */
1533 while ((*p
!= '\0') && (*p
++ != '.'))
1545 /* Determine the minimum length of a DHCP option prior to any variable
1546 * or inconsistent length formats, according to its configured format
1547 * variable (and possibly from supplied option cache contents for variable
1548 * length format symbols).
1552 format_min_length(format
, oc
)
1554 struct option_cache
*oc
;
1556 const char *p
, *name
;
1559 struct enumeration
*espace
;
1562 while (*p
!= '\0') {
1564 case '6': /* IPv6 Address */
1569 case 'I': /* IPv4 Address */
1570 case 'l': /* int32_t */
1571 case 'L': /* uint32_t */
1572 case 'T': /* Lease Time, uint32_t equivalent */
1577 case 's': /* int16_t */
1578 case 'S': /* uint16_t */
1583 case 'N': /* Enumeration value. */
1584 /* Consume space name. */
1588 log_fatal("Corrupt format: %s", format
);
1590 espace
= find_enumeration(name
, p
- name
);
1591 if (espace
== NULL
) {
1592 log_error("Unknown enumeration: %s", format
);
1593 /* Max is safest value to return. */
1597 min_len
+= espace
->width
;
1598 last_size
= espace
->width
;
1603 case 'b': /* int8_t */
1604 case 'B': /* uint8_t */
1605 case 'F': /* Flag that is always true. */
1606 case 'f': /* Flag */
1611 case 'o': /* Last argument is optional. */
1612 min_len
-= last_size
;
1614 /* XXX: It MAY be possible to sense the end of an
1615 * encapsulated space, but right now this is too
1616 * hard to support. Return a safe value.
1618 case 'e': /* Encapsulation hint (there is an 'E' later). */
1619 case 'E': /* Encapsulated options. */
1622 case 'd': /* "Domain name" */
1623 case 'D': /* "rfc1035 formatted names" */
1624 case 't': /* "ASCII Text" */
1625 case 'X': /* "ASCII or Hex Conditional */
1626 case 'x': /* "Hex" */
1627 case 'A': /* Array of all that precedes. */
1628 case 'a': /* Array of preceding symbol. */
1629 case 'Z': /* nothing. */
1632 case 'c': /* Compress flag for D atom. */
1633 log_error("format_min_length(%s): 'c' atom is illegal "
1634 "except after 'D' atom.", format
);
1638 /* No safe value is known. */
1639 log_error("format_min_length(%s): No safe value "
1640 "for unknown format symbols.", format
);
1649 /* Format the specified option so that a human can easily read it. */
1651 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1652 struct option
*option
;
1653 const unsigned char *data
;
1658 static char optbuf
[32768]; /* XXX */
1659 static char *endbuf
= &optbuf
[sizeof(optbuf
)];
1667 char fmtbuf
[32] = "";
1669 struct enumeration
*enumbuf
[32]; /* MUST be same as fmtbuf */
1671 const unsigned char *dp
= data
;
1680 memset (enumbuf
, 0, sizeof enumbuf
);
1682 /* Figure out the size of the data. */
1683 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1684 if (l
>= sizeof(fmtbuf
) - 1)
1685 log_fatal("Bounds failure on internal buffer at "
1689 log_error ("%s: Extra codes in format string: %s",
1691 &(option
-> format
[i
]));
1695 fmtbuf
[l
] = option
-> format
[i
];
1696 switch (option
-> format
[i
]) {
1704 /* Skip the universe name. */
1705 while (option
-> format
[i
] &&
1706 option
-> format
[i
] != '.')
1710 for (k
= 0; k
< len
; k
++) {
1711 if (!isascii (data
[k
]) ||
1712 !isprint (data
[k
]))
1715 /* If we found no bogus characters, or the bogus
1716 character we found is a trailing NUL, it's
1717 okay to print this option as text. */
1718 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1731 /* Fall Through ! */
1739 while (option
-> format
[i
] &&
1740 option
-> format
[i
] != '.')
1743 find_enumeration (&option
-> format
[k
] + 1,
1745 if (enumbuf
[l
] == NULL
) {
1749 hunksize
+= enumbuf
[l
]->width
;
1750 hunkinc
= enumbuf
[l
]->width
;
1783 log_error ("%s: garbage in format string: %s",
1785 &(option
-> format
[i
]));
1790 /* Check for too few bytes... */
1791 if (hunksize
- opthunk
> len
) {
1792 log_error ("%s: expecting at least %d bytes; got %d",
1797 /* Check for too many bytes... */
1798 if (numhunk
== -1 && hunksize
< len
)
1799 log_error ("%s: %d extra bytes",
1803 /* If this is an array, compute its size. */
1805 numhunk
= len
/ hunksize
;
1806 /* See if we got an exact number of hunks. */
1807 if (numhunk
> 0 && numhunk
* hunksize
< len
)
1808 log_error ("%s: %d extra bytes at end of array\n",
1810 len
- numhunk
* hunksize
);
1812 /* A one-hunk array prints the same as a single hunk. */
1816 /* Cycle through the array (or hunk) printing the data. */
1817 for (i
= 0; i
< numhunk
; i
++) {
1818 for (j
= 0; j
< numelem
; j
++) {
1819 switch (fmtbuf
[j
]) {
1821 /* endbuf-1 leaves room for NULL. */
1822 k
= pretty_text(&op
, endbuf
- 1, &dp
,
1823 data
+ len
, emit_quotes
);
1825 log_error("Error printing text.");
1830 case 'D': /* RFC1035 format name list */
1831 for( ; dp
< (data
+ len
) ; dp
+= k
) {
1832 unsigned char nbuff
[NS_MAXCDNAME
];
1833 const unsigned char *nbp
, *nend
;
1835 nend
= &nbuff
[sizeof(nbuff
)];
1837 /* If this is for ISC DHCP consumption
1838 * (emit_quotes), lay it out as a list
1839 * of STRING tokens. Otherwise, it is
1840 * a space-separated list of DNS-
1841 * escaped names as /etc/resolv.conf
1845 if (op
+ 2 > endbuf
)
1853 /* XXX: if fmtbuf[j+1] != 'c', we
1854 * should warn if the data was
1855 * compressed anyway.
1857 k
= MRns_name_unpack(data
,
1863 log_error("Invalid domain "
1868 /* If emit_quotes, then use ISC DHCP
1869 * escapes. Otherwise, rely only on
1874 pretty_domain(&op
, endbuf
-1,
1877 /* ns_name_ntop() includes
1878 * a trailing NUL in its
1881 count
= MRns_name_ntop(
1886 log_error("Invalid "
1891 /* Consume all but the trailing
1896 /* Replace the trailing NUL
1897 * with the implicit root
1898 * (in the unlikely event the
1899 * domain name /is/ the root).
1906 /* pretty-printing an array of enums is
1907 going to get ugly. */
1914 switch (enumbuf
[j
]->width
) {
1916 tval
= getUChar(dp
);
1920 tval
= getUShort(dp
);
1924 tval
= getULong(dp
);
1928 log_fatal("Impossible case at %s:%d.",
1930 return "<double impossible condition>";
1934 if (!enumbuf
[j
] -> values
[i
].name
)
1936 if (enumbuf
[j
] -> values
[i
].value
==
1940 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
1941 dp
+= enumbuf
[j
]->width
;
1945 sprintf(op
, "%lu", tval
);
1950 memcpy(iaddr
.iabuf
, dp
, 4);
1951 strcpy(op
, piaddr(iaddr
));
1956 memcpy(iaddr
.iabuf
, dp
, 16);
1957 strcpy(op
, piaddr(iaddr
));
1961 sprintf (op
, "%ld", (long)getLong (dp
));
1965 tval
= getULong (dp
);
1967 sprintf (op
, "%s", "infinite");
1969 sprintf(op
, "%lu", tval
);
1973 (unsigned long)getULong(dp
));
1977 sprintf (op
, "%d", (int)getShort (dp
));
1981 sprintf(op
, "%u", (unsigned)getUShort(dp
));
1985 sprintf (op
, "%d", *(const char *)dp
++);
1988 sprintf (op
, "%d", *dp
++);
1992 sprintf (op
, "%x", *dp
++);
1995 strcpy (op
, *dp
++ ? "true" : "false");
1998 strcpy (op
, "true");
2005 log_error ("Unexpected format code %c",
2009 if (dp
== data
+ len
)
2011 if (j
+ 1 < numelem
&& comma
!= ':')
2014 if (i
+ 1 < numhunk
) {
2017 if (dp
== data
+ len
)
2023 int get_option (result
, universe
, packet
, lease
, client_state
,
2024 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2025 struct data_string
*result
;
2026 struct universe
*universe
;
2027 struct packet
*packet
;
2028 struct lease
*lease
;
2029 struct client_state
*client_state
;
2030 struct option_state
*in_options
;
2031 struct option_state
*cfg_options
;
2032 struct option_state
*options
;
2033 struct binding_scope
**scope
;
2038 struct option_cache
*oc
;
2040 if (!universe
-> lookup_func
)
2042 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
2045 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
2046 in_options
, cfg_options
, scope
, oc
,
2052 void set_option (universe
, options
, option
, op
)
2053 struct universe
*universe
;
2054 struct option_state
*options
;
2055 struct option_cache
*option
;
2056 enum statement_op op
;
2058 struct option_cache
*oc
, *noc
;
2063 case eval_statement
:
2064 case break_statement
:
2066 log_error ("bogus statement type in set_option.");
2069 case default_option_statement
:
2070 oc
= lookup_option (universe
, options
,
2071 option
-> option
-> code
);
2074 save_option (universe
, options
, option
);
2077 case supersede_option_statement
:
2078 case send_option_statement
:
2079 /* Install the option, replacing any existing version. */
2080 save_option (universe
, options
, option
);
2083 case append_option_statement
:
2084 case prepend_option_statement
:
2085 oc
= lookup_option (universe
, options
,
2086 option
-> option
-> code
);
2088 save_option (universe
, options
, option
);
2091 /* If it's not an expression, make it into one. */
2092 if (!oc
-> expression
&& oc
-> data
.len
) {
2093 if (!expression_allocate (&oc
-> expression
, MDL
)) {
2094 log_error ("Can't allocate const expression.");
2097 oc
-> expression
-> op
= expr_const_data
;
2099 (&oc
-> expression
-> data
.const_data
,
2101 data_string_forget (&oc
-> data
, MDL
);
2103 noc
= (struct option_cache
*)0;
2104 if (!option_cache_allocate (&noc
, MDL
))
2106 if (op
== append_option_statement
) {
2107 if (!make_concat (&noc
-> expression
,
2109 option
-> expression
)) {
2110 option_cache_dereference (&noc
, MDL
);
2114 if (!make_concat (&noc
-> expression
,
2115 option
-> expression
,
2116 oc
-> expression
)) {
2117 option_cache_dereference (&noc
, MDL
);
2121 option_reference(&(noc
->option
), oc
->option
, MDL
);
2122 save_option (universe
, options
, noc
);
2123 option_cache_dereference (&noc
, MDL
);
2128 struct option_cache
*lookup_option (universe
, options
, code
)
2129 struct universe
*universe
;
2130 struct option_state
*options
;
2134 return (struct option_cache
*)0;
2135 if (universe
-> lookup_func
)
2136 return (*universe
-> lookup_func
) (universe
, options
, code
);
2138 log_error ("can't look up options in %s space.",
2140 return (struct option_cache
*)0;
2143 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
2144 struct universe
*universe
;
2145 struct option_state
*options
;
2152 /* Make sure there's a hash table. */
2153 if (universe
-> index
>= options
-> universe_count
||
2154 !(options
-> universes
[universe
-> index
]))
2155 return (struct option_cache
*)0;
2157 hash
= options
-> universes
[universe
-> index
];
2159 hashix
= compute_option_hash (code
);
2160 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2161 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
2163 return (struct option_cache
*)(bptr
-> car
);
2165 return (struct option_cache
*)0;
2168 /* Save a specified buffer into an option cache. */
2170 save_option_buffer(struct universe
*universe
, struct option_state
*options
,
2171 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2172 unsigned code
, int terminatep
)
2174 struct option_cache
*op
= NULL
;
2177 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2183 save_option(universe
, options
, op
);
2187 option_cache_dereference(&op
, MDL
);
2192 /* Append a specified buffer onto the tail of an option cache. */
2194 append_option_buffer(struct universe
*universe
, struct option_state
*options
,
2195 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2196 unsigned code
, int terminatep
)
2198 struct option_cache
*op
= NULL
;
2201 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2207 also_save_option(universe
, options
, op
);
2211 option_cache_dereference(&op
, MDL
);
2216 /* Create/copy a buffer into a new option cache. */
2218 prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
2219 unsigned char *buffer
, unsigned length
, unsigned code
,
2220 int terminatep
, struct option_cache
**opp
)
2222 struct buffer
*lbp
= NULL
;
2223 struct option
*option
= NULL
;
2224 struct option_cache
*op
;
2227 /* Code sizes of 8, 16, and 32 bits are allowed. */
2228 switch(universe
->tag_size
) {
2238 if (code
> 0xffffffff)
2243 log_fatal("Inconsistent universe tag size at %s:%d.", MDL
);
2246 option_code_hash_lookup(&option
, universe
->code_hash
, &code
, 0, MDL
);
2248 /* If we created an option structure for each option a client
2249 * supplied, it's possible we may create > 2^32 option structures.
2250 * That's not feasible. So by failing to enter these option
2251 * structures into the code and name hash tables, references will
2252 * never be more than 1 - when the option cache is destroyed, this
2253 * will be cleaned up.
2256 char nbuf
[sizeof("unknown-4294967295")];
2258 sprintf(nbuf
, "unknown-%u", code
);
2260 option
= new_option(nbuf
, MDL
);
2265 option
->format
= default_option_format
;
2266 option
->universe
= universe
;
2267 option
->code
= code
;
2269 /* new_option() doesn't set references, pretend. */
2273 if (!option_cache_allocate (opp
, MDL
)) {
2274 log_error("No memory for option code %s.%s.",
2275 universe
->name
, option
->name
);
2280 /* Pointer rather than double pointer makes for less parens. */
2283 option_reference(&op
->option
, option
, MDL
);
2285 /* If we weren't passed a buffer in which the data are saved and
2286 refcounted, allocate one now. */
2288 if (!buffer_allocate (&lbp
, length
+ terminatep
, MDL
)) {
2289 log_error ("no memory for option buffer.");
2294 memcpy (lbp
-> data
, buffer
, length
+ terminatep
);
2296 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
2299 /* Reference buffer copy to option cache. */
2300 op
-> data
.buffer
= (struct buffer
*)0;
2301 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
2303 /* Point option cache into buffer. */
2304 op
-> data
.data
= buffer
;
2305 op
-> data
.len
= length
;
2308 /* NUL terminate (we can get away with this because we (or
2309 the caller!) allocated one more than the buffer size, and
2310 because the byte following the end of an option is always
2311 the code of the next option, which the caller is getting
2312 out of the *original* buffer. */
2313 buffer
[length
] = 0;
2314 op
-> data
.terminated
= 1;
2316 op
-> data
.terminated
= 0;
2318 /* If this option is ultimately a text option, null determinate to
2319 * comply with RFC2132 section 2. Mark a flag so this can be sensed
2320 * later to echo NULLs back to clients that supplied them (they
2321 * probably expect them).
2323 if (format_has_text(option
->format
)) {
2324 int min_len
= format_min_length(option
->format
, op
);
2326 while ((op
->data
.len
> min_len
) &&
2327 (op
->data
.data
[op
->data
.len
-1] == '\0')) {
2329 op
->flags
|= OPTION_HAD_NULLS
;
2333 /* And let go of our references. */
2335 option_dereference(&option
, MDL
);
2341 count_options(struct option_cache
*dummy_oc
,
2342 struct packet
*dummy_packet
,
2343 struct lease
*dummy_lease
,
2344 struct client_state
*dummy_client_state
,
2345 struct option_state
*dummy_opt_state
,
2346 struct option_state
*opt_state
,
2347 struct binding_scope
**dummy_binding_scope
,
2348 struct universe
*dummy_universe
,
2349 void *void_accumulator
) {
2350 int *accumulator
= (int *)void_accumulator
;
2356 collect_oro(struct option_cache
*oc
,
2357 struct packet
*dummy_packet
,
2358 struct lease
*dummy_lease
,
2359 struct client_state
*dummy_client_state
,
2360 struct option_state
*dummy_opt_state
,
2361 struct option_state
*opt_state
,
2362 struct binding_scope
**dummy_binding_scope
,
2363 struct universe
*dummy_universe
,
2365 struct data_string
*oro
= (struct data_string
*)void_oro
;
2367 putUShort(oro
->buffer
->data
+ oro
->len
, oc
->option
->code
);
2371 /* build_server_oro() is presently unusued, but may be used at a future date
2372 * with support for Reconfigure messages (as a hint to the client about new
2373 * option value contents).
2376 build_server_oro(struct data_string
*server_oro
,
2377 struct option_state
*options
,
2378 const char *file
, int line
) {
2384 * Count the number of options, so we can allocate enough memory.
2385 * We want to mention sub-options too, so check all universes.
2388 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2389 NULL
, &dhcpv6_universe
, (void *)&num_opts
,
2391 for (i
=0; i
< options
->universe_count
; i
++) {
2392 if (options
->universes
[i
] != NULL
) {
2393 o
= universes
[i
]->enc_opt
;
2395 if (o
->universe
== &dhcpv6_universe
) {
2399 o
= o
->universe
->enc_opt
;
2407 memset(server_oro
, 0, sizeof(*server_oro
));
2408 if (!buffer_allocate(&server_oro
->buffer
, num_opts
* 2, MDL
)) {
2409 log_fatal("no memory to build server ORO");
2411 server_oro
->data
= server_oro
->buffer
->data
;
2415 * We want to mention sub-options too, so check all universes.
2417 server_oro
->len
= 0; /* gets set in collect_oro */
2418 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2419 NULL
, &dhcpv6_universe
, (void *)server_oro
,
2421 for (i
=0; i
< options
->universe_count
; i
++) {
2422 if (options
->universes
[i
] != NULL
) {
2423 o
= universes
[i
]->enc_opt
;
2425 if (o
->universe
== &dhcpv6_universe
) {
2427 tmp
= server_oro
->buffer
->data
;
2428 putUShort(tmp
+ server_oro
->len
,
2430 server_oro
->len
+= 2;
2433 o
= o
->universe
->enc_opt
;
2439 /* Wrapper function to put an option cache into an option state. */
2441 save_option(struct universe
*universe
, struct option_state
*options
,
2442 struct option_cache
*oc
)
2444 if (universe
->save_func
)
2445 (*universe
->save_func
)(universe
, options
, oc
, ISC_FALSE
);
2447 log_error("can't store options in %s space.", universe
->name
);
2450 /* Wrapper function to append an option cache into an option state's list. */
2452 also_save_option(struct universe
*universe
, struct option_state
*options
,
2453 struct option_cache
*oc
)
2455 if (universe
->save_func
)
2456 (*universe
->save_func
)(universe
, options
, oc
, ISC_TRUE
);
2458 log_error("can't store options in %s space.", universe
->name
);
2462 save_hashed_option(struct universe
*universe
, struct option_state
*options
,
2463 struct option_cache
*oc
, isc_boolean_t appendp
)
2467 pair
*hash
= options
-> universes
[universe
-> index
];
2468 struct option_cache
**ocloc
;
2470 if (oc
-> refcnt
== 0)
2473 /* Compute the hash. */
2474 hashix
= compute_option_hash (oc
-> option
-> code
);
2476 /* If there's no hash table, make one. */
2478 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
2480 log_error ("no memory to store %s.%s",
2481 universe
-> name
, oc
-> option
-> name
);
2484 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
2485 options
-> universes
[universe
-> index
] = (void *)hash
;
2487 /* Try to find an existing option matching the new one. */
2488 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2489 if (((struct option_cache
*)
2490 (bptr
-> car
)) -> option
-> code
==
2491 oc
-> option
-> code
)
2495 /* Deal with collisions on the hash list. */
2497 ocloc
= (struct option_cache
**)&bptr
->car
;
2500 * If appendp is set, append it onto the tail of the
2501 * ->next list. If it is not set, rotate it into
2502 * position at the head of the list.
2506 ocloc
= &(*ocloc
)->next
;
2507 } while (*ocloc
!= NULL
);
2509 option_cache_dereference(ocloc
, MDL
);
2512 option_cache_reference(ocloc
, oc
, MDL
);
2517 /* Otherwise, just put the new one at the head of the list. */
2518 bptr
= new_pair (MDL
);
2520 log_error ("No memory for option_cache reference.");
2523 bptr
-> cdr
= hash
[hashix
];
2525 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
2526 hash
[hashix
] = bptr
;
2529 void delete_option (universe
, options
, code
)
2530 struct universe
*universe
;
2531 struct option_state
*options
;
2534 if (universe
-> delete_func
)
2535 (*universe
-> delete_func
) (universe
, options
, code
);
2537 log_error ("can't delete options from %s space.",
2541 void delete_hashed_option (universe
, options
, code
)
2542 struct universe
*universe
;
2543 struct option_state
*options
;
2547 pair bptr
, prev
= (pair
)0;
2548 pair
*hash
= options
-> universes
[universe
-> index
];
2550 /* There may not be any options in this space. */
2554 /* Try to find an existing option matching the new one. */
2555 hashix
= compute_option_hash (code
);
2556 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2557 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
2562 /* If we found one, wipe it out... */
2565 prev
-> cdr
= bptr
-> cdr
;
2567 hash
[hashix
] = bptr
-> cdr
;
2568 option_cache_dereference
2569 ((struct option_cache
**)(&bptr
-> car
), MDL
);
2570 free_pair (bptr
, MDL
);
2574 extern struct option_cache
*free_option_caches
; /* XXX */
2576 int option_cache_dereference (ptr
, file
, line
)
2577 struct option_cache
**ptr
;
2581 if (!ptr
|| !*ptr
) {
2582 log_error ("Null pointer in option_cache_dereference: %s(%d)",
2584 #if defined (POINTER_DEBUG)
2592 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
2593 if (!(*ptr
) -> refcnt
) {
2594 if ((*ptr
) -> data
.buffer
)
2595 data_string_forget (&(*ptr
) -> data
, file
, line
);
2597 option_dereference(&(*ptr
)->option
, MDL
);
2598 if ((*ptr
) -> expression
)
2599 expression_dereference (&(*ptr
) -> expression
,
2602 option_cache_dereference (&((*ptr
) -> next
),
2604 /* Put it back on the free list... */
2605 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
2606 free_option_caches
= *ptr
;
2607 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
2609 if ((*ptr
) -> refcnt
< 0) {
2610 log_error ("%s(%d): negative refcnt!", file
, line
);
2611 #if defined (DEBUG_RC_HISTORY)
2612 dump_rc_history (*ptr
);
2614 #if defined (POINTER_DEBUG)
2617 *ptr
= (struct option_cache
*)0;
2621 *ptr
= (struct option_cache
*)0;
2626 int hashed_option_state_dereference (universe
, state
, file
, line
)
2627 struct universe
*universe
;
2628 struct option_state
*state
;
2636 /* Get the pointer to the array of hash table bucket heads. */
2637 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
2641 /* For each non-null head, loop through all the buckets dereferencing
2642 the attached option cache structures and freeing the buckets. */
2643 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2644 for (cp
= heads
[i
]; cp
; cp
= next
) {
2646 option_cache_dereference
2647 ((struct option_cache
**)&cp
-> car
,
2649 free_pair (cp
, file
, line
);
2653 dfree (heads
, file
, line
);
2654 state
-> universes
[universe
-> index
] = (void *)0;
2658 /* The 'data_string' primitive doesn't have an appension mechanism.
2659 * This function must then append a new option onto an existing buffer
2660 * by first duplicating the original buffer and appending the desired
2661 * values, followed by coping the new value into place.
2664 append_option(struct data_string
*dst
, struct universe
*universe
,
2665 struct option
*option
, struct data_string
*src
)
2667 struct data_string tmp
;
2669 if (src
->len
== 0 && option
->format
[0] != 'Z')
2672 memset(&tmp
, 0, sizeof(tmp
));
2674 /* Allocate a buffer to hold existing data, the current option's
2675 * tag and length, and the option's content.
2677 if (!buffer_allocate(&tmp
.buffer
,
2678 (dst
->len
+ universe
->length_size
+
2679 universe
->tag_size
+ src
->len
), MDL
)) {
2680 /* XXX: This kills all options presently stored in the
2681 * destination buffer. This is the way the original code
2682 * worked, and assumes an 'all or nothing' approach to
2683 * eg encapsulated option spaces. It may or may not be
2686 data_string_forget(dst
, MDL
);
2689 tmp
.data
= tmp
.buffer
->data
;
2691 /* Copy the existing data off the destination. */
2693 memcpy(tmp
.buffer
->data
, dst
->data
, dst
->len
);
2696 /* Place the new option tag and length. */
2697 (*universe
->store_tag
)(tmp
.buffer
->data
+ tmp
.len
, option
->code
);
2698 tmp
.len
+= universe
->tag_size
;
2699 (*universe
->store_length
)(tmp
.buffer
->data
+ tmp
.len
, src
->len
);
2700 tmp
.len
+= universe
->length_size
;
2702 /* Copy the option contents onto the end. */
2703 memcpy(tmp
.buffer
->data
+ tmp
.len
, src
->data
, src
->len
);
2704 tmp
.len
+= src
->len
;
2706 /* Play the shell game. */
2707 data_string_forget(dst
, MDL
);
2708 data_string_copy(dst
, &tmp
, MDL
);
2709 data_string_forget(&tmp
, MDL
);
2714 store_option(struct data_string
*result
, struct universe
*universe
,
2715 struct packet
*packet
, struct lease
*lease
,
2716 struct client_state
*client_state
,
2717 struct option_state
*in_options
, struct option_state
*cfg_options
,
2718 struct binding_scope
**scope
, struct option_cache
*oc
)
2720 struct data_string tmp
;
2721 struct universe
*subu
=NULL
;
2725 memset(&tmp
, 0, sizeof(tmp
));
2727 if (evaluate_option_cache(&tmp
, packet
, lease
, client_state
,
2728 in_options
, cfg_options
, scope
, oc
, MDL
)) {
2729 /* If the option is an extended 'e'ncapsulation (not a
2730 * direct 'E'ncapsulation), append the encapsulated space
2731 * onto the currently prepared value.
2734 if (oc
->option
->format
&&
2735 oc
->option
->format
[0] == 'e') {
2736 /* Skip forward to the universe name. */
2737 start
= strchr(oc
->option
->format
, 'E');
2741 /* Locate the name-terminating '.'. */
2742 end
= strchr(++start
, '.');
2744 /* A zero-length name is not allowed in
2745 * these kinds of encapsulations.
2747 if (end
== NULL
|| start
== end
)
2750 universe_hash_lookup(&subu
, universe_hash
,
2751 start
, end
- start
, MDL
);
2754 log_error("store_option: option %d "
2755 "refers to unknown "
2756 "option space '%.*s'.",
2758 (int)(end
- start
), start
);
2762 /* Append encapsulations, if any. We
2763 * already have the prepended values, so
2764 * we send those even if there are no
2765 * encapsulated options (and ->encapsulate()
2768 subu
->encapsulate(&tmp
, packet
, lease
,
2769 client_state
, in_options
,
2770 cfg_options
, scope
, subu
);
2773 } while (ISC_FALSE
);
2775 status
= append_option(result
, universe
, oc
->option
, &tmp
);
2776 data_string_forget(&tmp
, MDL
);
2784 int option_space_encapsulate (result
, packet
, lease
, client_state
,
2785 in_options
, cfg_options
, scope
, name
)
2786 struct data_string
*result
;
2787 struct packet
*packet
;
2788 struct lease
*lease
;
2789 struct client_state
*client_state
;
2790 struct option_state
*in_options
;
2791 struct option_state
*cfg_options
;
2792 struct binding_scope
**scope
;
2793 struct data_string
*name
;
2795 struct universe
*u
= NULL
;
2798 universe_hash_lookup(&u
, universe_hash
,
2799 (const char *)name
->data
, name
->len
, MDL
);
2801 log_error("option_space_encapsulate: option space '%.*s' does "
2802 "not exist, but is configured.",
2803 (int)name
->len
, name
->data
);
2807 if (u
->encapsulate
!= NULL
) {
2808 if (u
->encapsulate(result
, packet
, lease
, client_state
,
2809 in_options
, cfg_options
, scope
, u
))
2812 log_error("encapsulation requested for '%s' with no support.",
2818 /* Attempt to store any 'E'ncapsulated options that have not yet been
2819 * placed on the option buffer by the above (configuring a value in
2820 * the space over-rides any values in the child universe).
2822 * Note that there are far fewer universes than there will ever be
2823 * options in any universe. So it is faster to traverse the
2824 * configured universes, checking if each is encapsulated in the
2825 * current universe, and if so attempting to do so.
2827 * For each configured universe for this configuration option space,
2828 * which is encapsulated within the current universe, can not be found
2829 * by the lookup function (the universe-specific encapsulation
2830 * functions would already have stored such a value), and encapsulates
2831 * at least one option, append it.
2834 search_subencapsulation(struct data_string
*result
, struct packet
*packet
,
2835 struct lease
*lease
, struct client_state
*client_state
,
2836 struct option_state
*in_options
,
2837 struct option_state
*cfg_options
,
2838 struct binding_scope
**scope
,
2839 struct universe
*universe
)
2841 struct data_string sub
;
2842 struct universe
*subu
;
2845 memset(&sub
, 0, sizeof(sub
));
2846 for (i
= 0 ; i
< cfg_options
->universe_count
; i
++) {
2847 subu
= universes
[i
];
2850 log_fatal("Impossible condition at %s:%d.", MDL
);
2852 if (subu
->enc_opt
!= NULL
&&
2853 subu
->enc_opt
->universe
== universe
&&
2854 subu
->enc_opt
->format
!= NULL
&&
2855 subu
->enc_opt
->format
[0] == 'E' &&
2856 lookup_option(universe
, cfg_options
,
2857 subu
->enc_opt
->code
) == NULL
&&
2858 subu
->encapsulate(&sub
, packet
, lease
, client_state
,
2859 in_options
, cfg_options
,
2861 if (append_option(result
, universe
,
2862 subu
->enc_opt
, &sub
))
2865 data_string_forget(&sub
, MDL
);
2872 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
2873 in_options
, cfg_options
, scope
, universe
)
2874 struct data_string
*result
;
2875 struct packet
*packet
;
2876 struct lease
*lease
;
2877 struct client_state
*client_state
;
2878 struct option_state
*in_options
;
2879 struct option_state
*cfg_options
;
2880 struct binding_scope
**scope
;
2881 struct universe
*universe
;
2887 if (universe
-> index
>= cfg_options
-> universe_count
)
2890 hash
= cfg_options
-> universes
[universe
-> index
];
2894 /* For each hash bucket, and each configured option cache within
2895 * that bucket, append the option onto the buffer in encapsulated
2896 * format appropriate to the universe.
2899 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2900 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2901 if (store_option(result
, universe
, packet
, lease
,
2902 client_state
, in_options
, cfg_options
,
2903 scope
, (struct option_cache
*)p
->car
))
2908 if (search_subencapsulation(result
, packet
, lease
, client_state
,
2909 in_options
, cfg_options
, scope
, universe
))
2915 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
2916 in_options
, cfg_options
, scope
, universe
)
2917 struct data_string
*result
;
2918 struct packet
*packet
;
2919 struct lease
*lease
;
2920 struct client_state
*client_state
;
2921 struct option_state
*in_options
;
2922 struct option_state
*cfg_options
;
2923 struct binding_scope
**scope
;
2924 struct universe
*universe
;
2928 static struct option_cache
*no_nwip
;
2929 struct data_string ds
;
2930 struct option_chain_head
*head
;
2932 if (universe
-> index
>= cfg_options
-> universe_count
)
2934 head
= ((struct option_chain_head
*)
2935 cfg_options
-> universes
[nwip_universe
.index
]);
2940 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
2941 if (store_option (result
, universe
, packet
,
2942 lease
, client_state
, in_options
,
2944 (struct option_cache
*)ocp
-> car
))
2948 /* If there's no data, the nwip suboption is supposed to contain
2949 a suboption saying there's no data. */
2953 static unsigned char nni
[] = { 1, 0 };
2955 memset (&ds
, 0, sizeof ds
);
2958 if (option_cache_allocate (&no_nwip
, MDL
))
2959 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
2960 if (!option_code_hash_lookup(&no_nwip
->option
,
2961 nwip_universe
.code_hash
,
2963 log_fatal("Nwip option hash does not contain "
2967 if (store_option (result
, universe
, packet
, lease
,
2968 client_state
, in_options
,
2969 cfg_options
, scope
, no_nwip
))
2973 memset (&ds
, 0, sizeof ds
);
2975 /* If we have nwip options, the first one has to be the
2976 nwip-exists-in-option-area option. */
2977 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
2978 data_string_forget (result
, MDL
);
2981 ds
.data
= &ds
.buffer
-> data
[0];
2982 ds
.buffer
-> data
[0] = 2;
2983 ds
.buffer
-> data
[1] = 0;
2984 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
2985 data_string_forget (result
, MDL
);
2986 data_string_copy (result
, &ds
, MDL
);
2987 data_string_forget (&ds
, MDL
);
2993 /* We don't want to use ns_name_pton()...it doesn't tell us how many bytes
2994 * it has consumed, and it plays havoc with our escapes.
2996 * So this function does DNS encoding, and returns either the number of
2997 * octects consumed (on success), or -1 on failure.
3000 fqdn_encode(unsigned char *dst
, int dstlen
, const unsigned char *src
,
3004 int i
, j
, len
, outlen
=0;
3007 for (i
= 0, j
= 0 ; i
< srclen
; i
= j
) {
3008 while ((j
< srclen
) && (src
[j
] != '.') && (src
[j
] != '\0'))
3012 if ((outlen
+ 1 + len
) > dstlen
)
3018 /* We only do one FQDN, ending in one root label. */
3022 memcpy(out
, src
+ i
, len
);
3026 /* Advance past the root label. */
3030 if ((outlen
+ 1) > dstlen
)
3033 /* Place the root label. */
3040 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
3041 in_options
, cfg_options
, scope
, universe
)
3042 struct data_string
*result
;
3043 struct packet
*packet
;
3044 struct lease
*lease
;
3045 struct client_state
*client_state
;
3046 struct option_state
*in_options
;
3047 struct option_state
*cfg_options
;
3048 struct binding_scope
**scope
;
3049 struct universe
*universe
;
3052 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3056 struct buffer
*bp
= (struct buffer
*)0;
3057 struct option_chain_head
*head
;
3059 /* If there's no FQDN universe, don't encapsulate. */
3060 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
3062 head
= ((struct option_chain_head
*)
3063 cfg_options
-> universes
[fqdn_universe
.index
]);
3067 /* Figure out the values of all the suboptions. */
3068 memset (results
, 0, sizeof results
);
3069 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3070 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
3071 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
3073 evaluate_option_cache (&results
[oc
-> option
-> code
],
3074 packet
, lease
, client_state
, in_options
,
3075 cfg_options
, scope
, oc
, MDL
);
3077 /* We add a byte for the flags field.
3078 * We add two bytes for the two RCODE fields.
3079 * We add a byte because we will prepend a label count.
3080 * We add a byte because the input len doesn't count null termination,
3081 * and we will add a root label.
3083 len
= 5 + results
[FQDN_FQDN
].len
;
3084 /* Save the contents of the option in a buffer. */
3085 if (!buffer_allocate (&bp
, len
, MDL
)) {
3086 log_error ("no memory for option buffer.");
3090 buffer_reference (&result
-> buffer
, bp
, MDL
);
3092 result
-> data
= &bp
-> data
[0];
3094 memset (&bp
-> data
[0], 0, len
);
3095 /* XXX: The server should set bit 4 (yes, 4, not 3) to 1 if it is
3096 * not going to perform any ddns updates. The client should set the
3097 * bit if it doesn't want the server to perform any updates.
3098 * The problem is at this layer of abstraction we have no idea if
3099 * the caller is a client or server.
3101 * See RFC4702, Section 3.1, 'The "N" bit'.
3106 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3107 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3108 bp
-> data
[0] |= 2;
3109 if (results
[FQDN_SERVER_UPDATE
].len
&&
3110 results
[FQDN_SERVER_UPDATE
].data
[0])
3111 bp
-> data
[0] |= 1;
3112 if (results
[FQDN_RCODE1
].len
)
3113 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
3114 if (results
[FQDN_RCODE2
].len
)
3115 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
3117 if (results
[FQDN_ENCODED
].len
&&
3118 results
[FQDN_ENCODED
].data
[0]) {
3120 if (results
[FQDN_FQDN
].len
) {
3121 i
= fqdn_encode(&bp
->data
[3], len
- 3,
3122 results
[FQDN_FQDN
].data
,
3123 results
[FQDN_FQDN
].len
);
3131 result
->terminated
= 0;
3134 if (results
[FQDN_FQDN
].len
) {
3135 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
3136 results
[FQDN_FQDN
].len
);
3137 result
-> len
+= results
[FQDN_FQDN
].len
;
3138 result
-> terminated
= 0;
3142 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3143 if (results
[i
].len
)
3144 data_string_forget (&results
[i
], MDL
);
3146 buffer_dereference (&bp
, MDL
);
3148 data_string_forget(result
, MDL
);
3153 * Trap invalid attempts to inspect FQND6 contents.
3155 struct option_cache
*
3156 lookup_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3159 log_fatal("Impossible condition at %s:%d.", MDL
);
3164 * Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
3167 save_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3168 struct option_cache
*oc
, isc_boolean_t appendp
)
3170 log_fatal("Impossible condition at %s:%d.", MDL
);
3174 * Trap invalid attempts to delete an option out of the FQDN6 universe.
3177 delete_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3180 log_fatal("Impossible condition at %s:%d.", MDL
);
3183 /* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
3184 * V6's option cache entry.
3186 * This function is called speculatively by dhclient to setup
3187 * environment variables. But it would have already called the
3188 * foreach on the normal fqdn universe, so this is superfluous.
3191 fqdn6_option_space_foreach(struct packet
*packet
, struct lease
*lease
,
3192 struct client_state
*client_state
,
3193 struct option_state
*in_options
,
3194 struct option_state
*cfg_options
,
3195 struct binding_scope
**scope
,
3196 struct universe
*u
, void *stuff
,
3197 void (*func
)(struct option_cache
*,
3200 struct client_state
*,
3201 struct option_state
*,
3202 struct option_state
*,
3203 struct binding_scope
**,
3204 struct universe
*, void *))
3206 /* Pretend it is empty. */
3210 /* Turn the FQDN option space into a DHCPv6 FQDN option buffer.
3213 fqdn6_option_space_encapsulate(struct data_string
*result
,
3214 struct packet
*packet
, struct lease
*lease
,
3215 struct client_state
*client_state
,
3216 struct option_state
*in_options
,
3217 struct option_state
*cfg_options
,
3218 struct binding_scope
**scope
,
3219 struct universe
*universe
)
3222 struct option_chain_head
*head
;
3223 struct option_cache
*oc
;
3224 unsigned char *data
;
3225 int i
, len
, rval
= 0, count
;
3226 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3228 if (fqdn_universe
.index
>= cfg_options
->universe_count
)
3230 head
= ((struct option_chain_head
*)
3231 cfg_options
->universes
[fqdn_universe
.index
]);
3235 memset(results
, 0, sizeof(results
));
3236 for (ocp
= head
->first
; ocp
!= NULL
; ocp
= ocp
->cdr
) {
3237 oc
= (struct option_cache
*)(ocp
->car
);
3238 if (oc
->option
->code
> FQDN_SUBOPTION_COUNT
)
3239 log_fatal("Impossible condition at %s:%d.", MDL
);
3241 evaluate_option_cache(&results
[oc
->option
->code
], packet
,
3242 lease
, client_state
, in_options
,
3243 cfg_options
, scope
, oc
, MDL
);
3246 /* We add a byte for the flags field at the start of the option.
3247 * We add a byte because we will prepend a label count.
3248 * We add a byte because the input length doesn't include a trailing
3249 * NULL, and we will add a root label.
3251 len
= results
[FQDN_FQDN
].len
+ 3;
3252 if (!buffer_allocate(&result
->buffer
, len
, MDL
)) {
3253 log_error("No memory for virtual option buffer.");
3256 data
= result
->buffer
->data
;
3257 result
->data
= data
;
3259 /* The first byte is the flags field. */
3262 /* XXX: The server should set bit 3 (yes, 3, not 4) to 1 if we
3263 * are not going to perform any DNS updates. The problem is
3264 * that at this layer of abstraction, we do not know if the caller
3265 * is the client or the server.
3267 * See RFC4704 Section 4.1, 'The "N" bit'.
3272 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3273 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3275 if (results
[FQDN_SERVER_UPDATE
].len
&&
3276 results
[FQDN_SERVER_UPDATE
].data
[0])
3279 /* If there is no name, we're done. */
3280 if (results
[FQDN_FQDN
].len
== 0) {
3285 /* Convert textual representation to DNS format. */
3286 count
= fqdn_encode(data
+ 1, len
- 1,
3287 results
[FQDN_FQDN
].data
, results
[FQDN_FQDN
].len
);
3291 data_string_forget(result
, MDL
);
3295 result
->len
+= count
;
3296 result
->terminated
= 0;
3302 for (i
= 1 ; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3304 data_string_forget(&results
[i
], MDL
);
3310 /* Read the DHCPv6 FQDN option's contents into the FQDN virtual space.
3313 fqdn6_universe_decode(struct option_state
*options
,
3314 const unsigned char *buffer
, unsigned length
,
3317 struct buffer
*bp
= NULL
;
3318 unsigned char *first_dot
;
3319 int len
, hlen
, dlen
;
3321 /* The FQDN option has to be at least 1 byte long. */
3325 /* Save the contents of the option in a buffer. There are 3
3326 * one-byte values we record from the packet, so we go ahead
3327 * and allocate a bigger buffer to accommodate them. But the
3328 * 'length' we got (because it is a DNS encoded string) is
3329 * one longer than we need...so we only add two extra octets.
3331 if (!buffer_allocate(&bp
, length
+ 2, MDL
)) {
3332 log_error("No memory for dhcp6.fqdn option buffer.");
3336 /* The v6 FQDN is always 'encoded' per DNS. */
3338 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3339 bp
->data
, 1, FQDN_ENCODED
, 0))
3342 /* XXX: We need to process 'The "N" bit'. */
3344 if (buffer
[0] & 1) /* server-update. */
3349 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 2, 1,
3350 FQDN_SERVER_UPDATE
, 0))
3353 if (buffer
[0] & 2) /* no-client-update. */
3358 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 1, 1,
3359 FQDN_NO_CLIENT_UPDATE
, 0))
3362 /* Convert the domain name to textual representation for config. */
3363 len
= MRns_name_ntop(buffer
+ 1, (char *)bp
->data
+ 3, length
- 1);
3365 log_error("Unable to convert dhcp6.fqdn domain name to "
3370 /* Save the domain name. */
3372 unsigned char *fqdn_start
= bp
->data
+ 3;
3374 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3375 fqdn_start
, len
, FQDN_FQDN
, 1))
3378 first_dot
= (unsigned char *)strchr((char *)fqdn_start
, '.');
3380 if (first_dot
!= NULL
) {
3381 hlen
= first_dot
- fqdn_start
;
3388 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3389 fqdn_start
, len
, FQDN_FQDN
, 1) ||
3391 !save_option_buffer(&fqdn_universe
, options
, bp
,
3393 FQDN_HOSTNAME
, 0)) ||
3395 !save_option_buffer(&fqdn_universe
, options
, bp
,
3396 first_dot
, dlen
, FQDN_DOMAINNAME
, 0)))
3400 buffer_dereference(&bp
, MDL
);
3404 buffer_dereference(&bp
, MDL
);
3408 void option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3409 struct client_state
*client_state
,
3410 struct option_state
*in_options
,
3411 struct option_state
*cfg_options
,
3412 struct binding_scope
**scope
,
3413 struct universe
*u
, void *stuff
,
3414 void (*func
) (struct option_cache
*,
3416 struct lease
*, struct client_state
*,
3417 struct option_state
*,
3418 struct option_state
*,
3419 struct binding_scope
**,
3420 struct universe
*, void *))
3423 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
3424 cfg_options
, scope
, u
, stuff
, func
);
3427 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
3428 struct client_state
*client_state
,
3429 struct option_state
*in_options
,
3430 struct option_state
*cfg_options
,
3431 struct binding_scope
**scope
,
3432 struct universe
*u
, void *stuff
,
3433 void (*func
) (struct option_cache
*,
3435 struct lease
*, struct client_state
*,
3436 struct option_state
*,
3437 struct option_state
*,
3438 struct binding_scope
**,
3439 struct universe
*, void *),
3440 struct option_cache
*oc
,
3443 struct universe
*universe
= find_option_universe (oc
-> option
,
3445 if (universe
-> foreach
)
3446 (*universe
-> foreach
) (packet
, lease
, client_state
,
3447 in_options
, cfg_options
,
3448 scope
, universe
, stuff
, func
);
3451 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3452 struct client_state
*client_state
,
3453 struct option_state
*in_options
,
3454 struct option_state
*cfg_options
,
3455 struct binding_scope
**scope
,
3456 struct universe
*u
, void *stuff
,
3457 void (*func
) (struct option_cache
*,
3460 struct client_state
*,
3461 struct option_state
*,
3462 struct option_state
*,
3463 struct binding_scope
**,
3464 struct universe
*, void *))
3468 struct option_cache
*oc
;
3470 if (cfg_options
-> universe_count
<= u
-> index
)
3473 hash
= cfg_options
-> universes
[u
-> index
];
3476 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3478 /* XXX save _all_ options! XXX */
3479 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3480 oc
= (struct option_cache
*)p
-> car
;
3481 (*func
) (oc
, packet
, lease
, client_state
,
3482 in_options
, cfg_options
, scope
, u
, stuff
);
3488 save_linked_option(struct universe
*universe
, struct option_state
*options
,
3489 struct option_cache
*oc
, isc_boolean_t appendp
)
3492 struct option_chain_head
*head
;
3493 struct option_cache
**ocloc
;
3495 if (universe
-> index
>= options
-> universe_count
)
3497 head
= ((struct option_chain_head
*)
3498 options
-> universes
[universe
-> index
]);
3500 if (!option_chain_head_allocate (((struct option_chain_head
**)
3501 &options
-> universes
3502 [universe
-> index
]), MDL
))
3504 head
= ((struct option_chain_head
*)
3505 options
-> universes
[universe
-> index
]);
3508 /* Find the tail of the list. */
3509 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3510 ocloc
= (struct option_cache
**)&(*tail
)->car
;
3512 if (oc
->option
->code
== (*ocloc
)->option
->code
) {
3515 ocloc
= &(*ocloc
)->next
;
3516 } while (*ocloc
!= NULL
);
3518 option_cache_dereference(ocloc
, MDL
);
3520 option_cache_reference(ocloc
, oc
, MDL
);
3525 *tail
= cons (0, 0);
3527 option_cache_reference ((struct option_cache
**)
3528 (&(*tail
) -> car
), oc
, MDL
);
3532 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
3533 in_options
, cfg_options
, scope
, universe
)
3534 struct data_string
*result
;
3535 struct packet
*packet
;
3536 struct lease
*lease
;
3537 struct client_state
*client_state
;
3538 struct option_state
*in_options
;
3539 struct option_state
*cfg_options
;
3540 struct binding_scope
**scope
;
3541 struct universe
*universe
;
3545 struct option_chain_head
*head
;
3547 if (universe
-> index
>= cfg_options
-> universe_count
)
3549 head
= ((struct option_chain_head
*)
3550 cfg_options
-> universes
[universe
-> index
]);
3554 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3555 if (store_option (result
, universe
, packet
,
3556 lease
, client_state
, in_options
, cfg_options
,
3557 scope
, (struct option_cache
*)(oc
-> car
)))
3561 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3562 in_options
, cfg_options
, scope
, universe
))
3568 void delete_linked_option (universe
, options
, code
)
3569 struct universe
*universe
;
3570 struct option_state
*options
;
3573 pair
*tail
, tmp
= (pair
)0;
3574 struct option_chain_head
*head
;
3576 if (universe
-> index
>= options
-> universe_count
)
3578 head
= ((struct option_chain_head
*)
3579 options
-> universes
[universe
-> index
]);
3583 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3585 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
3587 tmp
= (*tail
) -> cdr
;
3588 option_cache_dereference ((struct option_cache
**)
3589 (&(*tail
) -> car
), MDL
);
3597 struct option_cache
*lookup_linked_option (universe
, options
, code
)
3598 struct universe
*universe
;
3599 struct option_state
*options
;
3603 struct option_chain_head
*head
;
3605 if (universe
-> index
>= options
-> universe_count
)
3607 head
= ((struct option_chain_head
*)
3608 options
-> universes
[universe
-> index
]);
3612 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3614 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
3615 return (struct option_cache
*)(oc
-> car
);
3619 return (struct option_cache
*)0;
3622 int linked_option_state_dereference (universe
, state
, file
, line
)
3623 struct universe
*universe
;
3624 struct option_state
*state
;
3628 return (option_chain_head_dereference
3629 ((struct option_chain_head
**)
3630 (&state
-> universes
[universe
-> index
]), MDL
));
3633 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3634 struct client_state
*client_state
,
3635 struct option_state
*in_options
,
3636 struct option_state
*cfg_options
,
3637 struct binding_scope
**scope
,
3638 struct universe
*u
, void *stuff
,
3639 void (*func
) (struct option_cache
*,
3642 struct client_state
*,
3643 struct option_state
*,
3644 struct option_state
*,
3645 struct binding_scope
**,
3646 struct universe
*, void *))
3649 struct option_chain_head
*head
;
3651 if (u
-> index
>= cfg_options
-> universe_count
)
3653 head
= ((struct option_chain_head
*)
3654 cfg_options
-> universes
[u
-> index
]);
3657 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
3658 (*func
) ((struct option_cache
*)(car
-> car
),
3659 packet
, lease
, client_state
,
3660 in_options
, cfg_options
, scope
, u
, stuff
);
3664 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
3665 struct interface_info
*interface
;
3666 struct dhcp_packet
*packet
;
3668 unsigned int from_port
;
3670 struct hardware
*hfrom
;
3672 struct option_cache
*op
;
3673 struct packet
*decoded_packet
;
3674 #if defined (DEBUG_MEMORY_LEAKAGE)
3675 unsigned long previous_outstanding
= dmalloc_outstanding
;
3678 #if defined (TRACING)
3679 trace_inpacket_stash (interface
, packet
, len
, from_port
, from
, hfrom
);
3682 decoded_packet
= (struct packet
*)0;
3683 if (!packet_allocate (&decoded_packet
, MDL
)) {
3684 log_error ("do_packet: no memory for incoming packet!");
3687 decoded_packet
-> raw
= packet
;
3688 decoded_packet
-> packet_length
= len
;
3689 decoded_packet
-> client_port
= from_port
;
3690 decoded_packet
-> client_addr
= from
;
3691 interface_reference (&decoded_packet
-> interface
, interface
, MDL
);
3692 decoded_packet
-> haddr
= hfrom
;
3694 if (packet
-> hlen
> sizeof packet
-> chaddr
) {
3695 packet_dereference (&decoded_packet
, MDL
);
3696 log_info ("Discarding packet with bogus hlen.");
3700 /* If there's an option buffer, try to parse it. */
3701 if (decoded_packet
-> packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
3702 if (!parse_options (decoded_packet
)) {
3703 if (decoded_packet
-> options
)
3704 option_state_dereference
3705 (&decoded_packet
-> options
, MDL
);
3706 packet_dereference (&decoded_packet
, MDL
);
3710 if (decoded_packet
-> options_valid
&&
3711 (op
= lookup_option (&dhcp_universe
,
3712 decoded_packet
-> options
,
3713 DHO_DHCP_MESSAGE_TYPE
))) {
3714 struct data_string dp
;
3715 memset (&dp
, 0, sizeof dp
);
3716 evaluate_option_cache (&dp
, decoded_packet
,
3718 (struct client_state
*)0,
3719 decoded_packet
-> options
,
3720 (struct option_state
*)0,
3721 (struct binding_scope
**)0,
3724 decoded_packet
-> packet_type
= dp
.data
[0];
3726 decoded_packet
-> packet_type
= 0;
3727 data_string_forget (&dp
, MDL
);
3731 if (decoded_packet
-> packet_type
)
3732 dhcp (decoded_packet
);
3734 bootp (decoded_packet
);
3736 /* If the caller kept the packet, they'll have upped the refcnt. */
3737 packet_dereference (&decoded_packet
, MDL
);
3739 #if defined (DEBUG_MEMORY_LEAKAGE)
3740 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
3742 dmalloc_outstanding
- previous_outstanding
,
3743 dmalloc_outstanding
, dmalloc_longterm
);
3745 #if defined (DEBUG_MEMORY_LEAKAGE)
3746 dmalloc_dump_outstanding ();
3748 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
3749 dump_rc_history (0);
3754 packet6_len_okay(const char *packet
, int len
) {
3758 if ((packet
[0] == DHCPV6_RELAY_FORW
) ||
3759 (packet
[0] == DHCPV6_RELAY_REPL
)) {
3760 if (len
>= sizeof(struct dhcpv6_relay_packet
)) {
3766 if (len
>= sizeof(struct dhcpv6_packet
)) {
3776 do_packet6(struct interface_info
*interface
, const char *packet
,
3777 int len
, int from_port
, const struct iaddr
*from
,
3778 isc_boolean_t was_unicast
) {
3779 unsigned char msg_type
;
3780 const struct dhcpv6_packet
*msg
;
3781 const struct dhcpv6_relay_packet
*relay
;
3782 struct packet
*decoded_packet
;
3784 if (!packet6_len_okay(packet
, len
)) {
3785 log_info("do_packet6: "
3786 "short packet from %s port %d, len %d, dropped",
3787 piaddr(*from
), from_port
, len
);
3791 decoded_packet
= NULL
;
3792 if (!packet_allocate(&decoded_packet
, MDL
)) {
3793 log_error("do_packet6: no memory for incoming packet.");
3797 if (!option_state_allocate(&decoded_packet
->options
, MDL
)) {
3798 log_error("do_packet6: no memory for options.");
3799 packet_dereference(&decoded_packet
, MDL
);
3803 /* IPv4 information, already set to 0 */
3804 /* decoded_packet->packet_type = 0; */
3805 /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
3806 /* decoded_packet->circuit_id = NULL; */
3807 /* decoded_packet->circuit_id_len = 0; */
3808 /* decoded_packet->remote_id = NULL; */
3809 /* decoded_packet->remote_id_len = 0; */
3810 decoded_packet
->raw
= (struct dhcp_packet
*) packet
;
3811 decoded_packet
->packet_length
= (unsigned) len
;
3812 decoded_packet
->client_port
= from_port
;
3813 decoded_packet
->client_addr
= *from
;
3814 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
3816 decoded_packet
->unicast
= was_unicast
;
3818 msg_type
= packet
[0];
3819 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
3820 (msg_type
== DHCPV6_RELAY_REPL
)) {
3821 relay
= (const struct dhcpv6_relay_packet
*)packet
;
3822 decoded_packet
->dhcpv6_msg_type
= relay
->msg_type
;
3824 /* relay-specific data */
3825 decoded_packet
->dhcpv6_hop_count
= relay
->hop_count
;
3826 memcpy(&decoded_packet
->dhcpv6_link_address
,
3827 relay
->link_address
, sizeof(relay
->link_address
));
3828 memcpy(&decoded_packet
->dhcpv6_peer_address
,
3829 relay
->peer_address
, sizeof(relay
->peer_address
));
3831 if (!parse_option_buffer(decoded_packet
->options
,
3832 relay
->options
, len
-sizeof(*relay
),
3833 &dhcpv6_universe
)) {
3834 /* no logging here, as parse_option_buffer() logs all
3835 cases where it fails */
3836 packet_dereference(&decoded_packet
, MDL
);
3840 msg
= (const struct dhcpv6_packet
*)packet
;
3841 decoded_packet
->dhcpv6_msg_type
= msg
->msg_type
;
3843 /* message-specific data */
3844 memcpy(decoded_packet
->dhcpv6_transaction_id
,
3845 msg
->transaction_id
,
3846 sizeof(decoded_packet
->dhcpv6_transaction_id
));
3848 if (!parse_option_buffer(decoded_packet
->options
,
3849 msg
->options
, len
-sizeof(*msg
),
3850 &dhcpv6_universe
)) {
3851 /* no logging here, as parse_option_buffer() logs all
3852 cases where it fails */
3853 packet_dereference(&decoded_packet
, MDL
);
3858 dhcpv6(decoded_packet
);
3860 packet_dereference(&decoded_packet
, MDL
);
3865 pretty_escape(char **dst
, char *dend
, const unsigned char **src
,
3866 const unsigned char *send
)
3870 /* If there aren't as many bytes left as there are in the source
3871 * buffer, don't even bother entering the loop.
3873 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3874 *dst
== NULL
|| *src
== NULL
|| (*dst
>= dend
) || (*src
> send
) ||
3875 ((send
- *src
) > (dend
- *dst
)))
3878 for ( ; *src
< send
; (*src
)++) {
3879 if (!isascii (**src
) || !isprint (**src
)) {
3880 /* Skip trailing NUL. */
3881 if ((*src
+ 1) != send
|| **src
!= '\0') {
3882 if (*dst
+ 4 > dend
)
3885 sprintf(*dst
, "\\%03o",
3890 } else if (**src
== '"' || **src
== '\'' || **src
== '$' ||
3891 **src
== '`' || **src
== '\\') {
3892 if (*dst
+ 2 > dend
)
3901 if (*dst
+ 1 > dend
)
3914 pretty_text(char **dst
, char *dend
, const unsigned char **src
,
3915 const unsigned char *send
, int emit_quotes
)
3919 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3920 *dst
== NULL
|| *src
== NULL
||
3921 ((*dst
+ (emit_quotes
? 2 : 0)) > dend
) || (*src
> send
))
3929 /* dend-1 leaves 1 byte for the closing quote. */
3930 count
= pretty_escape(dst
, dend
- (emit_quotes
? 1 : 0), src
, send
);
3935 if (emit_quotes
&& (*dst
< dend
)) {
3939 /* Includes quote prior to pretty_escape(); */
3947 pretty_domain(char **dst
, char *dend
, const unsigned char **src
,
3948 const unsigned char *send
)
3950 const unsigned char *tend
;
3954 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3955 *dst
== NULL
|| *src
== NULL
||
3956 ((*dst
+ 2) > dend
) || (*src
>= send
))
3963 /* Continue loop until end of src buffer. */
3967 /* Consume tag size. */
3971 /* At root, finis. */
3975 tend
= (*src
) + tsiz
;
3977 /* If the tag exceeds the source buffer, it's illegal.
3978 * This should also trap compression pointers (which should
3979 * not be in these buffers).
3984 /* dend-2 leaves room for a trailing dot and quote. */
3985 status
= pretty_escape(dst
, dend
-2, src
, tend
);
3987 if ((status
== -1) || ((*dst
+ 2) > dend
))
3992 count
+= status
+ 1;
4003 * Add the option identified with the option number and data to the
4007 add_option(struct option_state
*options
,
4008 unsigned int option_num
,
4010 unsigned int data_len
)
4012 struct option_cache
*oc
;
4013 struct option
*option
;
4015 /* INSIST(options != NULL); */
4016 /* INSIST(data != NULL); */
4019 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
4020 &option_num
, 0, MDL
)) {
4021 log_error("Attempting to add unknown option %d.", option_num
);
4026 if (!option_cache_allocate(&oc
, MDL
)) {
4027 log_error("No memory for option cache adding %s (option %d).",
4028 option
->name
, option_num
);
4032 if (!make_const_data(&oc
->expression
,
4038 log_error("No memory for constant data adding %s (option %d).",
4039 option
->name
, option_num
);
4040 option_cache_dereference(&oc
, MDL
);
4044 option_reference(&(oc
->option
), option
, MDL
);
4045 save_option(&dhcp_universe
, options
, oc
);
4046 option_cache_dereference(&oc
, MDL
);