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
;
140 char *reason
= "general failure";
142 if (!buffer_allocate (&bp
, length
, MDL
)) {
143 log_error ("no memory for option buffer.");
146 memcpy (bp
-> data
, buffer
, length
);
149 (offset
+ universe
->tag_size
) <= length
&&
150 (code
= universe
->get_tag(buffer
+ offset
)) != universe
->end
; ) {
151 offset
+= universe
->tag_size
;
153 /* Pad options don't have a length - just skip them. */
157 /* Don't look for length if the buffer isn't that big. */
158 if ((offset
+ universe
->length_size
) > length
) {
159 reason
= "code tag at end of buffer - missing "
164 /* All other fields (except PAD and END handled above)
165 * have a length field, unless it's a DHCPv6 zero-length
166 * options space (eg any of the enterprise-id'd options).
168 * Zero-length-size option spaces basically consume the
169 * entire options buffer, so have at it.
171 if (universe
->get_length
!= NULL
)
172 len
= universe
->get_length(buffer
+ offset
);
173 else if (universe
->length_size
== 0)
174 len
= length
- universe
->tag_size
;
176 log_fatal("Improperly configured option space(%s): "
177 "may not have a nonzero length size "
178 "AND a NULL get_length function.",
181 /* Silence compiler warnings. */
185 offset
+= universe
->length_size
;
187 option_code_hash_lookup(&option
, universe
->code_hash
, &code
,
190 /* If the length is outrageous, the options are bad. */
191 if (offset
+ len
> length
) {
192 reason
= "option length exceeds option buffer length";
194 log_error("parse_option_buffer: malformed option "
195 "%s.%s (code %u): %s.", universe
->name
,
196 option
? option
->name
: "<unknown>",
198 buffer_dereference (&bp
, MDL
);
202 /* If the option contains an encapsulation, parse it. If
203 the parse fails, or the option isn't an encapsulation (by
204 far the most common case), or the option isn't entirely
205 an encapsulation, keep the raw data as well. */
207 (option
->format
[0] == 'e' ||
208 option
->format
[0] == 'E') &&
209 (parse_encapsulated_suboptions(options
, option
,
210 bp
->data
+ offset
, len
,
212 op
= lookup_option(universe
, options
, code
);
214 if (op
!= NULL
&& universe
->concat_duplicates
) {
215 struct data_string
new;
216 memset(&new, 0, sizeof new);
217 if (!buffer_allocate(&new.buffer
,
220 log_error("parse_option_buffer: "
222 buffer_dereference(&bp
, MDL
);
225 /* Copy old option to new data object. */
226 memcpy(new.buffer
->data
, op
->data
.data
,
228 /* Concat new option behind old. */
229 memcpy(new.buffer
->data
+ op
->data
.len
,
230 bp
->data
+ offset
, len
);
231 new.len
= op
->data
.len
+ len
;
232 new.data
= new.buffer
->data
;
233 /* Save new concat'd object. */
234 data_string_forget(&op
->data
, MDL
);
235 data_string_copy(&op
->data
, &new, MDL
);
236 data_string_forget(&new, MDL
);
237 } else if (op
!= NULL
) {
238 /* We must append this statement onto the
241 while (op
->next
!= NULL
)
244 if (!option_cache_allocate(&nop
, MDL
)) {
245 log_error("parse_option_buffer: "
247 buffer_dereference(&bp
, MDL
);
251 option_reference(&nop
->option
, op
->option
, MDL
);
253 nop
->data
.buffer
= NULL
;
254 buffer_reference(&nop
->data
.buffer
, bp
, MDL
);
255 nop
->data
.data
= bp
->data
+ offset
;
258 option_cache_reference(&op
->next
, nop
, MDL
);
259 option_cache_dereference(&nop
, MDL
);
261 save_option_buffer(universe
, options
, bp
,
262 bp
->data
+ offset
, len
,
266 option_dereference(&option
, MDL
);
269 buffer_dereference (&bp
, MDL
);
273 /* If an option in an option buffer turns out to be an encapsulation,
274 figure out what to do. If we don't know how to de-encapsulate it,
275 or it's not well-formed, return zero; otherwise, return 1, indicating
276 that we succeeded in de-encapsulating it. */
278 struct universe
*find_option_universe (struct option
*eopt
, const char *uname
)
282 struct universe
*universe
= (struct universe
*)0;
284 /* Look for the E option in the option format. */
285 s
= strchr (eopt
-> format
, 'E');
287 log_error ("internal encapsulation format error 1.");
290 /* Look for the universe name in the option format. */
291 t
= strchr (++s
, '.');
292 /* If there was no trailing '.', or there's something after the
293 trailing '.', the option is bogus and we can't use it. */
295 log_error ("internal encapsulation format error 2.");
298 if (t
== s
&& uname
) {
299 for (i
= 0; i
< universe_count
; i
++) {
300 if (!strcmp (universes
[i
] -> name
, uname
)) {
301 universe
= universes
[i
];
306 for (i
= 0; i
< universe_count
; i
++) {
307 if (strlen (universes
[i
] -> name
) == t
- s
&&
308 !memcmp (universes
[i
] -> name
,
309 s
, (unsigned)(t
- s
))) {
310 universe
= universes
[i
];
318 /* If an option in an option buffer turns out to be an encapsulation,
319 figure out what to do. If we don't know how to de-encapsulate it,
320 or it's not well-formed, return zero; otherwise, return 1, indicating
321 that we succeeded in de-encapsulating it. */
323 int parse_encapsulated_suboptions (struct option_state
*options
,
325 const unsigned char *buffer
,
326 unsigned len
, struct universe
*eu
,
330 struct universe
*universe
= find_option_universe (eopt
, uname
);
332 /* If we didn't find the universe, we can't do anything with it
333 right now (e.g., we can't decode vendor options until we've
334 decoded the packet and executed the scopes that it matches). */
338 /* If we don't have a decoding function for it, we can't decode
340 if (!universe
-> decode
)
343 i
= (*universe
-> decode
) (options
, buffer
, len
, universe
);
345 /* If there is stuff before the suboptions, we have to keep it. */
346 if (eopt
-> format
[0] != 'E')
348 /* Otherwise, return the status of the decode function. */
352 int fqdn_universe_decode (struct option_state
*options
,
353 const unsigned char *buffer
,
354 unsigned length
, struct universe
*u
)
356 struct buffer
*bp
= (struct buffer
*)0;
358 /* FQDN options have to be at least four bytes long. */
362 /* Save the contents of the option in a buffer. */
363 if (!buffer_allocate (&bp
, length
+ 4, MDL
)) {
364 log_error ("no memory for option buffer.");
367 memcpy (&bp
-> data
[3], buffer
+ 1, length
- 1);
369 if (buffer
[0] & 4) /* encoded */
373 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
374 bp
->data
, 1, FQDN_ENCODED
, 0)) {
376 buffer_dereference (&bp
, MDL
);
380 if (buffer
[0] & 1) /* server-update */
384 if (buffer
[0] & 2) /* no-client-update */
389 /* XXX Ideally we should store the name in DNS format, so if the
390 XXX label isn't in DNS format, we convert it to DNS format,
391 XXX rather than converting labels specified in DNS format to
392 XXX the plain ASCII representation. But that's hard, so
395 /* Not encoded using DNS format? */
396 if (!bp
-> data
[0]) {
399 /* Some broken clients NUL-terminate this option. */
400 if (buffer
[length
- 1] == 0) {
405 /* Determine the length of the hostname component of the
406 name. If the name contains no '.' character, it
407 represents a non-qualified label. */
408 for (i
= 3; i
< length
&& buffer
[i
] != '.'; i
++);
411 /* Note: If the client sends a FQDN, the first '.' will
412 be used as a NUL terminator for the hostname. */
413 if (i
&& (!save_option_buffer(&fqdn_universe
, options
, bp
,
417 /* Note: If the client sends a single label, the
418 FQDN_DOMAINNAME option won't be set. */
419 if (length
> 4 + i
&&
420 (!save_option_buffer(&fqdn_universe
, options
, bp
,
421 &bp
-> data
[6 + i
], length
- 4 - i
,
422 FQDN_DOMAINNAME
, 1)))
424 /* Also save the whole name. */
426 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
427 &bp
-> data
[5], length
- 3,
433 unsigned total_len
= 0;
434 unsigned first_len
= 0;
440 while (s
< &bp
-> data
[0] + length
+ 2) {
443 log_info ("fancy bits in fqdn option");
450 if (s
+ len
> &bp
-> data
[0] + length
+ 3) {
451 log_info ("fqdn tag longer than buffer");
455 if (first_len
== 0) {
461 total_len
+= len
+ 1;
464 /* We wind up with a length that's one too many because
465 we shouldn't increment for the last label, but there's
466 no way to tell we're at the last label until we exit
472 first_len
= total_len
;
476 !save_option_buffer(&fqdn_universe
, options
, bp
,
477 &bp
-> data
[6], first_len
,
480 if (total_len
> 0 && first_len
!= total_len
) {
481 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
482 &bp
->data
[6 + first_len
],
483 total_len
- first_len
,
488 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
489 &bp
-> data
[6], total_len
,
494 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
496 FQDN_NO_CLIENT_UPDATE
, 0))
498 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
500 FQDN_SERVER_UPDATE
, 0))
503 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
507 if (!save_option_buffer (&fqdn_universe
, options
, bp
,
512 buffer_dereference (&bp
, MDL
);
517 * Load all options into a buffer, and then split them out into the three
518 * separate fields in the dhcp packet (options, file, and sname) where
519 * options can be stored.
522 cons_options(struct packet
*inpacket
, struct dhcp_packet
*outpacket
,
523 struct lease
*lease
, struct client_state
*client_state
,
524 int mms
, struct option_state
*in_options
,
525 struct option_state
*cfg_options
,
526 struct binding_scope
**scope
,
527 int overload_avail
, int terminate
, int bootpp
,
528 struct data_string
*prl
, const char *vuname
)
530 #define PRIORITY_COUNT 300
531 unsigned priority_list
[PRIORITY_COUNT
];
533 unsigned char buffer
[4096], agentopts
[1024];
535 unsigned mb_size
= 0, mb_max
= 0;
536 unsigned option_size
= 0, agent_size
= 0;
539 struct option_cache
*op
;
540 struct data_string ds
;
542 int overload_used
= 0;
543 int of1
= 0, of2
= 0;
545 memset(&ds
, 0, sizeof ds
);
548 * If there's a Maximum Message Size option in the incoming packet
549 * and no alternate maximum message size has been specified, or
550 * if the one specified in the packet is shorter than the
551 * alternative, take the one in the packet.
555 (op
= lookup_option(&dhcp_universe
, inpacket
->options
,
556 DHO_DHCP_MAX_MESSAGE_SIZE
))) {
557 evaluate_option_cache(&ds
, inpacket
,
558 lease
, client_state
, in_options
,
559 cfg_options
, scope
, op
, MDL
);
560 if (ds
.len
>= sizeof (u_int16_t
)) {
561 i
= getUShort(ds
.data
);
562 if(!mms
|| (i
< mms
))
565 data_string_forget(&ds
, MDL
);
569 * If the client has provided a maximum DHCP message size,
570 * use that, up to the MTU limit. Otherwise, if it's BOOTP,
571 * only 64 bytes; otherwise use up to the minimum IP MTU size
574 * XXX if a BOOTP client specifies a max message size, we will
578 if (mms
< DHCP_MTU_MIN
)
579 /* Enforce minimum packet size, per RFC 2132 */
580 mb_size
= DHCP_MIN_OPTION_LEN
;
581 else if (mms
> DHCP_MTU_MAX
)
583 * TODO: Packets longer than 1500 bytes really
584 * should be allowed, but it requires upstream
585 * changes to the way the packet is allocated. For
586 * now, we forbid them. They won't be needed very
589 mb_size
= DHCP_MAX_OPTION_LEN
;
591 mb_size
= mms
- DHCP_FIXED_LEN
;
594 if (inpacket
!= NULL
&&
595 (inpacket
->packet_length
- DHCP_FIXED_LEN
>= 64))
596 mb_size
= inpacket
->packet_length
- DHCP_FIXED_LEN
;
598 mb_size
= DHCP_MIN_OPTION_LEN
;
601 * If answering a client message, see whether any relay agent
602 * options were included with the message. If so, save them
603 * to copy back in later, and make space in the main buffer
604 * to accommodate them
606 if (client_state
== NULL
) {
607 priority_list
[0] = DHO_DHCP_AGENT_OPTIONS
;
609 agent_size
= store_options(NULL
, agentopts
, 0,
611 inpacket
, lease
, client_state
,
612 in_options
, cfg_options
, scope
,
613 priority_list
, priority_len
,
616 mb_size
+= agent_size
;
617 if (mb_size
> DHCP_MAX_OPTION_LEN
)
618 mb_size
= DHCP_MAX_OPTION_LEN
;
622 * Set offsets for buffer data to be copied into filename
623 * and servername fields
627 if (overload_avail
& 1) {
629 mb_max
+= DHCP_FILE_LEN
;
632 if (overload_avail
& 2) {
634 mb_max
+= DHCP_SNAME_LEN
;
638 * Preload the option priority list with protocol-mandatory options.
639 * This effectively gives these options the highest priority.
642 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE_TYPE
;
643 priority_list
[priority_len
++] = DHO_DHCP_SERVER_IDENTIFIER
;
644 priority_list
[priority_len
++] = DHO_DHCP_LEASE_TIME
;
645 priority_list
[priority_len
++] = DHO_DHCP_MESSAGE
;
646 priority_list
[priority_len
++] = DHO_DHCP_REQUESTED_ADDRESS
;
647 priority_list
[priority_len
++] = DHO_ASSOCIATED_IP
;
649 if (prl
!= NULL
&& prl
->len
> 0) {
650 if ((op
= lookup_option(&dhcp_universe
, cfg_options
,
651 DHO_SUBNET_SELECTION
))) {
652 if (priority_len
< PRIORITY_COUNT
)
653 priority_list
[priority_len
++] =
654 DHO_SUBNET_SELECTION
;
657 data_string_truncate(prl
, (PRIORITY_COUNT
- priority_len
));
659 for (i
= 0; i
< prl
->len
; i
++) {
661 * Prevent client from changing order of delivery
662 * of relay agent information option.
664 if (prl
->data
[i
] != DHO_DHCP_AGENT_OPTIONS
)
665 priority_list
[priority_len
++] = prl
->data
[i
];
669 * If the client doesn't request the FQDN option explicitly,
670 * to indicate priority, consider it lowest priority. Fit
671 * in the packet if there is space. Note that the option
672 * may only be included if the client supplied one.
674 if ((priority_len
< PRIORITY_COUNT
) &&
675 (lookup_option(&fqdn_universe
, inpacket
->options
,
676 FQDN_ENCODED
) != NULL
))
677 priority_list
[priority_len
++] = DHO_FQDN
;
680 * Some DHCP Servers will give the subnet-mask option if
681 * it is not on the parameter request list - so some client
682 * implementations have come to rely on this - so we will
683 * also make sure we supply this, at lowest priority.
685 * This is only done in response to DHCPDISCOVER or
686 * DHCPREQUEST messages, to avoid providing the option on
687 * DHCPINFORM or DHCPLEASEQUERY responses (if the client
688 * didn't request it).
690 if ((priority_len
< PRIORITY_COUNT
) &&
691 ((inpacket
->packet_type
== DHCPDISCOVER
) ||
692 (inpacket
->packet_type
== DHCPREQUEST
)))
693 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
696 * First, hardcode some more options that ought to be
697 * sent first...these are high priority to have in the
700 priority_list
[priority_len
++] = DHO_SUBNET_MASK
;
701 priority_list
[priority_len
++] = DHO_ROUTERS
;
702 priority_list
[priority_len
++] = DHO_DOMAIN_NAME_SERVERS
;
703 priority_list
[priority_len
++] = DHO_HOST_NAME
;
704 priority_list
[priority_len
++] = DHO_FQDN
;
707 * Append a list of the standard DHCP options from the
708 * standard DHCP option space. Actually, if a site
709 * option space hasn't been specified, we wind up
710 * treating the dhcp option space as the site option
711 * space, and the first for loop is skipped, because
712 * it's slightly more general to do it this way,
713 * taking the 1Q99 DHCP futures work into account.
715 if (cfg_options
->site_code_min
) {
716 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
717 hash
= cfg_options
->universes
[dhcp_universe
.index
];
719 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
720 op
= (struct option_cache
*)(pp
->car
);
721 if (op
->option
->code
<
722 cfg_options
->site_code_min
&&
723 priority_len
< PRIORITY_COUNT
&&
724 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
725 priority_list
[priority_len
++] =
733 * Now cycle through the site option space, or if there
734 * is no site option space, we'll be cycling through the
737 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
738 hash
= cfg_options
->universes
[cfg_options
->site_universe
];
740 for (pp
= hash
[i
]; pp
; pp
= pp
->cdr
) {
741 op
= (struct option_cache
*)(pp
->car
);
742 if (op
->option
->code
>=
743 cfg_options
->site_code_min
&&
744 priority_len
< PRIORITY_COUNT
&&
745 op
->option
->code
!= DHO_DHCP_AGENT_OPTIONS
)
746 priority_list
[priority_len
++] =
752 * Put any spaces that are encapsulated on the list,
753 * sort out whether they contain values later.
755 for (i
= 0; i
< cfg_options
->universe_count
; i
++) {
756 if (universes
[i
]->enc_opt
&&
757 priority_len
< PRIORITY_COUNT
&&
758 universes
[i
]->enc_opt
->universe
== &dhcp_universe
) {
759 if (universes
[i
]->enc_opt
->code
!=
760 DHO_DHCP_AGENT_OPTIONS
)
761 priority_list
[priority_len
++] =
762 universes
[i
]->enc_opt
->code
;
767 * The vendor option space can't stand on its own, so always
768 * add it to the list.
770 if (priority_len
< PRIORITY_COUNT
)
771 priority_list
[priority_len
++] =
772 DHO_VENDOR_ENCAPSULATED_OPTIONS
;
775 /* Put the cookie up front... */
776 memcpy(buffer
, DHCP_OPTIONS_COOKIE
, 4);
779 /* Copy the options into the big buffer... */
780 option_size
= store_options(&overload_used
, buffer
, index
, mb_max
,
781 inpacket
, lease
, client_state
,
782 in_options
, cfg_options
, scope
,
783 priority_list
, priority_len
,
784 of1
, of2
, terminate
, vuname
);
786 /* If store_options() failed */
787 if (option_size
== 0)
790 /* How much was stored in the main buffer? */
791 index
+= option_size
;
794 * If we're going to have to overload, store the overload
798 if (mb_size
- agent_size
- index
< 3)
801 buffer
[index
++] = DHO_DHCP_OPTION_OVERLOAD
;
803 buffer
[index
++] = overload_used
;
805 if (overload_used
& 1)
806 memcpy(outpacket
->file
, &buffer
[of1
], DHCP_FILE_LEN
);
808 if (overload_used
& 2)
809 memcpy(outpacket
->sname
, &buffer
[of2
], DHCP_SNAME_LEN
);
812 /* Now copy in preserved agent options, if any */
814 if (mb_size
- index
>= agent_size
) {
815 memcpy(&buffer
[index
], agentopts
, agent_size
);
818 log_error("Unable to store relay agent information "
822 /* Tack a DHO_END option onto the packet if we need to. */
824 buffer
[index
++] = DHO_END
;
826 /* Copy main buffer into the options buffer of the packet */
827 memcpy(outpacket
->options
, buffer
, index
);
829 /* Figure out the length. */
830 length
= DHCP_FIXED_NON_UDP
+ index
;
835 * XXX: We currently special case collecting VSIO options.
836 * We should be able to handle this in a more generic fashion, by
837 * including any encapsulated options that are present and desired.
838 * This will look something like the VSIO handling VSIO code.
839 * We may also consider handling the ORO-like options within
840 * encapsulated spaces.
850 vsio_options(struct option_cache
*oc
,
851 struct packet
*packet
,
852 struct lease
*dummy_lease
,
853 struct client_state
*dummy_client_state
,
854 struct option_state
*dummy_opt_state
,
855 struct option_state
*opt_state
,
856 struct binding_scope
**dummy_binding_scope
,
857 struct universe
*universe
,
858 void *void_vsio_state
) {
859 struct vsio_state
*vs
= (struct vsio_state
*)void_vsio_state
;
860 struct data_string ds
;
863 memset(&ds
, 0, sizeof(ds
));
864 if (evaluate_option_cache(&ds
, packet
, NULL
,
865 NULL
, opt_state
, NULL
,
866 &global_scope
, oc
, MDL
)) {
867 total_len
= ds
.len
+ universe
->tag_size
+ universe
->length_size
;
868 if (total_len
<= (vs
->buflen
- vs
->bufpos
)) {
869 if (universe
->tag_size
== 1) {
870 vs
->buf
[vs
->bufpos
++] = oc
->option
->code
;
871 } else if (universe
->tag_size
== 2) {
872 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
875 } else if (universe
->tag_size
== 4) {
876 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
880 if (universe
->length_size
== 1) {
881 vs
->buf
[vs
->bufpos
++] = ds
.len
;
882 } else if (universe
->length_size
== 2) {
883 putUShort((unsigned char *)vs
->buf
+vs
->bufpos
,
886 } else if (universe
->length_size
== 4) {
887 putULong((unsigned char *)vs
->buf
+vs
->bufpos
,
891 memcpy(vs
->buf
+ vs
->bufpos
, ds
.data
, ds
.len
);
892 vs
->bufpos
+= ds
.len
;
894 log_debug("No space for option %d in VSIO space %s.",
895 oc
->option
->code
, universe
->name
);
897 data_string_forget(&ds
, MDL
);
899 log_error("Error evaluating option %d in VSIO space %s.",
900 oc
->option
->code
, universe
->name
);
905 * Stores the options from the DHCPv6 universe into the buffer given.
907 * Required options are given as a 0-terminated list of option codes.
908 * Once those are added, the ORO is consulted.
912 store_options6(char *buf
, int buflen
,
913 struct option_state
*opt_state
,
914 struct packet
*packet
,
915 const int *required_opts
,
916 struct data_string
*oro
) {
918 struct option_cache
*oc
;
920 struct data_string ds
;
924 int in_required_opts
;
925 int vsio_option_code
;
927 struct vsio_state vs
;
934 * Find the option code for the VSIO universe.
936 vsio_option_code
= 0;
937 o
= vsio_universe
.enc_opt
;
939 if (o
->universe
== &dhcpv6_universe
) {
940 vsio_option_code
= o
->code
;
943 o
= o
->universe
->enc_opt
;
945 if (vsio_option_code
== 0) {
946 log_fatal("No VSIO option code found.");
949 if (required_opts
!= NULL
) {
950 for (i
=0; required_opts
[i
] != 0; i
++) {
951 if (required_opts
[i
] == vsio_option_code
) {
955 oc
= lookup_option(&dhcpv6_universe
,
956 opt_state
, required_opts
[i
]);
960 memset(&ds
, 0, sizeof(ds
));
961 for (; oc
!= NULL
; oc
= oc
->next
) {
962 if (evaluate_option_cache(&ds
, packet
, NULL
,
968 tmp
= (unsigned char *)buf
;
974 putUShort(tmp
+2, ds
.len
);
976 memcpy(tmp
+4, ds
.data
, ds
.len
);
977 /* update position */
978 bufpos
+= (4 + ds
.len
);
980 log_debug("No space for "
984 data_string_forget(&ds
, MDL
);
986 log_error("Error evaluating option %d",
996 oro_size
= oro
->len
/ 2;
998 for (i
=0; i
<oro_size
; i
++) {
999 memcpy(&code
, oro
->data
+(i
*2), 2);
1003 * See if we've already included this option because
1006 in_required_opts
= 0;
1007 if (required_opts
!= NULL
) {
1008 for (j
=0; required_opts
[j
] != 0; j
++) {
1009 if (required_opts
[j
] == code
) {
1010 in_required_opts
= 1;
1015 if (in_required_opts
) {
1020 * See if this is the VSIO option.
1022 if (code
== vsio_option_code
) {
1027 * Not already added, find this option.
1029 oc
= lookup_option(&dhcpv6_universe
, opt_state
, code
);
1030 memset(&ds
, 0, sizeof(ds
));
1031 for (; oc
!= NULL
; oc
= oc
->next
) {
1032 if (evaluate_option_cache(&ds
, packet
, NULL
, NULL
,
1034 &global_scope
, oc
, MDL
)) {
1035 if ((ds
.len
+ 4) <= (buflen
- bufpos
)) {
1036 tmp
= (unsigned char *)buf
+ bufpos
;
1038 putUShort(tmp
, code
);
1040 putUShort(tmp
+2, ds
.len
);
1042 memcpy(tmp
+4, ds
.data
, ds
.len
);
1043 /* update position */
1044 bufpos
+= (4 + ds
.len
);
1046 log_debug("No space for option %d",
1049 data_string_forget(&ds
, MDL
);
1051 log_error("Error evaluating option %d", code
);
1057 for (i
=0; i
< opt_state
->universe_count
; i
++) {
1058 if (opt_state
->universes
[i
] != NULL
) {
1059 o
= universes
[i
]->enc_opt
;
1061 (o
->universe
== &vsio_universe
)) {
1063 * Add the data from this VSIO option.
1067 vs
.bufpos
= bufpos
+8;
1068 option_space_foreach(packet
, NULL
,
1077 * If there was actually data here,
1080 if (vs
.bufpos
> bufpos
+8) {
1081 tmp
= (unsigned char *)buf
+
1086 vs
.bufpos
-bufpos
-4);
1087 putULong(tmp
+4, o
->code
);
1100 * Store all the requested options into the requested buffer.
1101 * XXX: ought to be static
1104 store_options(int *ocount
,
1105 unsigned char *buffer
, unsigned index
, unsigned buflen
,
1106 struct packet
*packet
, struct lease
*lease
,
1107 struct client_state
*client_state
,
1108 struct option_state
*in_options
,
1109 struct option_state
*cfg_options
,
1110 struct binding_scope
**scope
,
1111 unsigned *priority_list
, int priority_len
,
1112 unsigned first_cutoff
, int second_cutoff
, int terminate
,
1115 int bufix
= 0, six
= 0, tix
= 0;
1119 int bufend
, sbufend
;
1120 struct data_string od
;
1121 struct option_cache
*oc
;
1122 struct option
*option
= NULL
;
1126 * These arguments are relative to the start of the buffer, so
1127 * reduce them by the current buffer index, and advance the
1128 * buffer pointer to where we're going to start writing.
1130 buffer
= &buffer
[index
];
1133 first_cutoff
-= index
;
1135 second_cutoff
-= index
;
1137 /* Calculate the start and end of each section of the buffer */
1138 bufend
= sbufend
= buflen
;
1140 if (first_cutoff
>= buflen
)
1141 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL
);
1142 bufend
= first_cutoff
;
1144 if (second_cutoff
) {
1145 if (second_cutoff
>= buflen
)
1146 log_fatal("%s:%d:store_options: Invalid second cutoff.",
1148 sbufend
= second_cutoff
;
1150 } else if (second_cutoff
) {
1151 if (second_cutoff
>= buflen
)
1152 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL
);
1153 bufend
= second_cutoff
;
1156 memset (&od
, 0, sizeof od
);
1158 /* Eliminate duplicate options from the parameter request list.
1159 * Enforce RFC-mandated ordering of options that are present.
1161 for (i
= 0; i
< priority_len
- 1; i
++) {
1162 /* Eliminate duplicates. */
1164 for (ix
= i
+ 1; ix
< priority_len
+ tto
; ix
++) {
1166 priority_list
[ix
- tto
] =
1168 if (priority_list
[i
] == priority_list
[ix
]) {
1174 /* Enforce ordering of SUBNET_MASK options, according to
1175 * RFC2132 Section 3.3:
1177 * If both the subnet mask and the router option are
1178 * specified in a DHCP reply, the subnet mask option MUST
1181 * This guidance does not specify what to do if the client
1182 * PRL explicitly requests the options out of order, it is
1183 * a general statement.
1185 if (priority_list
[i
] == DHO_SUBNET_MASK
) {
1186 for (ix
= i
- 1 ; ix
>= 0 ; ix
--) {
1187 if (priority_list
[ix
] == DHO_ROUTERS
) {
1189 priority_list
[ix
] = DHO_SUBNET_MASK
;
1190 priority_list
[i
] = DHO_ROUTERS
;
1197 /* Copy out the options in the order that they appear in the
1199 for (i
= 0; i
< priority_len
; i
++) {
1200 /* Number of bytes left to store (some may already
1201 have been stored by a previous pass). */
1203 int optstart
, soptstart
, toptstart
;
1205 int have_encapsulation
= 0;
1206 struct data_string encapsulation
;
1209 memset (&encapsulation
, 0, sizeof encapsulation
);
1210 have_encapsulation
= 0;
1213 option_dereference(&option
, MDL
);
1215 /* Code for next option to try to store. */
1216 code
= priority_list
[i
];
1218 /* Look up the option in the site option space if the code
1219 is above the cutoff, otherwise in the DHCP option space. */
1220 if (code
>= cfg_options
-> site_code_min
)
1221 u
= universes
[cfg_options
-> site_universe
];
1225 oc
= lookup_option (u
, cfg_options
, code
);
1227 if (oc
&& oc
->option
)
1228 option_reference(&option
, oc
->option
, MDL
);
1230 option_code_hash_lookup(&option
, u
->code_hash
, &code
, 0, MDL
);
1232 /* If it's a straight encapsulation, and the user supplied a
1233 * value for the entire option, use that. Otherwise, search
1234 * the encapsulated space.
1236 * If it's a limited encapsulation with preceding data, and the
1237 * user supplied values for the preceding bytes, search the
1238 * encapsulated space.
1240 if ((option
!= NULL
) &&
1241 (((oc
== NULL
) && (option
->format
[0] == 'E')) ||
1242 ((oc
!= NULL
) && (option
->format
[0] == 'e')))) {
1244 struct option_cache
*tmp
;
1245 struct data_string name
;
1247 s
= strchr (option
->format
, 'E');
1249 t
= strchr (++s
, '.');
1251 memset (&name
, 0, sizeof name
);
1253 /* A zero-length universe name means the vendor
1254 option space, if one is defined. */
1256 if (vendor_cfg_option
) {
1257 tmp
= lookup_option (vendor_cfg_option
-> universe
,
1259 vendor_cfg_option
-> code
);
1261 evaluate_option_cache (&name
, packet
, lease
,
1266 } else if (vuname
) {
1267 name
.data
= (unsigned char *)s
;
1268 name
.len
= strlen (s
);
1271 name
.data
= (unsigned char *)s
;
1275 /* If we found a universe, and there are options configured
1276 for that universe, try to encapsulate it. */
1278 have_encapsulation
=
1279 (option_space_encapsulate
1280 (&encapsulation
, packet
, lease
, client_state
,
1281 in_options
, cfg_options
, scope
, &name
));
1282 data_string_forget (&name
, MDL
);
1287 /* In order to avoid memory leaks, we have to get to here
1288 with any option cache that we allocated in tmp not being
1289 referenced by tmp, and whatever option cache is referenced
1290 by oc being an actual reference. lookup_option doesn't
1291 generate a reference (this needs to be fixed), so the
1292 preceding goop ensures that if we *didn't* generate a new
1293 option cache, oc still winds up holding an actual reference. */
1295 /* If no data is available for this option, skip it. */
1296 if (!oc
&& !have_encapsulation
) {
1300 /* Find the value of the option... */
1303 evaluate_option_cache (&od
, packet
,
1304 lease
, client_state
, in_options
,
1305 cfg_options
, scope
, oc
, MDL
);
1307 /* If we have encapsulation for this option, and an oc
1308 * lookup succeeded, but the evaluation failed, it is
1309 * either because this is a complex atom (atoms before
1310 * E on format list) and the top half of the option is
1311 * not configured, or this is a simple encapsulated
1312 * space and the evaluator is giving us a NULL. Prefer
1313 * the evaluator's opinion over the subspace.
1316 data_string_forget (&encapsulation
, MDL
);
1317 data_string_forget (&od
, MDL
);
1322 /* We should now have a constant length for the option. */
1324 if (have_encapsulation
) {
1325 length
+= encapsulation
.len
;
1327 /* od.len can be nonzero if we got here without an
1328 * oc (cache lookup failed), but did have an encapsulated
1329 * simple encapsulation space.
1332 data_string_copy (&od
, &encapsulation
, MDL
);
1333 data_string_forget (&encapsulation
, MDL
);
1335 struct buffer
*bp
= (struct buffer
*)0;
1336 if (!buffer_allocate (&bp
, length
, MDL
)) {
1337 option_cache_dereference (&oc
, MDL
);
1338 data_string_forget (&od
, MDL
);
1339 data_string_forget (&encapsulation
, MDL
);
1342 memcpy (&bp
-> data
[0], od
.data
, od
.len
);
1343 memcpy (&bp
-> data
[od
.len
], encapsulation
.data
,
1345 data_string_forget (&od
, MDL
);
1346 data_string_forget (&encapsulation
, MDL
);
1347 od
.data
= &bp
-> data
[0];
1348 buffer_reference (&od
.buffer
, bp
, MDL
);
1349 buffer_dereference (&bp
, MDL
);
1355 /* Do we add a NUL? */
1356 if (terminate
&& option
&& format_has_text(option
->format
)) {
1363 /* Try to store the option. */
1365 /* If the option's length is more than 255, we must store it
1366 in multiple hunks. Store 255-byte hunks first. However,
1367 in any case, if the option data will cross a buffer
1368 boundary, split it across that boundary. */
1380 unsigned incr
= length
;
1382 unsigned char *base
;
1384 /* Try to fit it in the options buffer. */
1386 ((!six
&& !tix
&& (i
== priority_len
- 1) &&
1387 (bufix
+ 2 + length
< bufend
)) ||
1388 (bufix
+ 5 + length
< bufend
))) {
1391 /* Try to fit it in the second buffer. */
1392 } else if (!splitup
&& first_cutoff
&&
1393 (first_cutoff
+ six
+ 3 + length
< sbufend
)) {
1394 base
= &buffer
[first_cutoff
];
1396 /* Try to fit it in the third buffer. */
1397 } else if (!splitup
&& second_cutoff
&&
1398 (second_cutoff
+ tix
+ 3 + length
< buflen
)) {
1399 base
= &buffer
[second_cutoff
];
1401 /* Split the option up into the remaining space. */
1405 /* Use any remaining options space. */
1406 if (bufix
+ 6 < bufend
) {
1407 incr
= bufend
- bufix
- 5;
1410 /* Use any remaining first_cutoff space. */
1411 } else if (first_cutoff
&&
1412 (first_cutoff
+ six
+ 4 < sbufend
)) {
1413 incr
= sbufend
- (first_cutoff
+ six
) - 3;
1414 base
= &buffer
[first_cutoff
];
1416 /* Use any remaining second_cutoff space. */
1417 } else if (second_cutoff
&&
1418 (second_cutoff
+ tix
+ 4 < buflen
)) {
1419 incr
= buflen
- (second_cutoff
+ tix
) - 3;
1420 base
= &buffer
[second_cutoff
];
1422 /* Give up, roll back this option. */
1436 /* Everything looks good - copy it in! */
1438 base
[*pix
+ 1] = (unsigned char)incr
;
1439 if (tto
&& incr
== length
) {
1441 memcpy (base
+ *pix
+ 2,
1442 od
.data
+ ix
, (unsigned)(incr
- 1));
1443 base
[*pix
+ 2 + incr
- 1] = 0;
1445 memcpy (base
+ *pix
+ 2,
1446 od
.data
+ ix
, (unsigned)incr
);
1452 data_string_forget (&od
, MDL
);
1456 option_dereference(&option
, MDL
);
1458 /* If we can overload, and we have, then PAD and END those spaces. */
1459 if (first_cutoff
&& six
) {
1460 if ((first_cutoff
+ six
+ 1) < sbufend
)
1461 memset (&buffer
[first_cutoff
+ six
+ 1], DHO_PAD
,
1462 sbufend
- (first_cutoff
+ six
+ 1));
1463 else if (first_cutoff
+ six
>= sbufend
)
1464 log_fatal("Second buffer overflow in overloaded options.");
1466 buffer
[first_cutoff
+ six
] = DHO_END
;
1468 *ocount
|= 1; /* So that caller knows there's data there. */
1471 if (second_cutoff
&& tix
) {
1472 if (second_cutoff
+ tix
+ 1 < buflen
) {
1473 memset (&buffer
[second_cutoff
+ tix
+ 1], DHO_PAD
,
1474 buflen
- (second_cutoff
+ tix
+ 1));
1475 } else if (second_cutoff
+ tix
>= buflen
)
1476 log_fatal("Third buffer overflow in overloaded options.");
1478 buffer
[second_cutoff
+ tix
] = DHO_END
;
1480 *ocount
|= 2; /* So that caller knows there's data there. */
1483 if ((six
|| tix
) && (bufix
+ 3 > bufend
))
1484 log_fatal("Not enough space for option overload option.");
1489 /* Return true if the format string has a variable length text option
1490 * ("t"), return false otherwise.
1494 format_has_text(format
)
1500 while (*p
!= '\0') {
1506 /* These symbols are arbitrary, not fixed or
1507 * determinable length...text options with them is
1508 * invalid (whatever the case, they are never NULL
1519 /* 'c' only follows 'D' atoms, and indicates that
1520 * compression may be used. If there was a 'D'
1521 * atom already, we would have returned. So this
1522 * is an error, but continue looking for 't' anyway.
1524 log_error("format_has_text(%s): 'c' atoms are illegal "
1525 "except after 'D' atoms.", format
);
1528 /* 'E' is variable length, but not arbitrary...you
1529 * can find its length if you can find an END option.
1530 * N is (n)-byte in length but trails a name of a
1531 * space defining the enumeration values. So treat
1532 * both the same - valid, fixed-length fields.
1536 /* Consume the space name. */
1537 while ((*p
!= '\0') && (*p
++ != '.'))
1549 /* Determine the minimum length of a DHCP option prior to any variable
1550 * or inconsistent length formats, according to its configured format
1551 * variable (and possibly from supplied option cache contents for variable
1552 * length format symbols).
1556 format_min_length(format
, oc
)
1558 struct option_cache
*oc
;
1560 const char *p
, *name
;
1563 struct enumeration
*espace
;
1566 while (*p
!= '\0') {
1568 case '6': /* IPv6 Address */
1573 case 'I': /* IPv4 Address */
1574 case 'l': /* int32_t */
1575 case 'L': /* uint32_t */
1576 case 'T': /* Lease Time, uint32_t equivalent */
1581 case 's': /* int16_t */
1582 case 'S': /* uint16_t */
1587 case 'N': /* Enumeration value. */
1588 /* Consume space name. */
1592 log_fatal("Corrupt format: %s", format
);
1594 espace
= find_enumeration(name
, p
- name
);
1595 if (espace
== NULL
) {
1596 log_error("Unknown enumeration: %s", format
);
1597 /* Max is safest value to return. */
1601 min_len
+= espace
->width
;
1602 last_size
= espace
->width
;
1607 case 'b': /* int8_t */
1608 case 'B': /* uint8_t */
1609 case 'F': /* Flag that is always true. */
1610 case 'f': /* Flag */
1615 case 'o': /* Last argument is optional. */
1616 min_len
-= last_size
;
1618 /* XXX: It MAY be possible to sense the end of an
1619 * encapsulated space, but right now this is too
1620 * hard to support. Return a safe value.
1622 case 'e': /* Encapsulation hint (there is an 'E' later). */
1623 case 'E': /* Encapsulated options. */
1626 case 'd': /* "Domain name" */
1627 case 'D': /* "rfc1035 formatted names" */
1628 case 't': /* "ASCII Text" */
1629 case 'X': /* "ASCII or Hex Conditional */
1630 case 'x': /* "Hex" */
1631 case 'A': /* Array of all that precedes. */
1632 case 'a': /* Array of preceding symbol. */
1633 case 'Z': /* nothing. */
1636 case 'c': /* Compress flag for D atom. */
1637 log_error("format_min_length(%s): 'c' atom is illegal "
1638 "except after 'D' atom.", format
);
1642 /* No safe value is known. */
1643 log_error("format_min_length(%s): No safe value "
1644 "for unknown format symbols.", format
);
1653 /* Format the specified option so that a human can easily read it. */
1655 const char *pretty_print_option (option
, data
, len
, emit_commas
, emit_quotes
)
1656 struct option
*option
;
1657 const unsigned char *data
;
1662 static char optbuf
[32768]; /* XXX */
1663 static char *endbuf
= &optbuf
[sizeof(optbuf
)];
1671 char fmtbuf
[32] = "";
1673 struct enumeration
*enumbuf
[32]; /* MUST be same as fmtbuf */
1675 const unsigned char *dp
= data
;
1684 memset (enumbuf
, 0, sizeof enumbuf
);
1686 /* Figure out the size of the data. */
1687 for (l
= i
= 0; option
-> format
[i
]; i
++, l
++) {
1688 if (l
>= sizeof(fmtbuf
) - 1)
1689 log_fatal("Bounds failure on internal buffer at "
1693 log_error ("%s: Extra codes in format string: %s",
1695 &(option
-> format
[i
]));
1699 fmtbuf
[l
] = option
-> format
[i
];
1700 switch (option
-> format
[i
]) {
1708 /* Skip the universe name. */
1709 while (option
-> format
[i
] &&
1710 option
-> format
[i
] != '.')
1714 for (k
= 0; k
< len
; k
++) {
1715 if (!isascii (data
[k
]) ||
1716 !isprint (data
[k
]))
1719 /* If we found no bogus characters, or the bogus
1720 character we found is a trailing NUL, it's
1721 okay to print this option as text. */
1722 if (k
== len
|| (k
+ 1 == len
&& data
[k
] == 0)) {
1734 /* The 'c' atom is a 'D' modifier only. */
1735 log_error("'c' atom not following D atom in format "
1736 "string: %s", option
->format
);
1740 * Skip the 'c' atom, if present. It does not affect
1741 * how we convert wire->text format (if compression is
1742 * present either way, we still process it).
1744 if (option
->format
[i
+1] == 'c')
1751 /* Fall Through ! */
1758 while (option
-> format
[i
] &&
1759 option
-> format
[i
] != '.')
1762 find_enumeration (&option
-> format
[k
] + 1,
1764 if (enumbuf
[l
] == NULL
) {
1768 hunksize
+= enumbuf
[l
]->width
;
1769 hunkinc
= enumbuf
[l
]->width
;
1802 log_error ("%s: garbage in format string: %s",
1804 &(option
-> format
[i
]));
1809 /* Check for too few bytes... */
1810 if (hunksize
- opthunk
> len
) {
1811 log_error ("%s: expecting at least %d bytes; got %d",
1816 /* Check for too many bytes... */
1817 if (numhunk
== -1 && hunksize
< len
)
1818 log_error ("%s: %d extra bytes",
1822 /* If this is an array, compute its size. */
1824 numhunk
= len
/ hunksize
;
1825 /* See if we got an exact number of hunks. */
1826 if (numhunk
> 0 && numhunk
* hunksize
< len
)
1827 log_error ("%s: %d extra bytes at end of array\n",
1829 len
- numhunk
* hunksize
);
1831 /* A one-hunk array prints the same as a single hunk. */
1835 /* Cycle through the array (or hunk) printing the data. */
1836 for (i
= 0; i
< numhunk
; i
++) {
1837 for (j
= 0; j
< numelem
; j
++) {
1838 switch (fmtbuf
[j
]) {
1840 /* endbuf-1 leaves room for NULL. */
1841 k
= pretty_text(&op
, endbuf
- 1, &dp
,
1842 data
+ len
, emit_quotes
);
1844 log_error("Error printing text.");
1849 case 'D': /* RFC1035 format name list */
1850 for( ; dp
< (data
+ len
) ; dp
+= k
) {
1851 unsigned char nbuff
[NS_MAXCDNAME
];
1852 const unsigned char *nbp
, *nend
;
1854 nend
= &nbuff
[sizeof(nbuff
)];
1856 /* If this is for ISC DHCP consumption
1857 * (emit_quotes), lay it out as a list
1858 * of STRING tokens. Otherwise, it is
1859 * a space-separated list of DNS-
1860 * escaped names as /etc/resolv.conf
1864 if (op
+ 2 > endbuf
)
1872 /* XXX: if fmtbuf[j+1] != 'c', we
1873 * should warn if the data was
1874 * compressed anyway.
1876 k
= MRns_name_unpack(data
,
1882 log_error("Invalid domain "
1887 /* If emit_quotes, then use ISC DHCP
1888 * escapes. Otherwise, rely only on
1893 pretty_domain(&op
, endbuf
-1,
1896 /* ns_name_ntop() includes
1897 * a trailing NUL in its
1900 count
= MRns_name_ntop(
1905 log_error("Invalid "
1910 /* Consume all but the trailing
1915 /* Replace the trailing NUL
1916 * with the implicit root
1917 * (in the unlikely event the
1918 * domain name /is/ the root).
1925 /* pretty-printing an array of enums is
1926 going to get ugly. */
1933 switch (enumbuf
[j
]->width
) {
1935 tval
= getUChar(dp
);
1939 tval
= getUShort(dp
);
1943 tval
= getULong(dp
);
1947 log_fatal("Impossible case at %s:%d.",
1949 return "<double impossible condition>";
1953 if (!enumbuf
[j
] -> values
[i
].name
)
1955 if (enumbuf
[j
] -> values
[i
].value
==
1959 strcpy (op
, enumbuf
[j
] -> values
[i
].name
);
1960 dp
+= enumbuf
[j
]->width
;
1964 sprintf(op
, "%lu", tval
);
1969 memcpy(iaddr
.iabuf
, dp
, 4);
1970 strcpy(op
, piaddr(iaddr
));
1975 memcpy(iaddr
.iabuf
, dp
, 16);
1976 strcpy(op
, piaddr(iaddr
));
1980 sprintf (op
, "%ld", (long)getLong (dp
));
1984 tval
= getULong (dp
);
1986 sprintf (op
, "%s", "infinite");
1988 sprintf(op
, "%lu", tval
);
1992 (unsigned long)getULong(dp
));
1996 sprintf (op
, "%d", (int)getShort (dp
));
2000 sprintf(op
, "%u", (unsigned)getUShort(dp
));
2004 sprintf (op
, "%d", *(const char *)dp
++);
2007 sprintf (op
, "%d", *dp
++);
2011 sprintf (op
, "%x", *dp
++);
2014 strcpy (op
, *dp
++ ? "true" : "false");
2017 strcpy (op
, "true");
2024 log_error ("Unexpected format code %c",
2028 if (dp
== data
+ len
)
2030 if (j
+ 1 < numelem
&& comma
!= ':')
2033 if (i
+ 1 < numhunk
) {
2036 if (dp
== data
+ len
)
2042 int get_option (result
, universe
, packet
, lease
, client_state
,
2043 in_options
, cfg_options
, options
, scope
, code
, file
, line
)
2044 struct data_string
*result
;
2045 struct universe
*universe
;
2046 struct packet
*packet
;
2047 struct lease
*lease
;
2048 struct client_state
*client_state
;
2049 struct option_state
*in_options
;
2050 struct option_state
*cfg_options
;
2051 struct option_state
*options
;
2052 struct binding_scope
**scope
;
2057 struct option_cache
*oc
;
2059 if (!universe
-> lookup_func
)
2061 oc
= ((*universe
-> lookup_func
) (universe
, options
, code
));
2064 if (!evaluate_option_cache (result
, packet
, lease
, client_state
,
2065 in_options
, cfg_options
, scope
, oc
,
2071 void set_option (universe
, options
, option
, op
)
2072 struct universe
*universe
;
2073 struct option_state
*options
;
2074 struct option_cache
*option
;
2075 enum statement_op op
;
2077 struct option_cache
*oc
, *noc
;
2082 case eval_statement
:
2083 case break_statement
:
2085 log_error ("bogus statement type in set_option.");
2088 case default_option_statement
:
2089 oc
= lookup_option (universe
, options
,
2090 option
-> option
-> code
);
2093 save_option (universe
, options
, option
);
2096 case supersede_option_statement
:
2097 case send_option_statement
:
2098 /* Install the option, replacing any existing version. */
2099 save_option (universe
, options
, option
);
2102 case append_option_statement
:
2103 case prepend_option_statement
:
2104 oc
= lookup_option (universe
, options
,
2105 option
-> option
-> code
);
2107 save_option (universe
, options
, option
);
2110 /* If it's not an expression, make it into one. */
2111 if (!oc
-> expression
&& oc
-> data
.len
) {
2112 if (!expression_allocate (&oc
-> expression
, MDL
)) {
2113 log_error ("Can't allocate const expression.");
2116 oc
-> expression
-> op
= expr_const_data
;
2118 (&oc
-> expression
-> data
.const_data
,
2120 data_string_forget (&oc
-> data
, MDL
);
2122 noc
= (struct option_cache
*)0;
2123 if (!option_cache_allocate (&noc
, MDL
))
2125 if (op
== append_option_statement
) {
2126 if (!make_concat (&noc
-> expression
,
2128 option
-> expression
)) {
2129 option_cache_dereference (&noc
, MDL
);
2133 if (!make_concat (&noc
-> expression
,
2134 option
-> expression
,
2135 oc
-> expression
)) {
2136 option_cache_dereference (&noc
, MDL
);
2140 option_reference(&(noc
->option
), oc
->option
, MDL
);
2141 save_option (universe
, options
, noc
);
2142 option_cache_dereference (&noc
, MDL
);
2147 struct option_cache
*lookup_option (universe
, options
, code
)
2148 struct universe
*universe
;
2149 struct option_state
*options
;
2153 return (struct option_cache
*)0;
2154 if (universe
-> lookup_func
)
2155 return (*universe
-> lookup_func
) (universe
, options
, code
);
2157 log_error ("can't look up options in %s space.",
2159 return (struct option_cache
*)0;
2162 struct option_cache
*lookup_hashed_option (universe
, options
, code
)
2163 struct universe
*universe
;
2164 struct option_state
*options
;
2171 /* Make sure there's a hash table. */
2172 if (universe
-> index
>= options
-> universe_count
||
2173 !(options
-> universes
[universe
-> index
]))
2174 return (struct option_cache
*)0;
2176 hash
= options
-> universes
[universe
-> index
];
2178 hashix
= compute_option_hash (code
);
2179 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2180 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
==
2182 return (struct option_cache
*)(bptr
-> car
);
2184 return (struct option_cache
*)0;
2187 /* Save a specified buffer into an option cache. */
2189 save_option_buffer(struct universe
*universe
, struct option_state
*options
,
2190 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2191 unsigned code
, int terminatep
)
2193 struct option_cache
*op
= NULL
;
2196 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2202 save_option(universe
, options
, op
);
2206 option_cache_dereference(&op
, MDL
);
2211 /* Append a specified buffer onto the tail of an option cache. */
2213 append_option_buffer(struct universe
*universe
, struct option_state
*options
,
2214 struct buffer
*bp
, unsigned char *buffer
, unsigned length
,
2215 unsigned code
, int terminatep
)
2217 struct option_cache
*op
= NULL
;
2220 status
= prepare_option_buffer(universe
, bp
, buffer
, length
, code
,
2226 also_save_option(universe
, options
, op
);
2230 option_cache_dereference(&op
, MDL
);
2235 /* Create/copy a buffer into a new option cache. */
2237 prepare_option_buffer(struct universe
*universe
, struct buffer
*bp
,
2238 unsigned char *buffer
, unsigned length
, unsigned code
,
2239 int terminatep
, struct option_cache
**opp
)
2241 struct buffer
*lbp
= NULL
;
2242 struct option
*option
= NULL
;
2243 struct option_cache
*op
;
2246 /* Code sizes of 8, 16, and 32 bits are allowed. */
2247 switch(universe
->tag_size
) {
2257 if (code
> 0xffffffff)
2262 log_fatal("Inconsistent universe tag size at %s:%d.", MDL
);
2265 option_code_hash_lookup(&option
, universe
->code_hash
, &code
, 0, MDL
);
2267 /* If we created an option structure for each option a client
2268 * supplied, it's possible we may create > 2^32 option structures.
2269 * That's not feasible. So by failing to enter these option
2270 * structures into the code and name hash tables, references will
2271 * never be more than 1 - when the option cache is destroyed, this
2272 * will be cleaned up.
2275 char nbuf
[sizeof("unknown-4294967295")];
2277 sprintf(nbuf
, "unknown-%u", code
);
2279 option
= new_option(nbuf
, MDL
);
2284 option
->format
= default_option_format
;
2285 option
->universe
= universe
;
2286 option
->code
= code
;
2288 /* new_option() doesn't set references, pretend. */
2292 if (!option_cache_allocate (opp
, MDL
)) {
2293 log_error("No memory for option code %s.%s.",
2294 universe
->name
, option
->name
);
2299 /* Pointer rather than double pointer makes for less parens. */
2302 option_reference(&op
->option
, option
, MDL
);
2304 /* If we weren't passed a buffer in which the data are saved and
2305 refcounted, allocate one now. */
2307 if (!buffer_allocate (&lbp
, length
+ terminatep
, MDL
)) {
2308 log_error ("no memory for option buffer.");
2313 memcpy (lbp
-> data
, buffer
, length
+ terminatep
);
2315 buffer
= &bp
-> data
[0]; /* Refer to saved buffer. */
2318 /* Reference buffer copy to option cache. */
2319 op
-> data
.buffer
= (struct buffer
*)0;
2320 buffer_reference (&op
-> data
.buffer
, bp
, MDL
);
2322 /* Point option cache into buffer. */
2323 op
-> data
.data
= buffer
;
2324 op
-> data
.len
= length
;
2327 /* NUL terminate (we can get away with this because we (or
2328 the caller!) allocated one more than the buffer size, and
2329 because the byte following the end of an option is always
2330 the code of the next option, which the caller is getting
2331 out of the *original* buffer. */
2332 buffer
[length
] = 0;
2333 op
-> data
.terminated
= 1;
2335 op
-> data
.terminated
= 0;
2337 /* If this option is ultimately a text option, null determinate to
2338 * comply with RFC2132 section 2. Mark a flag so this can be sensed
2339 * later to echo NULLs back to clients that supplied them (they
2340 * probably expect them).
2342 if (format_has_text(option
->format
)) {
2343 int min_len
= format_min_length(option
->format
, op
);
2345 while ((op
->data
.len
> min_len
) &&
2346 (op
->data
.data
[op
->data
.len
-1] == '\0')) {
2348 op
->flags
|= OPTION_HAD_NULLS
;
2352 /* And let go of our references. */
2354 option_dereference(&option
, MDL
);
2360 count_options(struct option_cache
*dummy_oc
,
2361 struct packet
*dummy_packet
,
2362 struct lease
*dummy_lease
,
2363 struct client_state
*dummy_client_state
,
2364 struct option_state
*dummy_opt_state
,
2365 struct option_state
*opt_state
,
2366 struct binding_scope
**dummy_binding_scope
,
2367 struct universe
*dummy_universe
,
2368 void *void_accumulator
) {
2369 int *accumulator
= (int *)void_accumulator
;
2375 collect_oro(struct option_cache
*oc
,
2376 struct packet
*dummy_packet
,
2377 struct lease
*dummy_lease
,
2378 struct client_state
*dummy_client_state
,
2379 struct option_state
*dummy_opt_state
,
2380 struct option_state
*opt_state
,
2381 struct binding_scope
**dummy_binding_scope
,
2382 struct universe
*dummy_universe
,
2384 struct data_string
*oro
= (struct data_string
*)void_oro
;
2386 putUShort(oro
->buffer
->data
+ oro
->len
, oc
->option
->code
);
2390 /* build_server_oro() is presently unusued, but may be used at a future date
2391 * with support for Reconfigure messages (as a hint to the client about new
2392 * option value contents).
2395 build_server_oro(struct data_string
*server_oro
,
2396 struct option_state
*options
,
2397 const char *file
, int line
) {
2403 * Count the number of options, so we can allocate enough memory.
2404 * We want to mention sub-options too, so check all universes.
2407 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2408 NULL
, &dhcpv6_universe
, (void *)&num_opts
,
2410 for (i
=0; i
< options
->universe_count
; i
++) {
2411 if (options
->universes
[i
] != NULL
) {
2412 o
= universes
[i
]->enc_opt
;
2414 if (o
->universe
== &dhcpv6_universe
) {
2418 o
= o
->universe
->enc_opt
;
2426 memset(server_oro
, 0, sizeof(*server_oro
));
2427 if (!buffer_allocate(&server_oro
->buffer
, num_opts
* 2, MDL
)) {
2428 log_fatal("no memory to build server ORO");
2430 server_oro
->data
= server_oro
->buffer
->data
;
2434 * We want to mention sub-options too, so check all universes.
2436 server_oro
->len
= 0; /* gets set in collect_oro */
2437 option_space_foreach(NULL
, NULL
, NULL
, NULL
, options
,
2438 NULL
, &dhcpv6_universe
, (void *)server_oro
,
2440 for (i
=0; i
< options
->universe_count
; i
++) {
2441 if (options
->universes
[i
] != NULL
) {
2442 o
= universes
[i
]->enc_opt
;
2444 if (o
->universe
== &dhcpv6_universe
) {
2446 tmp
= server_oro
->buffer
->data
;
2447 putUShort(tmp
+ server_oro
->len
,
2449 server_oro
->len
+= 2;
2452 o
= o
->universe
->enc_opt
;
2458 /* Wrapper function to put an option cache into an option state. */
2460 save_option(struct universe
*universe
, struct option_state
*options
,
2461 struct option_cache
*oc
)
2463 if (universe
->save_func
)
2464 (*universe
->save_func
)(universe
, options
, oc
, ISC_FALSE
);
2466 log_error("can't store options in %s space.", universe
->name
);
2469 /* Wrapper function to append an option cache into an option state's list. */
2471 also_save_option(struct universe
*universe
, struct option_state
*options
,
2472 struct option_cache
*oc
)
2474 if (universe
->save_func
)
2475 (*universe
->save_func
)(universe
, options
, oc
, ISC_TRUE
);
2477 log_error("can't store options in %s space.", universe
->name
);
2481 save_hashed_option(struct universe
*universe
, struct option_state
*options
,
2482 struct option_cache
*oc
, isc_boolean_t appendp
)
2486 pair
*hash
= options
-> universes
[universe
-> index
];
2487 struct option_cache
**ocloc
;
2489 if (oc
-> refcnt
== 0)
2492 /* Compute the hash. */
2493 hashix
= compute_option_hash (oc
-> option
-> code
);
2495 /* If there's no hash table, make one. */
2497 hash
= (pair
*)dmalloc (OPTION_HASH_SIZE
* sizeof *hash
, MDL
);
2499 log_error ("no memory to store %s.%s",
2500 universe
-> name
, oc
-> option
-> name
);
2503 memset (hash
, 0, OPTION_HASH_SIZE
* sizeof *hash
);
2504 options
-> universes
[universe
-> index
] = (void *)hash
;
2506 /* Try to find an existing option matching the new one. */
2507 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2508 if (((struct option_cache
*)
2509 (bptr
-> car
)) -> option
-> code
==
2510 oc
-> option
-> code
)
2514 /* Deal with collisions on the hash list. */
2516 ocloc
= (struct option_cache
**)&bptr
->car
;
2519 * If appendp is set, append it onto the tail of the
2520 * ->next list. If it is not set, rotate it into
2521 * position at the head of the list.
2525 ocloc
= &(*ocloc
)->next
;
2526 } while (*ocloc
!= NULL
);
2528 option_cache_dereference(ocloc
, MDL
);
2531 option_cache_reference(ocloc
, oc
, MDL
);
2536 /* Otherwise, just put the new one at the head of the list. */
2537 bptr
= new_pair (MDL
);
2539 log_error ("No memory for option_cache reference.");
2542 bptr
-> cdr
= hash
[hashix
];
2544 option_cache_reference ((struct option_cache
**)&bptr
-> car
, oc
, MDL
);
2545 hash
[hashix
] = bptr
;
2548 void delete_option (universe
, options
, code
)
2549 struct universe
*universe
;
2550 struct option_state
*options
;
2553 if (universe
-> delete_func
)
2554 (*universe
-> delete_func
) (universe
, options
, code
);
2556 log_error ("can't delete options from %s space.",
2560 void delete_hashed_option (universe
, options
, code
)
2561 struct universe
*universe
;
2562 struct option_state
*options
;
2566 pair bptr
, prev
= (pair
)0;
2567 pair
*hash
= options
-> universes
[universe
-> index
];
2569 /* There may not be any options in this space. */
2573 /* Try to find an existing option matching the new one. */
2574 hashix
= compute_option_hash (code
);
2575 for (bptr
= hash
[hashix
]; bptr
; bptr
= bptr
-> cdr
) {
2576 if (((struct option_cache
*)(bptr
-> car
)) -> option
-> code
2581 /* If we found one, wipe it out... */
2584 prev
-> cdr
= bptr
-> cdr
;
2586 hash
[hashix
] = bptr
-> cdr
;
2587 option_cache_dereference
2588 ((struct option_cache
**)(&bptr
-> car
), MDL
);
2589 free_pair (bptr
, MDL
);
2593 extern struct option_cache
*free_option_caches
; /* XXX */
2595 int option_cache_dereference (ptr
, file
, line
)
2596 struct option_cache
**ptr
;
2600 if (!ptr
|| !*ptr
) {
2601 log_error ("Null pointer in option_cache_dereference: %s(%d)",
2603 #if defined (POINTER_DEBUG)
2611 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
2612 if (!(*ptr
) -> refcnt
) {
2613 if ((*ptr
) -> data
.buffer
)
2614 data_string_forget (&(*ptr
) -> data
, file
, line
);
2616 option_dereference(&(*ptr
)->option
, MDL
);
2617 if ((*ptr
) -> expression
)
2618 expression_dereference (&(*ptr
) -> expression
,
2621 option_cache_dereference (&((*ptr
) -> next
),
2623 /* Put it back on the free list... */
2624 (*ptr
) -> expression
= (struct expression
*)free_option_caches
;
2625 free_option_caches
= *ptr
;
2626 dmalloc_reuse (free_option_caches
, (char *)0, 0, 0);
2628 if ((*ptr
) -> refcnt
< 0) {
2629 log_error ("%s(%d): negative refcnt!", file
, line
);
2630 #if defined (DEBUG_RC_HISTORY)
2631 dump_rc_history (*ptr
);
2633 #if defined (POINTER_DEBUG)
2636 *ptr
= (struct option_cache
*)0;
2640 *ptr
= (struct option_cache
*)0;
2645 int hashed_option_state_dereference (universe
, state
, file
, line
)
2646 struct universe
*universe
;
2647 struct option_state
*state
;
2655 /* Get the pointer to the array of hash table bucket heads. */
2656 heads
= (pair
*)(state
-> universes
[universe
-> index
]);
2660 /* For each non-null head, loop through all the buckets dereferencing
2661 the attached option cache structures and freeing the buckets. */
2662 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2663 for (cp
= heads
[i
]; cp
; cp
= next
) {
2665 option_cache_dereference
2666 ((struct option_cache
**)&cp
-> car
,
2668 free_pair (cp
, file
, line
);
2672 dfree (heads
, file
, line
);
2673 state
-> universes
[universe
-> index
] = (void *)0;
2677 /* The 'data_string' primitive doesn't have an appension mechanism.
2678 * This function must then append a new option onto an existing buffer
2679 * by first duplicating the original buffer and appending the desired
2680 * values, followed by coping the new value into place.
2683 append_option(struct data_string
*dst
, struct universe
*universe
,
2684 struct option
*option
, struct data_string
*src
)
2686 struct data_string tmp
;
2688 if (src
->len
== 0 && option
->format
[0] != 'Z')
2691 memset(&tmp
, 0, sizeof(tmp
));
2693 /* Allocate a buffer to hold existing data, the current option's
2694 * tag and length, and the option's content.
2696 if (!buffer_allocate(&tmp
.buffer
,
2697 (dst
->len
+ universe
->length_size
+
2698 universe
->tag_size
+ src
->len
), MDL
)) {
2699 /* XXX: This kills all options presently stored in the
2700 * destination buffer. This is the way the original code
2701 * worked, and assumes an 'all or nothing' approach to
2702 * eg encapsulated option spaces. It may or may not be
2705 data_string_forget(dst
, MDL
);
2708 tmp
.data
= tmp
.buffer
->data
;
2710 /* Copy the existing data off the destination. */
2712 memcpy(tmp
.buffer
->data
, dst
->data
, dst
->len
);
2715 /* Place the new option tag and length. */
2716 (*universe
->store_tag
)(tmp
.buffer
->data
+ tmp
.len
, option
->code
);
2717 tmp
.len
+= universe
->tag_size
;
2718 (*universe
->store_length
)(tmp
.buffer
->data
+ tmp
.len
, src
->len
);
2719 tmp
.len
+= universe
->length_size
;
2721 /* Copy the option contents onto the end. */
2722 memcpy(tmp
.buffer
->data
+ tmp
.len
, src
->data
, src
->len
);
2723 tmp
.len
+= src
->len
;
2725 /* Play the shell game. */
2726 data_string_forget(dst
, MDL
);
2727 data_string_copy(dst
, &tmp
, MDL
);
2728 data_string_forget(&tmp
, MDL
);
2733 store_option(struct data_string
*result
, struct universe
*universe
,
2734 struct packet
*packet
, struct lease
*lease
,
2735 struct client_state
*client_state
,
2736 struct option_state
*in_options
, struct option_state
*cfg_options
,
2737 struct binding_scope
**scope
, struct option_cache
*oc
)
2739 struct data_string tmp
;
2740 struct universe
*subu
=NULL
;
2744 memset(&tmp
, 0, sizeof(tmp
));
2746 if (evaluate_option_cache(&tmp
, packet
, lease
, client_state
,
2747 in_options
, cfg_options
, scope
, oc
, MDL
)) {
2748 /* If the option is an extended 'e'ncapsulation (not a
2749 * direct 'E'ncapsulation), append the encapsulated space
2750 * onto the currently prepared value.
2753 if (oc
->option
->format
&&
2754 oc
->option
->format
[0] == 'e') {
2755 /* Skip forward to the universe name. */
2756 start
= strchr(oc
->option
->format
, 'E');
2760 /* Locate the name-terminating '.'. */
2761 end
= strchr(++start
, '.');
2763 /* A zero-length name is not allowed in
2764 * these kinds of encapsulations.
2766 if (end
== NULL
|| start
== end
)
2769 universe_hash_lookup(&subu
, universe_hash
,
2770 start
, end
- start
, MDL
);
2773 log_error("store_option: option %d "
2774 "refers to unknown "
2775 "option space '%.*s'.",
2777 (int)(end
- start
), start
);
2781 /* Append encapsulations, if any. We
2782 * already have the prepended values, so
2783 * we send those even if there are no
2784 * encapsulated options (and ->encapsulate()
2787 subu
->encapsulate(&tmp
, packet
, lease
,
2788 client_state
, in_options
,
2789 cfg_options
, scope
, subu
);
2792 } while (ISC_FALSE
);
2794 status
= append_option(result
, universe
, oc
->option
, &tmp
);
2795 data_string_forget(&tmp
, MDL
);
2803 int option_space_encapsulate (result
, packet
, lease
, client_state
,
2804 in_options
, cfg_options
, scope
, name
)
2805 struct data_string
*result
;
2806 struct packet
*packet
;
2807 struct lease
*lease
;
2808 struct client_state
*client_state
;
2809 struct option_state
*in_options
;
2810 struct option_state
*cfg_options
;
2811 struct binding_scope
**scope
;
2812 struct data_string
*name
;
2814 struct universe
*u
= NULL
;
2817 universe_hash_lookup(&u
, universe_hash
,
2818 (const char *)name
->data
, name
->len
, MDL
);
2820 log_error("option_space_encapsulate: option space '%.*s' does "
2821 "not exist, but is configured.",
2822 (int)name
->len
, name
->data
);
2826 if (u
->encapsulate
!= NULL
) {
2827 if (u
->encapsulate(result
, packet
, lease
, client_state
,
2828 in_options
, cfg_options
, scope
, u
))
2831 log_error("encapsulation requested for '%s' with no support.",
2837 /* Attempt to store any 'E'ncapsulated options that have not yet been
2838 * placed on the option buffer by the above (configuring a value in
2839 * the space over-rides any values in the child universe).
2841 * Note that there are far fewer universes than there will ever be
2842 * options in any universe. So it is faster to traverse the
2843 * configured universes, checking if each is encapsulated in the
2844 * current universe, and if so attempting to do so.
2846 * For each configured universe for this configuration option space,
2847 * which is encapsulated within the current universe, can not be found
2848 * by the lookup function (the universe-specific encapsulation
2849 * functions would already have stored such a value), and encapsulates
2850 * at least one option, append it.
2853 search_subencapsulation(struct data_string
*result
, struct packet
*packet
,
2854 struct lease
*lease
, struct client_state
*client_state
,
2855 struct option_state
*in_options
,
2856 struct option_state
*cfg_options
,
2857 struct binding_scope
**scope
,
2858 struct universe
*universe
)
2860 struct data_string sub
;
2861 struct universe
*subu
;
2864 memset(&sub
, 0, sizeof(sub
));
2865 for (i
= 0 ; i
< cfg_options
->universe_count
; i
++) {
2866 subu
= universes
[i
];
2869 log_fatal("Impossible condition at %s:%d.", MDL
);
2871 if (subu
->enc_opt
!= NULL
&&
2872 subu
->enc_opt
->universe
== universe
&&
2873 subu
->enc_opt
->format
!= NULL
&&
2874 subu
->enc_opt
->format
[0] == 'E' &&
2875 lookup_option(universe
, cfg_options
,
2876 subu
->enc_opt
->code
) == NULL
&&
2877 subu
->encapsulate(&sub
, packet
, lease
, client_state
,
2878 in_options
, cfg_options
,
2880 if (append_option(result
, universe
,
2881 subu
->enc_opt
, &sub
))
2884 data_string_forget(&sub
, MDL
);
2891 int hashed_option_space_encapsulate (result
, packet
, lease
, client_state
,
2892 in_options
, cfg_options
, scope
, universe
)
2893 struct data_string
*result
;
2894 struct packet
*packet
;
2895 struct lease
*lease
;
2896 struct client_state
*client_state
;
2897 struct option_state
*in_options
;
2898 struct option_state
*cfg_options
;
2899 struct binding_scope
**scope
;
2900 struct universe
*universe
;
2906 if (universe
-> index
>= cfg_options
-> universe_count
)
2909 hash
= cfg_options
-> universes
[universe
-> index
];
2913 /* For each hash bucket, and each configured option cache within
2914 * that bucket, append the option onto the buffer in encapsulated
2915 * format appropriate to the universe.
2918 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
2919 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
2920 if (store_option(result
, universe
, packet
, lease
,
2921 client_state
, in_options
, cfg_options
,
2922 scope
, (struct option_cache
*)p
->car
))
2927 if (search_subencapsulation(result
, packet
, lease
, client_state
,
2928 in_options
, cfg_options
, scope
, universe
))
2934 int nwip_option_space_encapsulate (result
, packet
, lease
, client_state
,
2935 in_options
, cfg_options
, scope
, universe
)
2936 struct data_string
*result
;
2937 struct packet
*packet
;
2938 struct lease
*lease
;
2939 struct client_state
*client_state
;
2940 struct option_state
*in_options
;
2941 struct option_state
*cfg_options
;
2942 struct binding_scope
**scope
;
2943 struct universe
*universe
;
2947 static struct option_cache
*no_nwip
;
2948 struct data_string ds
;
2949 struct option_chain_head
*head
;
2951 if (universe
-> index
>= cfg_options
-> universe_count
)
2953 head
= ((struct option_chain_head
*)
2954 cfg_options
-> universes
[nwip_universe
.index
]);
2959 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
2960 if (store_option (result
, universe
, packet
,
2961 lease
, client_state
, in_options
,
2963 (struct option_cache
*)ocp
-> car
))
2967 /* If there's no data, the nwip suboption is supposed to contain
2968 a suboption saying there's no data. */
2972 static unsigned char nni
[] = { 1, 0 };
2974 memset (&ds
, 0, sizeof ds
);
2977 if (option_cache_allocate (&no_nwip
, MDL
))
2978 data_string_copy (&no_nwip
-> data
, &ds
, MDL
);
2979 if (!option_code_hash_lookup(&no_nwip
->option
,
2980 nwip_universe
.code_hash
,
2982 log_fatal("Nwip option hash does not contain "
2986 if (store_option (result
, universe
, packet
, lease
,
2987 client_state
, in_options
,
2988 cfg_options
, scope
, no_nwip
))
2992 memset (&ds
, 0, sizeof ds
);
2994 /* If we have nwip options, the first one has to be the
2995 nwip-exists-in-option-area option. */
2996 if (!buffer_allocate (&ds
.buffer
, result
-> len
+ 2, MDL
)) {
2997 data_string_forget (result
, MDL
);
3000 ds
.data
= &ds
.buffer
-> data
[0];
3001 ds
.buffer
-> data
[0] = 2;
3002 ds
.buffer
-> data
[1] = 0;
3003 memcpy (&ds
.buffer
-> data
[2], result
-> data
, result
-> len
);
3004 data_string_forget (result
, MDL
);
3005 data_string_copy (result
, &ds
, MDL
);
3006 data_string_forget (&ds
, MDL
);
3012 /* We don't want to use ns_name_pton()...it doesn't tell us how many bytes
3013 * it has consumed, and it plays havoc with our escapes.
3015 * So this function does DNS encoding, and returns either the number of
3016 * octects consumed (on success), or -1 on failure.
3019 fqdn_encode(unsigned char *dst
, int dstlen
, const unsigned char *src
,
3023 int i
, j
, len
, outlen
=0;
3026 for (i
= 0, j
= 0 ; i
< srclen
; i
= j
) {
3027 while ((j
< srclen
) && (src
[j
] != '.') && (src
[j
] != '\0'))
3031 if ((outlen
+ 1 + len
) > dstlen
)
3037 /* We only do one FQDN, ending in one root label. */
3041 memcpy(out
, src
+ i
, len
);
3045 /* Advance past the root label. */
3049 if ((outlen
+ 1) > dstlen
)
3052 /* Place the root label. */
3059 int fqdn_option_space_encapsulate (result
, packet
, lease
, client_state
,
3060 in_options
, cfg_options
, scope
, universe
)
3061 struct data_string
*result
;
3062 struct packet
*packet
;
3063 struct lease
*lease
;
3064 struct client_state
*client_state
;
3065 struct option_state
*in_options
;
3066 struct option_state
*cfg_options
;
3067 struct binding_scope
**scope
;
3068 struct universe
*universe
;
3071 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3075 struct buffer
*bp
= (struct buffer
*)0;
3076 struct option_chain_head
*head
;
3078 /* If there's no FQDN universe, don't encapsulate. */
3079 if (fqdn_universe
.index
>= cfg_options
-> universe_count
)
3081 head
= ((struct option_chain_head
*)
3082 cfg_options
-> universes
[fqdn_universe
.index
]);
3086 /* Figure out the values of all the suboptions. */
3087 memset (results
, 0, sizeof results
);
3088 for (ocp
= head
-> first
; ocp
; ocp
= ocp
-> cdr
) {
3089 struct option_cache
*oc
= (struct option_cache
*)(ocp
-> car
);
3090 if (oc
-> option
-> code
> FQDN_SUBOPTION_COUNT
)
3092 evaluate_option_cache (&results
[oc
-> option
-> code
],
3093 packet
, lease
, client_state
, in_options
,
3094 cfg_options
, scope
, oc
, MDL
);
3096 /* We add a byte for the flags field.
3097 * We add two bytes for the two RCODE fields.
3098 * We add a byte because we will prepend a label count.
3099 * We add a byte because the input len doesn't count null termination,
3100 * and we will add a root label.
3102 len
= 5 + results
[FQDN_FQDN
].len
;
3103 /* Save the contents of the option in a buffer. */
3104 if (!buffer_allocate (&bp
, len
, MDL
)) {
3105 log_error ("no memory for option buffer.");
3109 buffer_reference (&result
-> buffer
, bp
, MDL
);
3111 result
-> data
= &bp
-> data
[0];
3113 memset (&bp
-> data
[0], 0, len
);
3114 /* XXX: The server should set bit 4 (yes, 4, not 3) to 1 if it is
3115 * not going to perform any ddns updates. The client should set the
3116 * bit if it doesn't want the server to perform any updates.
3117 * The problem is at this layer of abstraction we have no idea if
3118 * the caller is a client or server.
3120 * See RFC4702, Section 3.1, 'The "N" bit'.
3125 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3126 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3127 bp
-> data
[0] |= 2;
3128 if (results
[FQDN_SERVER_UPDATE
].len
&&
3129 results
[FQDN_SERVER_UPDATE
].data
[0])
3130 bp
-> data
[0] |= 1;
3131 if (results
[FQDN_RCODE1
].len
)
3132 bp
-> data
[1] = results
[FQDN_RCODE1
].data
[0];
3133 if (results
[FQDN_RCODE2
].len
)
3134 bp
-> data
[2] = results
[FQDN_RCODE2
].data
[0];
3136 if (results
[FQDN_ENCODED
].len
&&
3137 results
[FQDN_ENCODED
].data
[0]) {
3139 if (results
[FQDN_FQDN
].len
) {
3140 i
= fqdn_encode(&bp
->data
[3], len
- 3,
3141 results
[FQDN_FQDN
].data
,
3142 results
[FQDN_FQDN
].len
);
3150 result
->terminated
= 0;
3153 if (results
[FQDN_FQDN
].len
) {
3154 memcpy (&bp
-> data
[3], results
[FQDN_FQDN
].data
,
3155 results
[FQDN_FQDN
].len
);
3156 result
-> len
+= results
[FQDN_FQDN
].len
;
3157 result
-> terminated
= 0;
3161 for (i
= 1; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3162 if (results
[i
].len
)
3163 data_string_forget (&results
[i
], MDL
);
3165 buffer_dereference (&bp
, MDL
);
3167 data_string_forget(result
, MDL
);
3172 * Trap invalid attempts to inspect FQND6 contents.
3174 struct option_cache
*
3175 lookup_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3178 log_fatal("Impossible condition at %s:%d.", MDL
);
3183 * Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
3186 save_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3187 struct option_cache
*oc
, isc_boolean_t appendp
)
3189 log_fatal("Impossible condition at %s:%d.", MDL
);
3193 * Trap invalid attempts to delete an option out of the FQDN6 universe.
3196 delete_fqdn6_option(struct universe
*universe
, struct option_state
*options
,
3199 log_fatal("Impossible condition at %s:%d.", MDL
);
3202 /* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
3203 * V6's option cache entry.
3205 * This function is called speculatively by dhclient to setup
3206 * environment variables. But it would have already called the
3207 * foreach on the normal fqdn universe, so this is superfluous.
3210 fqdn6_option_space_foreach(struct packet
*packet
, struct lease
*lease
,
3211 struct client_state
*client_state
,
3212 struct option_state
*in_options
,
3213 struct option_state
*cfg_options
,
3214 struct binding_scope
**scope
,
3215 struct universe
*u
, void *stuff
,
3216 void (*func
)(struct option_cache
*,
3219 struct client_state
*,
3220 struct option_state
*,
3221 struct option_state
*,
3222 struct binding_scope
**,
3223 struct universe
*, void *))
3225 /* Pretend it is empty. */
3229 /* Turn the FQDN option space into a DHCPv6 FQDN option buffer.
3232 fqdn6_option_space_encapsulate(struct data_string
*result
,
3233 struct packet
*packet
, struct lease
*lease
,
3234 struct client_state
*client_state
,
3235 struct option_state
*in_options
,
3236 struct option_state
*cfg_options
,
3237 struct binding_scope
**scope
,
3238 struct universe
*universe
)
3241 struct option_chain_head
*head
;
3242 struct option_cache
*oc
;
3243 unsigned char *data
;
3244 int i
, len
, rval
= 0, count
;
3245 struct data_string results
[FQDN_SUBOPTION_COUNT
+ 1];
3247 if (fqdn_universe
.index
>= cfg_options
->universe_count
)
3249 head
= ((struct option_chain_head
*)
3250 cfg_options
->universes
[fqdn_universe
.index
]);
3254 memset(results
, 0, sizeof(results
));
3255 for (ocp
= head
->first
; ocp
!= NULL
; ocp
= ocp
->cdr
) {
3256 oc
= (struct option_cache
*)(ocp
->car
);
3257 if (oc
->option
->code
> FQDN_SUBOPTION_COUNT
)
3258 log_fatal("Impossible condition at %s:%d.", MDL
);
3260 evaluate_option_cache(&results
[oc
->option
->code
], packet
,
3261 lease
, client_state
, in_options
,
3262 cfg_options
, scope
, oc
, MDL
);
3265 /* We add a byte for the flags field at the start of the option.
3266 * We add a byte because we will prepend a label count.
3267 * We add a byte because the input length doesn't include a trailing
3268 * NULL, and we will add a root label.
3270 len
= results
[FQDN_FQDN
].len
+ 3;
3271 if (!buffer_allocate(&result
->buffer
, len
, MDL
)) {
3272 log_error("No memory for virtual option buffer.");
3275 data
= result
->buffer
->data
;
3276 result
->data
= data
;
3278 /* The first byte is the flags field. */
3281 /* XXX: The server should set bit 3 (yes, 3, not 4) to 1 if we
3282 * are not going to perform any DNS updates. The problem is
3283 * that at this layer of abstraction, we do not know if the caller
3284 * is the client or the server.
3286 * See RFC4704 Section 4.1, 'The "N" bit'.
3291 if (results
[FQDN_NO_CLIENT_UPDATE
].len
&&
3292 results
[FQDN_NO_CLIENT_UPDATE
].data
[0])
3294 if (results
[FQDN_SERVER_UPDATE
].len
&&
3295 results
[FQDN_SERVER_UPDATE
].data
[0])
3298 /* If there is no name, we're done. */
3299 if (results
[FQDN_FQDN
].len
== 0) {
3304 /* Convert textual representation to DNS format. */
3305 count
= fqdn_encode(data
+ 1, len
- 1,
3306 results
[FQDN_FQDN
].data
, results
[FQDN_FQDN
].len
);
3310 data_string_forget(result
, MDL
);
3314 result
->len
+= count
;
3315 result
->terminated
= 0;
3321 for (i
= 1 ; i
<= FQDN_SUBOPTION_COUNT
; i
++) {
3323 data_string_forget(&results
[i
], MDL
);
3329 /* Read the DHCPv6 FQDN option's contents into the FQDN virtual space.
3332 fqdn6_universe_decode(struct option_state
*options
,
3333 const unsigned char *buffer
, unsigned length
,
3336 struct buffer
*bp
= NULL
;
3337 unsigned char *first_dot
;
3338 int len
, hlen
, dlen
;
3340 /* The FQDN option has to be at least 1 byte long. */
3344 /* Save the contents of the option in a buffer. There are 3
3345 * one-byte values we record from the packet, so we go ahead
3346 * and allocate a bigger buffer to accommodate them. But the
3347 * 'length' we got (because it is a DNS encoded string) is
3348 * one longer than we need...so we only add two extra octets.
3350 if (!buffer_allocate(&bp
, length
+ 2, MDL
)) {
3351 log_error("No memory for dhcp6.fqdn option buffer.");
3355 /* The v6 FQDN is always 'encoded' per DNS. */
3357 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3358 bp
->data
, 1, FQDN_ENCODED
, 0))
3361 /* XXX: We need to process 'The "N" bit'. */
3363 if (buffer
[0] & 1) /* server-update. */
3368 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 2, 1,
3369 FQDN_SERVER_UPDATE
, 0))
3372 if (buffer
[0] & 2) /* no-client-update. */
3377 if (!save_option_buffer(&fqdn_universe
, options
, bp
, bp
->data
+ 1, 1,
3378 FQDN_NO_CLIENT_UPDATE
, 0))
3381 /* Convert the domain name to textual representation for config. */
3382 len
= MRns_name_ntop(buffer
+ 1, (char *)bp
->data
+ 3, length
- 1);
3384 log_error("Unable to convert dhcp6.fqdn domain name to "
3389 /* Save the domain name. */
3391 unsigned char *fqdn_start
= bp
->data
+ 3;
3393 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3394 fqdn_start
, len
, FQDN_FQDN
, 1))
3397 first_dot
= (unsigned char *)strchr((char *)fqdn_start
, '.');
3399 if (first_dot
!= NULL
) {
3400 hlen
= first_dot
- fqdn_start
;
3407 if (!save_option_buffer(&fqdn_universe
, options
, bp
,
3408 fqdn_start
, len
, FQDN_FQDN
, 1) ||
3410 !save_option_buffer(&fqdn_universe
, options
, bp
,
3412 FQDN_HOSTNAME
, 0)) ||
3414 !save_option_buffer(&fqdn_universe
, options
, bp
,
3415 first_dot
, dlen
, FQDN_DOMAINNAME
, 0)))
3419 buffer_dereference(&bp
, MDL
);
3423 buffer_dereference(&bp
, MDL
);
3427 void option_space_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 *))
3442 (*u
-> foreach
) (packet
, lease
, client_state
, in_options
,
3443 cfg_options
, scope
, u
, stuff
, func
);
3446 void suboption_foreach (struct packet
*packet
, struct lease
*lease
,
3447 struct client_state
*client_state
,
3448 struct option_state
*in_options
,
3449 struct option_state
*cfg_options
,
3450 struct binding_scope
**scope
,
3451 struct universe
*u
, void *stuff
,
3452 void (*func
) (struct option_cache
*,
3454 struct lease
*, struct client_state
*,
3455 struct option_state
*,
3456 struct option_state
*,
3457 struct binding_scope
**,
3458 struct universe
*, void *),
3459 struct option_cache
*oc
,
3462 struct universe
*universe
= find_option_universe (oc
-> option
,
3464 if (universe
-> foreach
)
3465 (*universe
-> foreach
) (packet
, lease
, client_state
,
3466 in_options
, cfg_options
,
3467 scope
, universe
, stuff
, func
);
3470 void hashed_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3471 struct client_state
*client_state
,
3472 struct option_state
*in_options
,
3473 struct option_state
*cfg_options
,
3474 struct binding_scope
**scope
,
3475 struct universe
*u
, void *stuff
,
3476 void (*func
) (struct option_cache
*,
3479 struct client_state
*,
3480 struct option_state
*,
3481 struct option_state
*,
3482 struct binding_scope
**,
3483 struct universe
*, void *))
3487 struct option_cache
*oc
;
3489 if (cfg_options
-> universe_count
<= u
-> index
)
3492 hash
= cfg_options
-> universes
[u
-> index
];
3495 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
3497 /* XXX save _all_ options! XXX */
3498 for (p
= hash
[i
]; p
; p
= p
-> cdr
) {
3499 oc
= (struct option_cache
*)p
-> car
;
3500 (*func
) (oc
, packet
, lease
, client_state
,
3501 in_options
, cfg_options
, scope
, u
, stuff
);
3507 save_linked_option(struct universe
*universe
, struct option_state
*options
,
3508 struct option_cache
*oc
, isc_boolean_t appendp
)
3511 struct option_chain_head
*head
;
3512 struct option_cache
**ocloc
;
3514 if (universe
-> index
>= options
-> universe_count
)
3516 head
= ((struct option_chain_head
*)
3517 options
-> universes
[universe
-> index
]);
3519 if (!option_chain_head_allocate (((struct option_chain_head
**)
3520 &options
-> universes
3521 [universe
-> index
]), MDL
))
3523 head
= ((struct option_chain_head
*)
3524 options
-> universes
[universe
-> index
]);
3527 /* Find the tail of the list. */
3528 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3529 ocloc
= (struct option_cache
**)&(*tail
)->car
;
3531 if (oc
->option
->code
== (*ocloc
)->option
->code
) {
3534 ocloc
= &(*ocloc
)->next
;
3535 } while (*ocloc
!= NULL
);
3537 option_cache_dereference(ocloc
, MDL
);
3539 option_cache_reference(ocloc
, oc
, MDL
);
3544 *tail
= cons (0, 0);
3546 option_cache_reference ((struct option_cache
**)
3547 (&(*tail
) -> car
), oc
, MDL
);
3551 int linked_option_space_encapsulate (result
, packet
, lease
, client_state
,
3552 in_options
, cfg_options
, scope
, universe
)
3553 struct data_string
*result
;
3554 struct packet
*packet
;
3555 struct lease
*lease
;
3556 struct client_state
*client_state
;
3557 struct option_state
*in_options
;
3558 struct option_state
*cfg_options
;
3559 struct binding_scope
**scope
;
3560 struct universe
*universe
;
3564 struct option_chain_head
*head
;
3566 if (universe
-> index
>= cfg_options
-> universe_count
)
3568 head
= ((struct option_chain_head
*)
3569 cfg_options
-> universes
[universe
-> index
]);
3573 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3574 if (store_option (result
, universe
, packet
,
3575 lease
, client_state
, in_options
, cfg_options
,
3576 scope
, (struct option_cache
*)(oc
-> car
)))
3580 if (search_subencapsulation(result
, packet
, lease
, client_state
,
3581 in_options
, cfg_options
, scope
, universe
))
3587 void delete_linked_option (universe
, options
, code
)
3588 struct universe
*universe
;
3589 struct option_state
*options
;
3592 pair
*tail
, tmp
= (pair
)0;
3593 struct option_chain_head
*head
;
3595 if (universe
-> index
>= options
-> universe_count
)
3597 head
= ((struct option_chain_head
*)
3598 options
-> universes
[universe
-> index
]);
3602 for (tail
= &head
-> first
; *tail
; tail
= &((*tail
) -> cdr
)) {
3604 ((struct option_cache
*)(*tail
) -> car
) -> option
-> code
)
3606 tmp
= (*tail
) -> cdr
;
3607 option_cache_dereference ((struct option_cache
**)
3608 (&(*tail
) -> car
), MDL
);
3616 struct option_cache
*lookup_linked_option (universe
, options
, code
)
3617 struct universe
*universe
;
3618 struct option_state
*options
;
3622 struct option_chain_head
*head
;
3624 if (universe
-> index
>= options
-> universe_count
)
3626 head
= ((struct option_chain_head
*)
3627 options
-> universes
[universe
-> index
]);
3631 for (oc
= head
-> first
; oc
; oc
= oc
-> cdr
) {
3633 ((struct option_cache
*)(oc
-> car
)) -> option
-> code
) {
3634 return (struct option_cache
*)(oc
-> car
);
3638 return (struct option_cache
*)0;
3641 int linked_option_state_dereference (universe
, state
, file
, line
)
3642 struct universe
*universe
;
3643 struct option_state
*state
;
3647 return (option_chain_head_dereference
3648 ((struct option_chain_head
**)
3649 (&state
-> universes
[universe
-> index
]), MDL
));
3652 void linked_option_space_foreach (struct packet
*packet
, struct lease
*lease
,
3653 struct client_state
*client_state
,
3654 struct option_state
*in_options
,
3655 struct option_state
*cfg_options
,
3656 struct binding_scope
**scope
,
3657 struct universe
*u
, void *stuff
,
3658 void (*func
) (struct option_cache
*,
3661 struct client_state
*,
3662 struct option_state
*,
3663 struct option_state
*,
3664 struct binding_scope
**,
3665 struct universe
*, void *))
3668 struct option_chain_head
*head
;
3670 if (u
-> index
>= cfg_options
-> universe_count
)
3672 head
= ((struct option_chain_head
*)
3673 cfg_options
-> universes
[u
-> index
]);
3676 for (car
= head
-> first
; car
; car
= car
-> cdr
) {
3677 (*func
) ((struct option_cache
*)(car
-> car
),
3678 packet
, lease
, client_state
,
3679 in_options
, cfg_options
, scope
, u
, stuff
);
3683 void do_packet (interface
, packet
, len
, from_port
, from
, hfrom
)
3684 struct interface_info
*interface
;
3685 struct dhcp_packet
*packet
;
3687 unsigned int from_port
;
3689 struct hardware
*hfrom
;
3691 struct option_cache
*op
;
3692 struct packet
*decoded_packet
;
3693 #if defined (DEBUG_MEMORY_LEAKAGE)
3694 unsigned long previous_outstanding
= dmalloc_outstanding
;
3697 #if defined (TRACING)
3698 trace_inpacket_stash (interface
, packet
, len
, from_port
, from
, hfrom
);
3701 decoded_packet
= (struct packet
*)0;
3702 if (!packet_allocate (&decoded_packet
, MDL
)) {
3703 log_error ("do_packet: no memory for incoming packet!");
3706 decoded_packet
-> raw
= packet
;
3707 decoded_packet
-> packet_length
= len
;
3708 decoded_packet
-> client_port
= from_port
;
3709 decoded_packet
-> client_addr
= from
;
3710 interface_reference (&decoded_packet
-> interface
, interface
, MDL
);
3711 decoded_packet
-> haddr
= hfrom
;
3713 if (packet
-> hlen
> sizeof packet
-> chaddr
) {
3714 packet_dereference (&decoded_packet
, MDL
);
3715 log_info ("Discarding packet with bogus hlen.");
3719 /* If there's an option buffer, try to parse it. */
3720 if (decoded_packet
-> packet_length
>= DHCP_FIXED_NON_UDP
+ 4) {
3721 if (!parse_options (decoded_packet
)) {
3722 if (decoded_packet
-> options
)
3723 option_state_dereference
3724 (&decoded_packet
-> options
, MDL
);
3725 packet_dereference (&decoded_packet
, MDL
);
3729 if (decoded_packet
-> options_valid
&&
3730 (op
= lookup_option (&dhcp_universe
,
3731 decoded_packet
-> options
,
3732 DHO_DHCP_MESSAGE_TYPE
))) {
3733 struct data_string dp
;
3734 memset (&dp
, 0, sizeof dp
);
3735 evaluate_option_cache (&dp
, decoded_packet
,
3737 (struct client_state
*)0,
3738 decoded_packet
-> options
,
3739 (struct option_state
*)0,
3740 (struct binding_scope
**)0,
3743 decoded_packet
-> packet_type
= dp
.data
[0];
3745 decoded_packet
-> packet_type
= 0;
3746 data_string_forget (&dp
, MDL
);
3750 if (decoded_packet
-> packet_type
)
3751 dhcp (decoded_packet
);
3753 bootp (decoded_packet
);
3755 /* If the caller kept the packet, they'll have upped the refcnt. */
3756 packet_dereference (&decoded_packet
, MDL
);
3758 #if defined (DEBUG_MEMORY_LEAKAGE)
3759 log_info ("generation %ld: %ld new, %ld outstanding, %ld long-term",
3761 dmalloc_outstanding
- previous_outstanding
,
3762 dmalloc_outstanding
, dmalloc_longterm
);
3764 #if defined (DEBUG_MEMORY_LEAKAGE)
3765 dmalloc_dump_outstanding ();
3767 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
3768 dump_rc_history (0);
3773 packet6_len_okay(const char *packet
, int len
) {
3777 if ((packet
[0] == DHCPV6_RELAY_FORW
) ||
3778 (packet
[0] == DHCPV6_RELAY_REPL
)) {
3779 if (len
>= sizeof(struct dhcpv6_relay_packet
)) {
3785 if (len
>= sizeof(struct dhcpv6_packet
)) {
3795 do_packet6(struct interface_info
*interface
, const char *packet
,
3796 int len
, int from_port
, const struct iaddr
*from
,
3797 isc_boolean_t was_unicast
) {
3798 unsigned char msg_type
;
3799 const struct dhcpv6_packet
*msg
;
3800 const struct dhcpv6_relay_packet
*relay
;
3801 struct packet
*decoded_packet
;
3803 if (!packet6_len_okay(packet
, len
)) {
3804 log_info("do_packet6: "
3805 "short packet from %s port %d, len %d, dropped",
3806 piaddr(*from
), from_port
, len
);
3810 decoded_packet
= NULL
;
3811 if (!packet_allocate(&decoded_packet
, MDL
)) {
3812 log_error("do_packet6: no memory for incoming packet.");
3816 if (!option_state_allocate(&decoded_packet
->options
, MDL
)) {
3817 log_error("do_packet6: no memory for options.");
3818 packet_dereference(&decoded_packet
, MDL
);
3822 /* IPv4 information, already set to 0 */
3823 /* decoded_packet->packet_type = 0; */
3824 /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
3825 /* decoded_packet->circuit_id = NULL; */
3826 /* decoded_packet->circuit_id_len = 0; */
3827 /* decoded_packet->remote_id = NULL; */
3828 /* decoded_packet->remote_id_len = 0; */
3829 decoded_packet
->raw
= (struct dhcp_packet
*) packet
;
3830 decoded_packet
->packet_length
= (unsigned) len
;
3831 decoded_packet
->client_port
= from_port
;
3832 decoded_packet
->client_addr
= *from
;
3833 interface_reference(&decoded_packet
->interface
, interface
, MDL
);
3835 decoded_packet
->unicast
= was_unicast
;
3837 msg_type
= packet
[0];
3838 if ((msg_type
== DHCPV6_RELAY_FORW
) ||
3839 (msg_type
== DHCPV6_RELAY_REPL
)) {
3840 relay
= (const struct dhcpv6_relay_packet
*)packet
;
3841 decoded_packet
->dhcpv6_msg_type
= relay
->msg_type
;
3843 /* relay-specific data */
3844 decoded_packet
->dhcpv6_hop_count
= relay
->hop_count
;
3845 memcpy(&decoded_packet
->dhcpv6_link_address
,
3846 relay
->link_address
, sizeof(relay
->link_address
));
3847 memcpy(&decoded_packet
->dhcpv6_peer_address
,
3848 relay
->peer_address
, sizeof(relay
->peer_address
));
3850 if (!parse_option_buffer(decoded_packet
->options
,
3851 relay
->options
, len
-sizeof(*relay
),
3852 &dhcpv6_universe
)) {
3853 /* no logging here, as parse_option_buffer() logs all
3854 cases where it fails */
3855 packet_dereference(&decoded_packet
, MDL
);
3859 msg
= (const struct dhcpv6_packet
*)packet
;
3860 decoded_packet
->dhcpv6_msg_type
= msg
->msg_type
;
3862 /* message-specific data */
3863 memcpy(decoded_packet
->dhcpv6_transaction_id
,
3864 msg
->transaction_id
,
3865 sizeof(decoded_packet
->dhcpv6_transaction_id
));
3867 if (!parse_option_buffer(decoded_packet
->options
,
3868 msg
->options
, len
-sizeof(*msg
),
3869 &dhcpv6_universe
)) {
3870 /* no logging here, as parse_option_buffer() logs all
3871 cases where it fails */
3872 packet_dereference(&decoded_packet
, MDL
);
3877 dhcpv6(decoded_packet
);
3879 packet_dereference(&decoded_packet
, MDL
);
3884 pretty_escape(char **dst
, char *dend
, const unsigned char **src
,
3885 const unsigned char *send
)
3889 /* If there aren't as many bytes left as there are in the source
3890 * buffer, don't even bother entering the loop.
3892 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3893 *dst
== NULL
|| *src
== NULL
|| (*dst
>= dend
) || (*src
> send
) ||
3894 ((send
- *src
) > (dend
- *dst
)))
3897 for ( ; *src
< send
; (*src
)++) {
3898 if (!isascii (**src
) || !isprint (**src
)) {
3899 /* Skip trailing NUL. */
3900 if ((*src
+ 1) != send
|| **src
!= '\0') {
3901 if (*dst
+ 4 > dend
)
3904 sprintf(*dst
, "\\%03o",
3909 } else if (**src
== '"' || **src
== '\'' || **src
== '$' ||
3910 **src
== '`' || **src
== '\\') {
3911 if (*dst
+ 2 > dend
)
3920 if (*dst
+ 1 > dend
)
3933 pretty_text(char **dst
, char *dend
, const unsigned char **src
,
3934 const unsigned char *send
, int emit_quotes
)
3938 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3939 *dst
== NULL
|| *src
== NULL
||
3940 ((*dst
+ (emit_quotes
? 2 : 0)) > dend
) || (*src
> send
))
3948 /* dend-1 leaves 1 byte for the closing quote. */
3949 count
= pretty_escape(dst
, dend
- (emit_quotes
? 1 : 0), src
, send
);
3954 if (emit_quotes
&& (*dst
< dend
)) {
3958 /* Includes quote prior to pretty_escape(); */
3966 pretty_domain(char **dst
, char *dend
, const unsigned char **src
,
3967 const unsigned char *send
)
3969 const unsigned char *tend
;
3973 if (dst
== NULL
|| dend
== NULL
|| src
== NULL
|| send
== NULL
||
3974 *dst
== NULL
|| *src
== NULL
||
3975 ((*dst
+ 2) > dend
) || (*src
>= send
))
3982 /* Continue loop until end of src buffer. */
3986 /* Consume tag size. */
3990 /* At root, finis. */
3994 tend
= (*src
) + tsiz
;
3996 /* If the tag exceeds the source buffer, it's illegal.
3997 * This should also trap compression pointers (which should
3998 * not be in these buffers).
4003 /* dend-2 leaves room for a trailing dot and quote. */
4004 status
= pretty_escape(dst
, dend
-2, src
, tend
);
4006 if ((status
== -1) || ((*dst
+ 2) > dend
))
4011 count
+= status
+ 1;
4022 * Add the option identified with the option number and data to the
4026 add_option(struct option_state
*options
,
4027 unsigned int option_num
,
4029 unsigned int data_len
)
4031 struct option_cache
*oc
;
4032 struct option
*option
;
4034 /* INSIST(options != NULL); */
4035 /* INSIST(data != NULL); */
4038 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
4039 &option_num
, 0, MDL
)) {
4040 log_error("Attempting to add unknown option %d.", option_num
);
4045 if (!option_cache_allocate(&oc
, MDL
)) {
4046 log_error("No memory for option cache adding %s (option %d).",
4047 option
->name
, option_num
);
4051 if (!make_const_data(&oc
->expression
,
4057 log_error("No memory for constant data adding %s (option %d).",
4058 option
->name
, option_num
);
4059 option_cache_dereference(&oc
, MDL
);
4063 option_reference(&(oc
->option
), option
, MDL
);
4064 save_option(&dhcp_universe
, options
, oc
);
4065 option_cache_dereference(&oc
, MDL
);