ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
options.c
Go to the documentation of this file.
1/* options.c
2
3 DHCP options parsing and reassembly. */
4
5/*
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 *
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.
20 *
21 * Internet Systems Consortium, Inc.
22 * PO Box 360
23 * Newmarket, NH 03857 USA
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29#define DHCP_OPTION_DATA
30#include "dhcpd.h"
31#include <omapip/omapip_p.h>
32#include <limits.h>
33
35
36static int pretty_text(char **, char *, const unsigned char **,
37 const unsigned char *, int);
38static int pretty_dname(char **, char *, const unsigned char *,
39 const unsigned char *);
40static int pretty_domain(char **, char *, const unsigned char **,
41 const unsigned char *);
42static int prepare_option_buffer(struct universe *universe, struct buffer *bp,
43 unsigned char *buffer, unsigned length,
44 unsigned code, int terminatep,
45 struct option_cache **opp);
46
47/* Parse all available options out of the specified packet. */
48/* Note, the caller is responsible for allocating packet->options. */
50 struct packet *packet;
51{
52 struct option_cache *op = NULL;
53
54 /* If we don't see the magic cookie, there's nothing to parse. */
55 if (memcmp (packet -> raw -> options, DHCP_OPTIONS_COOKIE, 4)) {
56 packet -> options_valid = 0;
57 return 1;
58 }
59
60 /* Go through the options field, up to the end of the packet
61 or the End field. */
62 if (!parse_option_buffer (packet -> options,
63 &packet -> raw -> options [4],
64 (packet -> packet_length -
66 &dhcp_universe)) {
67
68 /* STSN servers have a bug where they send a mangled
69 domain-name option, and whatever is beyond that in
70 the packet is junk. Microsoft clients accept this,
71 which is probably why whoever implemented the STSN
72 server isn't aware of the problem yet. To work around
73 this, we will accept corrupt packets from the server if
74 they contain a valid DHCP_MESSAGE_TYPE option, but
75 will not accept any corrupt client packets (the ISC DHCP
76 server is sufficiently widely used that it is probably
77 beneficial for it to be picky) and will not accept
78 packets whose type can't be determined. */
79
80 if ((op = lookup_option (&dhcp_universe, packet -> options,
82 if (!op -> data.data ||
83 (op -> data.data [0] != DHCPOFFER &&
84 op -> data.data [0] != DHCPACK &&
85 op -> data.data [0] != DHCPNAK))
86 return 0;
87 } else
88 return 0;
89 }
90
91 /* If we parsed a DHCP Option Overload option, parse more
92 options out of the buffer(s) containing them. */
93 if ((op = lookup_option (&dhcp_universe, packet -> options,
95 if (op -> data.data [0] & 1) {
97 (packet -> options,
98 (unsigned char *)packet -> raw -> file,
99 sizeof packet -> raw -> file,
101 return 0;
102 }
103 if (op -> data.data [0] & 2) {
105 (packet -> options,
106 (unsigned char *)packet -> raw -> sname,
107 sizeof packet -> raw -> sname,
109 return 0;
110 }
111 }
112 packet -> options_valid = 1;
113 return 1;
114}
115
116/* Parse options out of the specified buffer, storing addresses of option
117 * values in packet->options.
118 */
119int parse_option_buffer (options, buffer, length, universe)
120 struct option_state *options;
121 const unsigned char *buffer;
122 unsigned length;
123 struct universe *universe;
124{
125 unsigned len, offset;
126 unsigned code;
127 struct option_cache *op = NULL, *nop = NULL;
128 struct buffer *bp = (struct buffer *)0;
129 struct option *option = NULL;
130 char *reason = "general failure";
131
132 if (!buffer_allocate (&bp, length, MDL)) {
133 log_error ("no memory for option buffer.");
134 return 0;
135 }
136 memcpy (bp -> data, buffer, length);
137
138 for (offset = 0;
139 (offset + universe->tag_size) <= length &&
140 (code = universe->get_tag(buffer + offset)) != universe->end; ) {
141 offset += universe->tag_size;
142
143 /* Pad options don't have a length - just skip them. */
144 if (code == DHO_PAD)
145 continue;
146
147 /* Don't look for length if the buffer isn't that big. */
148 if ((offset + universe->length_size) > length) {
149 reason = "code tag at end of buffer - missing "
150 "length field";
151 goto bogus;
152 }
153
154 /* All other fields (except PAD and END handled above)
155 * have a length field, unless it's a DHCPv6 zero-length
156 * options space (eg any of the enterprise-id'd options).
157 *
158 * Zero-length-size option spaces basically consume the
159 * entire options buffer, so have at it.
160 */
161 if (universe->get_length != NULL)
162 len = universe->get_length(buffer + offset);
163 else if (universe->length_size == 0)
164 len = length - universe->tag_size;
165 else {
166 log_fatal("Improperly configured option space(%s): "
167 "may not have a nonzero length size "
168 "AND a NULL get_length function.",
169 universe->name);
170
171 /* Silence compiler warnings. */
172 return 0;
173 }
174
175 offset += universe->length_size;
176
177 option_code_hash_lookup(&option, universe->code_hash, &code,
178 0, MDL);
179
180 /* If the length is outrageous, the options are bad. */
181 if (offset + len > length) {
182 /* Avoid reference count overflow */
184 reason = "option length exceeds option buffer length";
185 bogus:
186 log_error("parse_option_buffer: malformed option "
187 "%s.%s (code %u): %s.", universe->name,
188 option ? option->name : "<unknown>",
189 code, reason);
190 buffer_dereference (&bp, MDL);
191 return 0;
192 }
193
194 /* If the option contains an encapsulation, parse it. In
195 any case keep the raw data as well. (Previous to 4.4.0
196 we only kept the raw data if the parse failed, the option
197 wasn't an encapsulation (by far the most common case), or
198 the option wasn't entirely an encapsulation
199 */
200
201 if (option &&
202 (option->format[0] == 'e' || option->format[0] == 'E')) {
204 bp->data + offset,
205 len,
206 universe, NULL);
207 }
208
210 len == 0) {
211 /* non-compliant clients can send it
212 * we'll just drop it and go on */
213 log_debug ("Ignoring empty DHO_HOST_NAME option");
215 offset += len;
216 continue;
217 }
218
219 op = lookup_option(universe, options, code);
220 if (op == NULL) {
221 /* If we don't have an option create one */
222 if (save_option_buffer(universe, options, bp,
223 bp->data + offset, len,
224 code, 1) == 0) {
225 log_error("parse_option_buffer: "
226 "save_option_buffer failed");
229 return (0);
230 }
231 } else if (universe->concat_duplicates) {
232 /* If we do have an option either concat with
233 what is there ...*/
234 struct data_string new;
235 memset(&new, 0, sizeof new);
236 if (!buffer_allocate(&new.buffer, op->data.len + len,
237 MDL)) {
238 log_error("parse_option_buffer: No memory.");
241 return (0);
242 }
243 /* Copy old option to new data object. */
244 memcpy(new.buffer->data, op->data.data,
245 op->data.len);
246 /* Concat new option behind old. */
247 memcpy(new.buffer->data + op->data.len,
248 bp->data + offset, len);
249 new.len = op->data.len + len;
250 new.data = new.buffer->data;
251 /* Save new concat'd object. */
253 data_string_copy(&op->data, &new, MDL);
254 data_string_forget(&new, MDL);
255 } else {
256 /* ... or we must append this statement onto the
257 * end of the list.
258 */
259 while (op->next != NULL)
260 op = op->next;
261
262 if (!option_cache_allocate(&nop, MDL)) {
263 log_error("parse_option_buffer: No memory.");
266 return (0);
267 }
268
269 option_reference(&nop->option, op->option, MDL);
270
271 nop->data.buffer = NULL;
272 buffer_reference(&nop->data.buffer, bp, MDL);
273 nop->data.data = bp->data + offset;
274 nop->data.len = len;
275
276 option_cache_reference(&op->next, nop, MDL);
278 }
279
281 offset += len;
282 }
283 buffer_dereference (&bp, MDL);
284 return (1);
285}
286
287/* If an option in an option buffer turns out to be an encapsulation,
288 figure out what to do. If we don't know how to de-encapsulate it,
289 or it's not well-formed, return zero; otherwise, return 1, indicating
290 that we succeeded in de-encapsulating it. */
291
292struct universe *find_option_universe (struct option *eopt, const char *uname)
293{
294 int i;
295 char *s, *t;
296 struct universe *universe = (struct universe *)0;
297
298 /* Look for the E option in the option format. */
299 s = strchr (eopt -> format, 'E');
300 if (!s) {
301 log_error ("internal encapsulation format error 1.");
302 return 0;
303 }
304 /* Look for the universe name in the option format. */
305 t = strchr (++s, '.');
306 /* If there was no trailing '.', or there's something after the
307 trailing '.', the option is bogus and we can't use it. */
308 if (!t || t [1]) {
309 log_error ("internal encapsulation format error 2.");
310 return 0;
311 }
312 if (t == s && uname) {
313 for (i = 0; i < universe_count; i++) {
314 if (!strcmp (universes [i] -> name, uname)) {
315 universe = universes [i];
316 break;
317 }
318 }
319 } else if (t != s) {
320 for (i = 0; i < universe_count; i++) {
321 if (strlen (universes [i] -> name) == t - s &&
322 !memcmp (universes [i] -> name,
323 s, (unsigned)(t - s))) {
324 universe = universes [i];
325 break;
326 }
327 }
328 }
329 return universe;
330}
331
332/* If an option in an option buffer turns out to be an encapsulation,
333 figure out what to do. If we don't know how to de-encapsulate it,
334 or it's not well-formed, return zero; otherwise, return 1, indicating
335 that we succeeded in de-encapsulating it. */
336
338 struct option *eopt,
339 const unsigned char *buffer,
340 unsigned len, struct universe *eu,
341 const char *uname)
342{
343 int i;
344 struct universe *universe = find_option_universe (eopt, uname);
345
346 /* If we didn't find the universe, we can't do anything with it
347 right now (e.g., we can't decode vendor options until we've
348 decoded the packet and executed the scopes that it matches). */
349 if (!universe)
350 return 0;
351
352 /* If we don't have a decoding function for it, we can't decode
353 it. */
354 if (!universe -> decode)
355 return 0;
356
357 i = (*universe -> decode) (options, buffer, len, universe);
358
359 /* If there is stuff before the suboptions, we have to keep it. */
360 if (eopt -> format [0] != 'E')
361 return 0;
362 /* Otherwise, return the status of the decode function. */
363 return i;
364}
365
367 const unsigned char *buffer,
368 unsigned length, struct universe *u)
369{
370 struct buffer *bp = (struct buffer *)0;
371
372 /* FQDN options have to be at least four bytes long. */
373 if (length < 3)
374 return 0;
375
376 /* Save the contents of the option in a buffer. */
377 if (!buffer_allocate (&bp, length + 4, MDL)) {
378 log_error ("no memory for option buffer.");
379 return 0;
380 }
381 memcpy (&bp -> data [3], buffer + 1, length - 1);
382
383 if (buffer [0] & 4) /* encoded */
384 bp -> data [0] = 1;
385 else
386 bp -> data [0] = 0;
387 if (!save_option_buffer(&fqdn_universe, options, bp,
388 bp->data, 1, FQDN_ENCODED, 0)) {
389 bad:
390 buffer_dereference (&bp, MDL);
391 return 0;
392 }
393
394 if (buffer [0] & 1) /* server-update */
395 bp -> data [2] = 1;
396 else
397 bp -> data [2] = 0;
398 if (buffer [0] & 2) /* no-client-update */
399 bp -> data [1] = 1;
400 else
401 bp -> data [1] = 0;
402
403 /* XXX Ideally we should store the name in DNS format, so if the
404 XXX label isn't in DNS format, we convert it to DNS format,
405 XXX rather than converting labels specified in DNS format to
406 XXX the plain ASCII representation. But that's hard, so
407 XXX not now. */
408
409 /* Not encoded using DNS format? */
410 if (!bp -> data [0]) {
411 unsigned i;
412
413 /* Some broken clients NUL-terminate this option. */
414 if (buffer [length - 1] == 0) {
415 --length;
416 bp -> data [1] = 1;
417 }
418
419 /* Determine the length of the hostname component of the
420 name. If the name contains no '.' character, it
421 represents a non-qualified label. */
422 for (i = 3; i < length && buffer [i] != '.'; i++);
423 i -= 3;
424
425 /* Note: If the client sends a FQDN, the first '.' will
426 be used as a NUL terminator for the hostname. */
427 if (i && (!save_option_buffer(&fqdn_universe, options, bp,
428 &bp->data[5], i,
429 FQDN_HOSTNAME, 0)))
430 goto bad;
431 /* Note: If the client sends a single label, the
432 FQDN_DOMAINNAME option won't be set. */
433 if (length > 4 + i &&
434 (!save_option_buffer(&fqdn_universe, options, bp,
435 &bp -> data[6 + i], length - 4 - i,
436 FQDN_DOMAINNAME, 1)))
437 goto bad;
438 /* Also save the whole name. */
439 if (length > 3) {
440 if (!save_option_buffer(&fqdn_universe, options, bp,
441 &bp -> data [5], length - 3,
442 FQDN_FQDN, 1))
443 goto bad;
444 }
445 } else {
446 unsigned len;
447 unsigned total_len = 0;
448 unsigned first_len = 0;
449 int terminated = 0;
450 unsigned char *s;
451
452 s = &bp -> data[5];
453
454 while (s < &bp -> data[0] + length + 2) {
455 len = *s;
456 if (len > 63) {
457 log_info ("label length exceeds 63 in fqdn option");
458 goto bad;
459 }
460 if (len == 0) {
461 terminated = 1;
462 break;
463 }
464 if (s + len > &bp -> data [0] + length + 3) {
465 log_info ("fqdn label longer than buffer");
466 goto bad;
467 }
468
469 if (first_len == 0) {
470 first_len = len;
471 }
472
473 *s = '.';
474 s += len + 1;
475 total_len += len + 1;
476 }
477
478 /* We wind up with a length that's one too many because
479 we shouldn't increment for the last label, but there's
480 no way to tell we're at the last label until we exit
481 the loop. :'*/
482 if (total_len > 0)
483 total_len--;
484
485 if (!terminated) {
486 first_len = total_len;
487 }
488
489 if (first_len > 0 &&
490 !save_option_buffer(&fqdn_universe, options, bp,
491 &bp -> data[6], first_len,
492 FQDN_HOSTNAME, 0))
493 goto bad;
494 if (total_len > 0 && first_len != total_len) {
495 if (!save_option_buffer(&fqdn_universe, options, bp,
496 &bp->data[6 + first_len],
497 total_len - first_len,
498 FQDN_DOMAINNAME, 1))
499 goto bad;
500 }
501 if (total_len > 0)
502 if (!save_option_buffer (&fqdn_universe, options, bp,
503 &bp -> data [6], total_len,
504 FQDN_FQDN, 1))
505 goto bad;
506 }
507
508 if (!save_option_buffer (&fqdn_universe, options, bp,
509 &bp -> data [1], 1,
511 goto bad;
512 if (!save_option_buffer (&fqdn_universe, options, bp,
513 &bp -> data [2], 1,
515 goto bad;
516
517 if (!save_option_buffer (&fqdn_universe, options, bp,
518 &bp -> data [3], 1,
519 FQDN_RCODE1, 0))
520 goto bad;
521 if (!save_option_buffer (&fqdn_universe, options, bp,
522 &bp -> data [4], 1,
523 FQDN_RCODE2, 0))
524 goto bad;
525
526 buffer_dereference (&bp, MDL);
527 return 1;
528}
529
530/*
531 * Load all options into a buffer, and then split them out into the three
532 * separate fields in the dhcp packet (options, file, and sname) where
533 * options can be stored.
534 *
535 * returns 0 on error, length of packet on success
536 */
537int
538cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
539 struct lease *lease, struct client_state *client_state,
540 int mms, struct option_state *in_options,
541 struct option_state *cfg_options,
542 struct binding_scope **scope,
543 int overload_avail, int terminate, int bootpp,
544 struct data_string *prl, const char *vuname)
545{
546#define PRIORITY_COUNT 300
547 unsigned priority_list[PRIORITY_COUNT];
548 int priority_len;
549 unsigned char buffer[4096], agentopts[1024];
550 unsigned index = 0;
551 unsigned mb_size = 0, mb_max = 0;
552 unsigned option_size = 0, agent_size = 0;
553 unsigned length;
554 int i;
555 struct option_cache *op;
556 struct data_string ds;
557 pair pp, *hash;
558 int overload_used = 0;
559 int of1 = 0, of2 = 0;
560
561 memset(&ds, 0, sizeof ds);
562
563 /*
564 * If there's a Maximum Message Size option in the incoming packet
565 * and no alternate maximum message size has been specified, or
566 * if the one specified in the packet is shorter than the
567 * alternative, take the one in the packet.
568 */
569
570 if (inpacket &&
571 (op = lookup_option(&dhcp_universe, inpacket->options,
573 (evaluate_option_cache(&ds, inpacket, lease,
574 client_state, in_options,
575 cfg_options, scope, op, MDL) != 0)) {
576 if (ds.len >= sizeof (u_int16_t)) {
577 i = getUShort(ds.data);
578 if(!mms || (i < mms))
579 mms = i;
580 }
582 }
583
584 /*
585 * If the client has provided a maximum DHCP message size,
586 * use that, up to the MTU limit. Otherwise, if it's BOOTP,
587 * only 64 bytes; otherwise use up to the minimum IP MTU size
588 * (576 bytes).
589 *
590 * XXX if a BOOTP client specifies a max message size, we will
591 * honor it.
592 */
593 if (mms) {
594 if (mms < DHCP_MTU_MIN)
595 /* Enforce minimum packet size, per RFC 2132 */
596 mb_size = DHCP_MIN_OPTION_LEN;
597 else if (mms > DHCP_MTU_MAX)
598 /*
599 * TODO: Packets longer than 1500 bytes really
600 * should be allowed, but it requires upstream
601 * changes to the way the packet is allocated. For
602 * now, we forbid them. They won't be needed very
603 * often anyway.
604 */
605 mb_size = DHCP_MAX_OPTION_LEN;
606 else
607 mb_size = mms - DHCP_FIXED_LEN;
608 } else if (bootpp) {
609 mb_size = 64;
610 if (inpacket != NULL &&
611 (inpacket->packet_length >= 64 + DHCP_FIXED_NON_UDP))
612 mb_size = inpacket->packet_length - DHCP_FIXED_NON_UDP;
613 } else
614 mb_size = DHCP_MIN_OPTION_LEN;
615
616 /*
617 * If answering a client message, see whether any relay agent
618 * options were included with the message. If so, save them
619 * to copy back in later, and make space in the main buffer
620 * to accommodate them
621 */
622 if (client_state == NULL) {
623 priority_list[0] = DHO_DHCP_AGENT_OPTIONS;
624 priority_len = 1;
625 agent_size = store_options(NULL, agentopts, 0,
626 sizeof(agentopts),
627 inpacket, lease, client_state,
628 in_options, cfg_options, scope,
629 priority_list, priority_len,
630 0, 0, 0, NULL);
631
632 mb_size += agent_size;
633 if (mb_size > DHCP_MAX_OPTION_LEN)
634 mb_size = DHCP_MAX_OPTION_LEN;
635 }
636
637 /*
638 * Set offsets for buffer data to be copied into filename
639 * and servername fields
640 */
641 if (mb_size > agent_size)
642 mb_max = mb_size - agent_size;
643 else
644 mb_max = mb_size;
645
646 if (overload_avail & 1) {
647 of1 = mb_max;
648 mb_max += DHCP_FILE_LEN;
649 }
650
651 if (overload_avail & 2) {
652 of2 = mb_max;
653 mb_max += DHCP_SNAME_LEN;
654 }
655
656 /*
657 * Preload the option priority list with protocol-mandatory options.
658 * This effectively gives these options the highest priority.
659 * This provides the order for any available options, the option
660 * must be in the option cache in order to actually be included.
661 */
662 priority_len = 0;
663 priority_list[priority_len++] = DHO_DHCP_MESSAGE_TYPE;
664 priority_list[priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
665 priority_list[priority_len++] = DHO_DHCP_LEASE_TIME;
666 priority_list[priority_len++] = DHO_DHCP_RENEWAL_TIME;
667 priority_list[priority_len++] = DHO_DHCP_REBINDING_TIME;
668 priority_list[priority_len++] = DHO_DHCP_MESSAGE;
669 priority_list[priority_len++] = DHO_DHCP_REQUESTED_ADDRESS;
670 priority_list[priority_len++] = DHO_ASSOCIATED_IP;
671
672 if (prl != NULL && prl->len > 0) {
673 if ((op = lookup_option(&dhcp_universe, cfg_options,
675 if (priority_len < PRIORITY_COUNT)
676 priority_list[priority_len++] =
678 }
679
680 /* If echo-client-id is on, then we add client identifier to
681 * the priority_list. This way we'll send it whether or not it
682 * is in the PRL. */
683 if ((inpacket != NULL) && (priority_len < PRIORITY_COUNT) &&
684 (inpacket->sv_echo_client_id == ISC_TRUE)) {
685 priority_list[priority_len++] =
687 }
688
689 data_string_truncate(prl, (PRIORITY_COUNT - priority_len));
690
691 /*
692 * Copy the client's PRL onto the priority_list after our high
693 * priority header.
694 */
695 for (i = 0; i < prl->len; i++) {
696 /*
697 * Prevent client from changing order of delivery
698 * of relay agent information option.
699 */
700 if (prl->data[i] != DHO_DHCP_AGENT_OPTIONS)
701 priority_list[priority_len++] = prl->data[i];
702 }
703
704 /*
705 * If the client doesn't request the FQDN option explicitly,
706 * to indicate priority, consider it lowest priority. Fit
707 * in the packet if there is space. Note that the option
708 * may only be included if the client supplied one.
709 */
710 if ((inpacket != NULL) && (priority_len < PRIORITY_COUNT) &&
712 FQDN_ENCODED) != NULL))
713 priority_list[priority_len++] = DHO_FQDN;
714
715 /*
716 * Some DHCP Servers will give the subnet-mask option if
717 * it is not on the parameter request list - so some client
718 * implementations have come to rely on this - so we will
719 * also make sure we supply this, at lowest priority.
720 *
721 * This is only done in response to DHCPDISCOVER or
722 * DHCPREQUEST messages, to avoid providing the option on
723 * DHCPINFORM or DHCPLEASEQUERY responses (if the client
724 * didn't request it).
725 */
726 if ((inpacket != NULL) && (priority_len < PRIORITY_COUNT) &&
727 ((inpacket->packet_type == DHCPDISCOVER) ||
728 (inpacket->packet_type == DHCPREQUEST)))
729 priority_list[priority_len++] = DHO_SUBNET_MASK;
730 } else {
731 /*
732 * First, hardcode some more options that ought to be
733 * sent first...these are high priority to have in the
734 * packet.
735 */
736 priority_list[priority_len++] = DHO_SUBNET_MASK;
737 if (lookup_option(&dhcp_universe, cfg_options,
739 priority_list[priority_len++] = DHO_CLASSLESS_STATIC_ROUTES;
740 else
741 priority_list[priority_len++] = DHO_ROUTERS;
742 priority_list[priority_len++] = DHO_DOMAIN_NAME_SERVERS;
743 priority_list[priority_len++] = DHO_HOST_NAME;
744 priority_list[priority_len++] = DHO_FQDN;
745
746 /*
747 * Append a list of the standard DHCP options from the
748 * standard DHCP option space. Actually, if a site
749 * option space hasn't been specified, we wind up
750 * treating the dhcp option space as the site option
751 * space, and the first for loop is skipped, because
752 * it's slightly more general to do it this way,
753 * taking the 1Q99 DHCP futures work into account.
754 */
755 if (cfg_options->site_code_min) {
756 for (i = 0; i < OPTION_HASH_SIZE; i++) {
757 hash = cfg_options->universes[dhcp_universe.index];
758 if (hash) {
759 for (pp = hash[i]; pp; pp = pp->cdr) {
760 op = (struct option_cache *)(pp->car);
761 if (op->option->code <
762 cfg_options->site_code_min &&
763 priority_len < PRIORITY_COUNT &&
765 priority_list[priority_len++] =
766 op->option->code;
767 }
768 }
769 }
770 }
771
772 /*
773 * Now cycle through the site option space, or if there
774 * is no site option space, we'll be cycling through the
775 * dhcp option space.
776 */
777 for (i = 0; i < OPTION_HASH_SIZE; i++) {
778 hash = cfg_options->universes[cfg_options->site_universe];
779 if (hash != NULL)
780 for (pp = hash[i]; pp; pp = pp->cdr) {
781 op = (struct option_cache *)(pp->car);
782 if (op->option->code >=
783 cfg_options->site_code_min &&
784 priority_len < PRIORITY_COUNT &&
786 priority_list[priority_len++] =
787 op->option->code;
788 }
789 }
790
791 /*
792 * Put any spaces that are encapsulated on the list,
793 * sort out whether they contain values later.
794 */
795 for (i = 0; i < cfg_options->universe_count; i++) {
796 if (universes[i]->enc_opt &&
797 priority_len < PRIORITY_COUNT &&
798 universes[i]->enc_opt->universe == &dhcp_universe) {
799 if (universes[i]->enc_opt->code !=
801 priority_list[priority_len++] =
802 universes[i]->enc_opt->code;
803 }
804 }
805
806 /*
807 * The vendor option space can't stand on its own, so always
808 * add it to the list.
809 */
810 if (priority_len < PRIORITY_COUNT)
811 priority_list[priority_len++] =
813 }
814
815 /* Put the cookie up front... */
816 memcpy(buffer, DHCP_OPTIONS_COOKIE, 4);
817 index += 4;
818
819 /* Copy the options into the big buffer... */
820 option_size = store_options(&overload_used, buffer, index, mb_max,
821 inpacket, lease, client_state,
822 in_options, cfg_options, scope,
823 priority_list, priority_len,
824 of1, of2, terminate, vuname);
825
826 /* If store_options() failed */
827 if (option_size == 0)
828 return 0;
829
830 /* How much was stored in the main buffer? */
831 index += option_size;
832
833 /*
834 * If we're going to have to overload, store the overload
835 * option first.
836 */
837 if (overload_used) {
838 if (mb_size - agent_size - index < 3)
839 return 0;
840
842 buffer[index++] = 1;
843 buffer[index++] = overload_used;
844
845 if (overload_used & 1)
846 memcpy(outpacket->file, &buffer[of1], DHCP_FILE_LEN);
847
848 if (overload_used & 2)
849 memcpy(outpacket->sname, &buffer[of2], DHCP_SNAME_LEN);
850 }
851
852 /* Now copy in preserved agent options, if any */
853 if (agent_size) {
854 if (mb_size - index >= agent_size) {
855 memcpy(&buffer[index], agentopts, agent_size);
856 index += agent_size;
857 } else
858 log_error("Unable to store relay agent information "
859 "in reply packet.");
860 }
861
862 /* Tack a DHO_END option onto the packet if we need to. */
863 if (index < mb_size)
864 buffer[index++] = DHO_END;
865
866 /* Copy main buffer into the options buffer of the packet */
867 memcpy(outpacket->options, buffer, index);
868
869 /* Figure out the length. */
870 length = DHCP_FIXED_NON_UDP + index;
871 return length;
872}
873
874/*
875 * XXX: We currently special case collecting VSIO options.
876 * We should be able to handle this in a more generic fashion, by
877 * including any encapsulated options that are present and desired.
878 * This will look something like the VSIO handling VSIO code.
879 * We may also consider handling the ORO-like options within
880 * encapsulated spaces.
881 */
882
884 char *buf;
887};
888
889static void
890vsio_options(struct option_cache *oc,
891 struct packet *packet,
892 struct lease *dummy_lease,
893 struct client_state *dummy_client_state,
894 struct option_state *dummy_opt_state,
895 struct option_state *opt_state,
896 struct binding_scope **dummy_binding_scope,
897 struct universe *universe,
898 void *void_vsio_state) {
899 struct vsio_state *vs = (struct vsio_state *)void_vsio_state;
900 struct data_string ds;
901 int total_len;
902
903 memset(&ds, 0, sizeof(ds));
904 if (evaluate_option_cache(&ds, packet, NULL,
905 NULL, opt_state, NULL,
906 &global_scope, oc, MDL)) {
907 total_len = ds.len + universe->tag_size + universe->length_size;
908 if (total_len <= (vs->buflen - vs->bufpos)) {
909 if (universe->tag_size == 1) {
910 vs->buf[vs->bufpos++] = oc->option->code;
911 } else if (universe->tag_size == 2) {
912 putUShort((unsigned char *)vs->buf+vs->bufpos,
913 oc->option->code);
914 vs->bufpos += 2;
915 } else if (universe->tag_size == 4) {
916 putULong((unsigned char *)vs->buf+vs->bufpos,
917 oc->option->code);
918 vs->bufpos += 4;
919 }
920 if (universe->length_size == 1) {
921 vs->buf[vs->bufpos++] = ds.len;
922 } else if (universe->length_size == 2) {
923 putUShort((unsigned char *)vs->buf+vs->bufpos,
924 ds.len);
925 vs->bufpos += 2;
926 } else if (universe->length_size == 4) {
927 putULong((unsigned char *)vs->buf+vs->bufpos,
928 ds.len);
929 vs->bufpos += 4;
930 }
931 memcpy(vs->buf + vs->bufpos, ds.data, ds.len);
932 vs->bufpos += ds.len;
933 } else {
934 log_debug("No space for option %d in VSIO space %s.",
935 oc->option->code, universe->name);
936 }
938 } else {
939 log_error("Error evaluating option %d in VSIO space %s.",
940 oc->option->code, universe->name);
941 }
942}
943
961static void
962add_option6_data(char *buf, int buflen, int* bufpos, uint16_t code,
963 struct data_string* ds) {
964 if ((ds->len + 4) > (buflen - *bufpos)) {
965 log_debug("No space for option %d", code);
966 } else {
967 unsigned char* tmp = (unsigned char *)buf + *bufpos;
968 /* option tag */
969 putUShort(tmp, code);
970 /* option length */
971 putUShort(tmp+2, ds->len);
972 /* option data */
973 memcpy(tmp+4, ds->data, ds->len);
974 /* update position */
975 *bufpos += 4 + ds->len;
976 }
977}
978
1005static void
1006store_encap6 (char *buf, int buflen, int* bufpos,
1007 struct option_state *opt_state, struct packet *packet,
1008 struct option* encap_opt, uint16_t code) {
1009 /* We need to extract the name of the universe
1010 * to use for this option. We expect a format string
1011 * of the form "Ename.". If we don't find a name we bail. */
1012 struct data_string ds;
1013 struct data_string name;
1014 char* s = (char*)encap_opt->format;
1015 char* t;
1016 if ((s == NULL) || (*s != 'E') || (strlen(s) <= 2)) {
1017 return;
1018 }
1019
1020 t = strchr(++s, '.');
1021 if ((t == NULL) || (t == s)) {
1022 return;
1023 }
1024
1025 memset(&ds, 0, sizeof(ds));
1026 memset(&name, 0, sizeof(name));
1027 name.data = (unsigned char *)s;
1028 name.len = t - s;
1029
1030 /* Now we call the routine to find and encapsulate the requested
1031 * option/universe. A return of 0 means no option information was
1032 * available and nothing is added to the buffer */
1033 if (option_space_encapsulate(&ds, packet, NULL, NULL, NULL, opt_state,
1034 &global_scope, &name) != 0) {
1035 add_option6_data(buf, buflen, bufpos, code, &ds);
1036 data_string_forget(&ds, MDL);
1037 }
1038}
1039
1040/*
1041 * Stores the options from the DHCPv6 universe into the buffer given.
1042 *
1043 * Required options are given as a 0-terminated list of option codes.
1044 * Once those are added, the ORO is consulted.
1045 */
1046
1047int
1048store_options6(char *buf, int buflen,
1049 struct option_state *opt_state,
1050 struct packet *packet,
1051 const int *required_opts,
1052 struct data_string *oro) {
1053 int i, j;
1054 struct option_cache *oc;
1055 struct option *o;
1056 struct data_string ds;
1057 int bufpos;
1058 int oro_size;
1059 u_int16_t code;
1060 int in_required_opts;
1061 int vsio_option_code;
1062 int vsio_wanted;
1063 struct vsio_state vs;
1064 unsigned char *tmp;
1065
1066 bufpos = 0;
1067 vsio_wanted = 0;
1068
1069 /*
1070 * Find the option code for the VSIO universe.
1071 */
1072 vsio_option_code = 0;
1073 o = vsio_universe.enc_opt;
1074 while (o != NULL) {
1075 if (o->universe == &dhcpv6_universe) {
1076 vsio_option_code = o->code;
1077 break;
1078 }
1079 o = o->universe->enc_opt;
1080 }
1081 if (vsio_option_code == 0) {
1082 log_fatal("No VSIO option code found.");
1083 }
1084
1085 if (required_opts != NULL) {
1086 for (i=0; required_opts[i] != 0; i++) {
1087 if (required_opts[i] == vsio_option_code) {
1088 vsio_wanted = 1;
1089 }
1090
1092 opt_state, required_opts[i]);
1093 if (oc == NULL) {
1094 continue;
1095 }
1096 memset(&ds, 0, sizeof(ds));
1097 for (; oc != NULL ; oc = oc->next) {
1098 if (evaluate_option_cache(&ds, packet, NULL,
1099 NULL, opt_state,
1100 NULL, &global_scope,
1101 oc, MDL)) {
1102 add_option6_data(buf, buflen, &bufpos,
1103 (uint16_t)required_opts[i], &ds);
1104 data_string_forget(&ds, MDL);
1105 } else {
1106 log_error("Error evaluating option %d",
1107 required_opts[i]);
1108 }
1109 }
1110 }
1111 }
1112
1113 if (oro == NULL) {
1114 oro_size = 0;
1115 } else {
1116 oro_size = oro->len / 2;
1117 }
1118 for (i=0; i<oro_size; i++) {
1119 memcpy(&code, oro->data+(i*2), 2);
1120 code = ntohs(code);
1121
1122 /*
1123 * See if we've already included this option because
1124 * it is required.
1125 */
1126 in_required_opts = 0;
1127 if (required_opts != NULL) {
1128 for (j=0; required_opts[j] != 0; j++) {
1129 if (required_opts[j] == code) {
1130 in_required_opts = 1;
1131 break;
1132 }
1133 }
1134 }
1135 if (in_required_opts) {
1136 continue;
1137 }
1138
1139 /*
1140 * If this is the VSIO option flag it so we'll know to
1141 * check the vsio space later on. However we still need
1142 * to check for the existence of any defined via
1143 * dhcp6.vendor-opts. Those are stored as simple values.
1144 */
1145 if (code == vsio_option_code) {
1146 vsio_wanted = 1;
1147 }
1148
1149 /*
1150 * Not already added, find this option.
1151 */
1152 oc = lookup_option(&dhcpv6_universe, opt_state, code);
1153 memset(&ds, 0, sizeof(ds));
1154 if (oc != NULL) {
1155 /* We have a simple value for the option */
1156 for (; oc != NULL ; oc = oc->next) {
1157 if (evaluate_option_cache(&ds, packet, NULL,
1158 NULL, opt_state, NULL,
1159 &global_scope, oc,
1160 MDL)) {
1161 add_option6_data(buf, buflen, &bufpos,
1162 code, &ds);
1163 data_string_forget(&ds, MDL);
1164 } else {
1165 log_error("Error evaluating option %d",
1166 code);
1167 }
1168 }
1169 } else {
1170 /*
1171 * We don't have a simple value, check to see if we
1172 * have an universe to encapsulate into an option.
1173 */
1174 struct option *encap_opt = NULL;
1175 unsigned int code_int = code;
1176
1177 option_code_hash_lookup(&encap_opt,
1178 dhcpv6_universe.code_hash,
1179 &code_int, 0, MDL);
1180 if (encap_opt != NULL) {
1181 store_encap6(buf, buflen, &bufpos, opt_state,
1182 packet, encap_opt, code);
1183 option_dereference(&encap_opt, MDL);
1184 }
1185 }
1186 }
1187
1188 if (vsio_wanted) {
1189 for (i=0; i < opt_state->universe_count; i++) {
1190 if (opt_state->universes[i] != NULL) {
1191 o = universes[i]->enc_opt;
1192 if ((o != NULL) &&
1193 (o->universe == &vsio_universe)) {
1194 /*
1195 * Add the data from this VSIO option.
1196 */
1197 vs.buf = buf;
1198 vs.buflen = buflen;
1199 vs.bufpos = bufpos+8;
1201 NULL,
1202 NULL, opt_state,
1203 NULL,
1204 universes[i],
1205 (void *)&vs,
1206 vsio_options);
1207
1208 /*
1209 * If there was actually data here,
1210 * add the "header".
1211 */
1212 if (vs.bufpos > bufpos+8) {
1213 tmp = (unsigned char *)buf +
1214 bufpos;
1215 putUShort(tmp,
1216 vsio_option_code);
1217 putUShort(tmp+2,
1218 vs.bufpos-bufpos-4);
1219 putULong(tmp+4, o->code);
1220
1221 bufpos = vs.bufpos;
1222 }
1223 }
1224 }
1225 }
1226 }
1227
1228 return bufpos;
1229}
1230
1231/*
1232 * Store all the requested options into the requested buffer.
1233 * XXX: ought to be static
1234 */
1235int
1236store_options(int *ocount,
1237 unsigned char *buffer, unsigned index, unsigned buflen,
1238 struct packet *packet, struct lease *lease,
1239 struct client_state *client_state,
1240 struct option_state *in_options,
1241 struct option_state *cfg_options,
1242 struct binding_scope **scope,
1243 unsigned *priority_list, int priority_len,
1244 unsigned first_cutoff, int second_cutoff, int terminate,
1245 const char *vuname)
1246{
1247 int bufix = 0, six = 0, tix = 0;
1248 int i;
1249 int ix;
1250 int tto;
1251 int bufend, sbufend;
1252 struct data_string od;
1253 struct option_cache *oc;
1254 struct option *option = NULL;
1255 unsigned code;
1256
1257 /*
1258 * These arguments are relative to the start of the buffer, so
1259 * reduce them by the current buffer index, and advance the
1260 * buffer pointer to where we're going to start writing.
1261 */
1262 buffer = &buffer[index];
1263 buflen -= index;
1264 if (first_cutoff)
1265 first_cutoff -= index;
1266 if (second_cutoff)
1267 second_cutoff -= index;
1268
1269 /* Calculate the start and end of each section of the buffer */
1270 bufend = sbufend = buflen;
1271 if (first_cutoff) {
1272 if (first_cutoff >= buflen)
1273 log_fatal("%s:%d:store_options: Invalid first cutoff.", MDL);
1274 bufend = first_cutoff;
1275
1276 if (second_cutoff) {
1277 if (second_cutoff >= buflen)
1278 log_fatal("%s:%d:store_options: Invalid second cutoff.",
1279 MDL);
1280 sbufend = second_cutoff;
1281 }
1282 } else if (second_cutoff) {
1283 if (second_cutoff >= buflen)
1284 log_fatal("%s:%d:store_options: Invalid second cutoff.", MDL);
1285 bufend = second_cutoff;
1286 }
1287
1288 memset (&od, 0, sizeof od);
1289
1290 /* Eliminate duplicate options from the parameter request list.
1291 * Enforce RFC-mandated ordering of options that are present.
1292 */
1293 for (i = 0; i < priority_len; i++) {
1294 /* Eliminate duplicates. */
1295 tto = 0;
1296 for (ix = i + 1; ix < priority_len + tto; ix++) {
1297 if (tto)
1298 priority_list [ix - tto] =
1299 priority_list [ix];
1300 if (priority_list [i] == priority_list [ix]) {
1301 tto++;
1302 priority_len--;
1303 }
1304 }
1305
1306 /* Enforce ordering of SUBNET_MASK options, according to
1307 * RFC2132 Section 3.3:
1308 *
1309 * If both the subnet mask and the router option are
1310 * specified in a DHCP reply, the subnet mask option MUST
1311 * be first.
1312 *
1313 * This guidance does not specify what to do if the client
1314 * PRL explicitly requests the options out of order, it is
1315 * a general statement.
1316 */
1317 if (priority_list[i] == DHO_SUBNET_MASK) {
1318 for (ix = i - 1 ; ix >= 0 ; ix--) {
1319 if (priority_list[ix] == DHO_ROUTERS) {
1320 /* swap */
1321 priority_list[ix] = DHO_SUBNET_MASK;
1322 priority_list[i] = DHO_ROUTERS;
1323 break;
1324 }
1325 }
1326 }
1327 }
1328
1329 /* Copy out the options in the order that they appear in the
1330 priority list... */
1331 for (i = 0; i < priority_len; i++) {
1332 /* Number of bytes left to store (some may already
1333 have been stored by a previous pass). */
1334 unsigned length;
1335 int optstart, soptstart, toptstart;
1336 struct universe *u;
1337 int have_encapsulation = 0;
1338 struct data_string encapsulation;
1339 int splitup;
1340
1341 memset (&encapsulation, 0, sizeof encapsulation);
1342 have_encapsulation = 0;
1343
1344 if (option != NULL)
1346
1347 /* Code for next option to try to store. */
1348 code = priority_list [i];
1349
1350 /* Look up the option in the site option space if the code
1351 is above the cutoff, otherwise in the DHCP option space. */
1352 if (code >= cfg_options -> site_code_min)
1353 u = universes [cfg_options -> site_universe];
1354 else
1355 u = &dhcp_universe;
1356
1357 oc = lookup_option (u, cfg_options, code);
1358
1359 if (oc && oc->option)
1361 else
1362 option_code_hash_lookup(&option, u->code_hash, &code, 0, MDL);
1363
1364 /* If it's a straight encapsulation, and the user supplied a
1365 * value for the entire option, use that. Otherwise, search
1366 * the encapsulated space.
1367 *
1368 * If it's a limited encapsulation with preceding data, and the
1369 * user supplied values for the preceding bytes, search the
1370 * encapsulated space.
1371 */
1372 if ((option != NULL) &&
1373 (((oc == NULL) && (option->format[0] == 'E')) ||
1374 ((oc != NULL) && (option->format[0] == 'e')))) {
1375 static char *s, *t;
1376 struct option_cache *tmp;
1377 struct data_string name;
1378
1379 s = strchr (option->format, 'E');
1380 if (s)
1381 t = strchr (++s, '.');
1382 if (s && t) {
1383 memset (&name, 0, sizeof name);
1384
1385 /* A zero-length universe name means the vendor
1386 option space, if one is defined. */
1387 if (t == s) {
1388 if (vendor_cfg_option) {
1390 cfg_options,
1391 vendor_cfg_option -> code);
1392 if (tmp)
1393 /* No need to check the return as we check name.len below */
1394 (void) evaluate_option_cache (&name, packet, lease,
1396 in_options,
1397 cfg_options,
1398 scope, tmp, MDL);
1399 } else if (vuname) {
1400 name.data = (unsigned char *)s;
1401 name.len = strlen (s);
1402 }
1403 } else {
1404 name.data = (unsigned char *)s;
1405 name.len = t - s;
1406 }
1407
1408 /* If we found a universe, and there are options configured
1409 for that universe, try to encapsulate it. */
1410 if (name.len) {
1411 have_encapsulation =
1413 (&encapsulation, packet, lease, client_state,
1414 in_options, cfg_options, scope, &name));
1415 }
1416
1417 data_string_forget (&name, MDL);
1418 }
1419 }
1420
1421 /* In order to avoid memory leaks, we have to get to here
1422 with any option cache that we allocated in tmp not being
1423 referenced by tmp, and whatever option cache is referenced
1424 by oc being an actual reference. lookup_option doesn't
1425 generate a reference (this needs to be fixed), so the
1426 preceding goop ensures that if we *didn't* generate a new
1427 option cache, oc still winds up holding an actual reference. */
1428
1429 /* If no data is available for this option, skip it. */
1430 if (!oc && !have_encapsulation) {
1431 continue;
1432 }
1433
1434 /* Find the value of the option... */
1435 od.len = 0;
1436 if (oc) {
1437 /* No need to check the return as we check od.len below */
1438 (void) evaluate_option_cache (&od, packet,
1439 lease, client_state, in_options,
1440 cfg_options, scope, oc, MDL);
1441
1442 /* If we have encapsulation for this option, and an oc
1443 * lookup succeeded, but the evaluation failed, it is
1444 * either because this is a complex atom (atoms before
1445 * E on format list) and the top half of the option is
1446 * not configured, or this is a simple encapsulated
1447 * space and the evaluator is giving us a NULL. Prefer
1448 * the evaluator's opinion over the subspace.
1449 */
1450 if (!od.len) {
1451 data_string_forget (&encapsulation, MDL);
1452 data_string_forget (&od, MDL);
1453 continue;
1454 }
1455 }
1456
1457 /* We should now have a constant length for the option. */
1458 length = od.len;
1459 if (have_encapsulation) {
1460 length += encapsulation.len;
1461
1462 /* od.len can be nonzero if we got here without an
1463 * oc (cache lookup failed), but did have an encapsulated
1464 * simple encapsulation space.
1465 */
1466 if (!od.len) {
1467 data_string_copy (&od, &encapsulation, MDL);
1468 data_string_forget (&encapsulation, MDL);
1469 } else {
1470 struct buffer *bp = (struct buffer *)0;
1471 if (!buffer_allocate (&bp, length, MDL)) {
1473 data_string_forget (&od, MDL);
1474 data_string_forget (&encapsulation, MDL);
1475 continue;
1476 }
1477 memcpy (&bp -> data [0], od.data, od.len);
1478 memcpy (&bp -> data [od.len], encapsulation.data,
1479 encapsulation.len);
1480 data_string_forget (&od, MDL);
1481 data_string_forget (&encapsulation, MDL);
1482 od.data = &bp -> data [0];
1483 buffer_reference (&od.buffer, bp, MDL);
1484 buffer_dereference (&bp, MDL);
1485 od.len = length;
1486 od.terminated = 0;
1487 }
1488 }
1489
1490 /* Do we add a NUL? */
1491 if (terminate && option && format_has_text(option->format)) {
1492 length++;
1493 tto = 1;
1494 } else {
1495 tto = 0;
1496 }
1497
1498 /* Try to store the option. */
1499
1500 /* If the option's length is more than 255, we must store it
1501 in multiple hunks. Store 255-byte hunks first. However,
1502 in any case, if the option data will cross a buffer
1503 boundary, split it across that boundary. */
1504
1505 if (length > 255)
1506 splitup = 1;
1507 else
1508 splitup = 0;
1509
1510 ix = 0;
1511 optstart = bufix;
1512 soptstart = six;
1513 toptstart = tix;
1514 while (length) {
1515 unsigned incr = length;
1516 int *pix;
1517 unsigned char *base;
1518
1519 /* Try to fit it in the options buffer. */
1520 if (!splitup &&
1521 ((!six && !tix && (i == priority_len - 1) &&
1522 (bufix + 2 + length < bufend)) ||
1523 (bufix + 5 + length < bufend))) {
1524 base = buffer;
1525 pix = &bufix;
1526 /* Try to fit it in the second buffer. */
1527 } else if (!splitup && first_cutoff &&
1528 (first_cutoff + six + 3 + length < sbufend)) {
1529 base = &buffer[first_cutoff];
1530 pix = &six;
1531 /* Try to fit it in the third buffer. */
1532 } else if (!splitup && second_cutoff &&
1533 (second_cutoff + tix + 3 + length < buflen)) {
1534 base = &buffer[second_cutoff];
1535 pix = &tix;
1536 /* Split the option up into the remaining space. */
1537 } else {
1538 splitup = 1;
1539
1540 /* Use any remaining options space. */
1541 if (bufix + 6 < bufend) {
1542 incr = bufend - bufix - 5;
1543 base = buffer;
1544 pix = &bufix;
1545 /* Use any remaining first_cutoff space. */
1546 } else if (first_cutoff &&
1547 (first_cutoff + six + 4 < sbufend)) {
1548 incr = sbufend - (first_cutoff + six) - 3;
1549 base = &buffer[first_cutoff];
1550 pix = &six;
1551 /* Use any remaining second_cutoff space. */
1552 } else if (second_cutoff &&
1553 (second_cutoff + tix + 4 < buflen)) {
1554 incr = buflen - (second_cutoff + tix) - 3;
1555 base = &buffer[second_cutoff];
1556 pix = &tix;
1557 /* Give up, roll back this option. */
1558 } else {
1559 bufix = optstart;
1560 six = soptstart;
1561 tix = toptstart;
1562 break;
1563 }
1564 }
1565
1566 if (incr > length)
1567 incr = length;
1568 if (incr > 255)
1569 incr = 255;
1570
1571 /* Everything looks good - copy it in! */
1572 base [*pix] = code;
1573 base [*pix + 1] = (unsigned char)incr;
1574 if (tto && incr == length) {
1575 if (incr > 1)
1576 memcpy (base + *pix + 2,
1577 od.data + ix, (unsigned)(incr - 1));
1578 base [*pix + 2 + incr - 1] = 0;
1579 } else {
1580 memcpy (base + *pix + 2,
1581 od.data + ix, (unsigned)incr);
1582 }
1583 length -= incr;
1584 ix += incr;
1585 *pix += 2 + incr;
1586 }
1587 data_string_forget (&od, MDL);
1588 }
1589
1590 if (option != NULL)
1592
1593 /* If we can overload, and we have, then PAD and END those spaces. */
1594 if (first_cutoff && six) {
1595 if ((first_cutoff + six + 1) < sbufend)
1596 memset (&buffer[first_cutoff + six + 1], DHO_PAD,
1597 sbufend - (first_cutoff + six + 1));
1598 else if (first_cutoff + six >= sbufend)
1599 log_fatal("Second buffer overflow in overloaded options.");
1600
1601 buffer[first_cutoff + six] = DHO_END;
1602 if (ocount != NULL)
1603 *ocount |= 1; /* So that caller knows there's data there. */
1604 }
1605
1606 if (second_cutoff && tix) {
1607 if (second_cutoff + tix + 1 < buflen) {
1608 memset (&buffer[second_cutoff + tix + 1], DHO_PAD,
1609 buflen - (second_cutoff + tix + 1));
1610 } else if (second_cutoff + tix >= buflen)
1611 log_fatal("Third buffer overflow in overloaded options.");
1612
1613 buffer[second_cutoff + tix] = DHO_END;
1614 if (ocount != NULL)
1615 *ocount |= 2; /* So that caller knows there's data there. */
1616 }
1617
1618 if ((six || tix) && (bufix + 3 > bufend))
1619 log_fatal("Not enough space for option overload option.");
1620
1621 return bufix;
1622}
1623
1624/* Return true if the format string has a variable length text option
1625 * ("t"), return false otherwise.
1626 */
1627
1628int
1630 const char *format;
1631{
1632 const char *p;
1633
1634 p = format;
1635 while (*p != '\0') {
1636 switch (*p++) {
1637 case 't':
1638 case 'k':
1639 return 1;
1640
1641 /* These symbols are arbitrary, not fixed or
1642 * determinable length...text options with them is
1643 * invalid (whatever the case, they are never NULL
1644 * terminated).
1645 */
1646 case 'A':
1647 case 'a':
1648 case 'X':
1649 case 'x':
1650 case 'D':
1651 case 'd':
1652 return 0;
1653
1654 case 'c':
1655 /* 'c' only follows 'D' atoms, and indicates that
1656 * compression may be used. If there was a 'D'
1657 * atom already, we would have returned. So this
1658 * is an error, but continue looking for 't' anyway.
1659 */
1660 log_error("format_has_text(%s): 'c' atoms are illegal "
1661 "except after 'D' atoms.", format);
1662 break;
1663
1664 /* 'E' is variable length, but not arbitrary...you
1665 * can find its length if you can find an END option.
1666 * N is (n)-byte in length but trails a name of a
1667 * space defining the enumeration values. So treat
1668 * both the same - valid, fixed-length fields.
1669 */
1670 case 'E':
1671 case 'N':
1672 /* Consume the space name. */
1673 while ((*p != '\0') && (*p++ != '.'))
1674 ;
1675 break;
1676
1677 default:
1678 break;
1679 }
1680 }
1681
1682 return 0;
1683}
1684
1685/* Determine the minimum length of a DHCP option prior to any variable
1686 * or inconsistent length formats, according to its configured format
1687 * variable (and possibly from supplied option cache contents for variable
1688 * length format symbols).
1689 */
1690
1691int
1693 const char *format;
1694 struct option_cache *oc;
1695{
1696 const char *p, *name;
1697 int min_len = 0;
1698 int last_size = 0;
1699 struct enumeration *espace;
1700
1701 p = format;
1702 while (*p != '\0') {
1703 switch (*p++) {
1704 case '6': /* IPv6 Address */
1705 min_len += 16;
1706 last_size = 16;
1707 break;
1708
1709 case 'I': /* IPv4 Address */
1710 case 'l': /* int32_t */
1711 case 'L': /* uint32_t */
1712 case 'T': /* Lease Time, uint32_t equivalent */
1713 min_len += 4;
1714 last_size = 4;
1715 break;
1716
1717 case 's': /* int16_t */
1718 case 'S': /* uint16_t */
1719 min_len += 2;
1720 last_size = 2;
1721 break;
1722
1723 case 'N': /* Enumeration value. */
1724 /* Consume space name. */
1725 name = p;
1726 p = strchr(p, '.');
1727 if (p == NULL)
1728 log_fatal("Corrupt format: %s", format);
1729
1730 espace = find_enumeration(name, p - name);
1731 if (espace == NULL) {
1732 log_error("Unknown enumeration: %s", format);
1733 /* Max is safest value to return. */
1734 return INT_MAX;
1735 }
1736
1737 min_len += espace->width;
1738 last_size = espace->width;
1739 p++;
1740
1741 break;
1742
1743 case 'b': /* int8_t */
1744 case 'B': /* uint8_t */
1745 case 'F': /* Flag that is always true. */
1746 case 'f': /* Flag */
1747 min_len++;
1748 last_size = 1;
1749 break;
1750
1751 case 'o': /* Last argument is optional. */
1752 min_len -= last_size;
1753
1754 /* XXX: It MAY be possible to sense the end of an
1755 * encapsulated space, but right now this is too
1756 * hard to support. Return a safe value.
1757 */
1758 case 'e': /* Encapsulation hint (there is an 'E' later). */
1759 case 'E': /* Encapsulated options. */
1760 return min_len;
1761
1762 case 'd': /* "Domain name" */
1763 case 'D': /* "rfc1035 formatted names" */
1764 case 't': /* "ASCII Text" */
1765 case 'X': /* "ASCII or Hex Conditional */
1766 case 'x': /* "Hex" */
1767 case 'A': /* Array of all that precedes. */
1768 case 'a': /* Array of preceding symbol. */
1769 case 'Z': /* nothing. */
1770 case 'k': /* key name */
1771 return min_len;
1772
1773 case 'c': /* Compress flag for D atom. */
1774 log_error("format_min_length(%s): 'c' atom is illegal "
1775 "except after 'D' atom.", format);
1776 return INT_MAX;
1777
1778 default:
1779 /* No safe value is known. */
1780 log_error("format_min_length(%s): No safe value "
1781 "for unknown format symbols.", format);
1782 return INT_MAX;
1783 }
1784 }
1785
1786 return min_len;
1787}
1788
1789
1790/* Format the specified option so that a human can easily read it. */
1791/* Maximum pretty printed size */
1792#define MAX_OUTPUT_SIZE 32*1024
1793const char *pretty_print_option (option, data, len, emit_commas, emit_quotes)
1794 struct option *option;
1795 const unsigned char *data;
1796 unsigned len;
1797 int emit_commas;
1798 int emit_quotes;
1799{
1800 /* We add 128 byte pad so we don't have to add checks everywhere. */
1801 static char optbuf [MAX_OUTPUT_SIZE + 128]; /* XXX */
1802 static char *endbuf = optbuf + MAX_OUTPUT_SIZE;
1803 int hunksize = 0;
1804 int opthunk = 0;
1805 int hunkinc = 0;
1806 int numhunk = -1;
1807 int numelem = 0;
1808 int count;
1809 int i, j, k, l;
1810 char fmtbuf[32] = "";
1811 struct iaddr iaddr;
1812 struct enumeration *enumbuf[32]; /* MUST be same as fmtbuf */
1813 char *op = optbuf;
1814 const unsigned char *dp = data;
1815 char comma;
1816 unsigned long tval;
1817 isc_boolean_t a_array = ISC_FALSE;
1818 int len_used;
1819 unsigned int octets = 0;
1820
1821 if (emit_commas)
1822 comma = ',';
1823 else
1824 comma = ' ';
1825
1826 memset (enumbuf, 0, sizeof enumbuf);
1827
1828 if (option->format[0] != 'R') { /* see explanation lower */
1829 /* Figure out the size of the data. */
1830 for (l = i = 0; option -> format [i]; i++, l++) {
1831 if (l >= sizeof(fmtbuf) - 1)
1832 log_fatal("Bounds failure on internal buffer at "
1833 "%s:%d", MDL);
1834
1835 if (!numhunk) {
1836 log_error ("%s: Extra codes in format string: %s",
1837 option -> name,
1838 &(option -> format [i]));
1839 break;
1840 }
1841 numelem++;
1842 fmtbuf [l] = option -> format [i];
1843 switch (option -> format [i]) {
1844 case 'a':
1845 a_array = ISC_TRUE;
1846 /* Fall through */
1847 case 'A':
1848 --numelem;
1849 fmtbuf [l] = 0;
1850 numhunk = 0;
1851 break;
1852 case 'E':
1853 /* Skip the universe name. */
1854 while (option -> format [i] &&
1855 option -> format [i] != '.')
1856 i++;
1857 /* Fall Through! */
1858 case 'X':
1859 for (k = 0; k < len; k++) {
1860 if (!isascii (data [k]) ||
1861 !isprint (data [k]))
1862 break;
1863 }
1864 /* If we found no bogus characters, or the bogus
1865 character we found is a trailing NUL, it's
1866 okay to print this option as text. */
1867 if (k == len || (k + 1 == len && data [k] == 0)) {
1868 fmtbuf [l] = 't';
1869 numhunk = -2;
1870 } else {
1871 fmtbuf [l] = 'x';
1872 hunksize++;
1873 comma = ':';
1874 numhunk = 0;
1875 a_array = ISC_TRUE;
1876 hunkinc = 1;
1877 }
1878 fmtbuf [l + 1] = 0;
1879 break;
1880 case 'c':
1881 /* The 'c' atom is a 'D' modifier only. */
1882 log_error("'c' atom not following D atom in format "
1883 "string: %s", option->format);
1884 break;
1885 case 'D':
1886 /*
1887 * Skip the 'c' atom, if present. It does not affect
1888 * how we convert wire->text format (if compression is
1889 * present either way, we still process it).
1890 */
1891 if (option->format[i+1] == 'c')
1892 i++;
1893 fmtbuf[l + 1] = 0;
1894 numhunk = -2;
1895 break;
1896 case 'd':
1897 /* Should not be optional, array or compressed */
1898 if ((option->format[i+1] == 'o') ||
1899 (option->format[i+1] == 'a') ||
1900 (option->format[i+1] == 'A') ||
1901 (option->format[i+1] == 'c')) {
1902 log_error("%s: Illegal use of domain name: %s",
1903 option->name,
1904 &(option->format[i-1]));
1905 fmtbuf[l + 1] = 0;
1906 }
1907 k = MRns_name_len(data + len, data + hunksize);
1908 if (k == -1) {
1909 log_error("Invalid domain name.");
1910 return "<error>";
1911 }
1912 hunksize += k;
1913 break;
1914
1915 case 't':
1916 case 'k':
1917 fmtbuf[l + 1] = 0;
1918 numhunk = -2;
1919 break;
1920 case 'N':
1921 k = i;
1922 while (option -> format [i] &&
1923 option -> format [i] != '.')
1924 i++;
1925 enumbuf [l] =
1926 find_enumeration (&option -> format [k] + 1,
1927 i - k - 1);
1928 if (enumbuf[l] == NULL) {
1929 hunksize += 1;
1930 hunkinc = 1;
1931 } else {
1932 hunksize += enumbuf[l]->width;
1933 hunkinc = enumbuf[l]->width;
1934 }
1935 break;
1936 case '6':
1937 hunksize += 16;
1938 hunkinc = 16;
1939 break;
1940 case 'I':
1941 case 'l':
1942 case 'L':
1943 case 'T':
1944 hunksize += 4;
1945 hunkinc = 4;
1946 break;
1947 case 's':
1948 case 'S':
1949 hunksize += 2;
1950 hunkinc = 2;
1951 break;
1952 case 'b':
1953 case 'B':
1954 case 'f':
1955 case 'F':
1956 hunksize++;
1957 hunkinc = 1;
1958 break;
1959 case 'e':
1960 case 'Z':
1961 break;
1962 case 'o':
1963 opthunk += hunkinc;
1964 break;
1965 default:
1966 log_error ("%s: garbage in format string: %s",
1967 option -> name,
1968 &(option -> format [i]));
1969 break;
1970 }
1971 }
1972
1973 /* Check for too few bytes... */
1974 if (hunksize - opthunk > len) {
1975 log_error ("%s: expecting at least %d bytes; got %d",
1976 option -> name,
1977 hunksize, len);
1978 return "<error>";
1979 }
1980 /* Check for too many bytes... */
1981 if (numhunk == -1 && hunksize < len)
1982 log_error ("%s: %d extra bytes",
1983 option -> name,
1984 len - hunksize);
1985
1986 /* If this is an array, compute its size. */
1987 if (numhunk == 0) {
1988 if (a_array == ISC_TRUE) {
1989 /*
1990 * It is an 'a' type array - we repeat the
1991 * last format type. A binary string for 'X'
1992 * is also like this. hunkinc is the size
1993 * of the last format type and we add 1 to
1994 * cover the entire first record.
1995 */
1996
1997 /* If format string had no valid entries prior to
1998 * 'a' hunkinc will be 0. Ex: "a", "oa", "aA" */
1999 if (hunkinc == 0) {
2000 log_error ("%s: invalid 'a' format: %s",
2002 return ("<error>");
2003 }
2004
2005 numhunk = ((len - hunksize) / hunkinc) + 1;
2006 len_used = hunksize + ((numhunk - 1) * hunkinc);
2007 } else {
2008 /*
2009 * It is an 'A' type array - we repeat the
2010 * entire record
2011 */
2012
2013 /* If format string had no valid entries prior to
2014 * 'A' hunksize will be 0. Ex: "A", "oA", "foA" */
2015 if (hunksize == 0) {
2016 log_error ("%s: invalid 'A' format: %s",
2018 return ("<error>");
2019 }
2020
2021 numhunk = len / hunksize;
2022 len_used = numhunk * hunksize;
2023 }
2024
2025 /* See if we got an exact number of hunks. */
2026 if (len_used < len) {
2027 log_error ("%s: %d extra bytes at end of array\n",
2028 option -> name,
2029 len - len_used);
2030 }
2031 }
2032
2033
2034 /* A one-hunk array prints the same as a single hunk. */
2035 if (numhunk < 0)
2036 numhunk = 1;
2037
2038 } else { /* option->format[i] == 'R') */
2039 /* R (destination descriptor) has variable length.
2040 * We can find it only in classless static route option,
2041 * so we are for sure parsing classless static route option now.
2042 * We go through whole the option to check whether there are no
2043 * missing/extra bytes.
2044 * I didn't find out how to improve the existing code and that's the
2045 * reason for this separate 'else' where I do my own checkings.
2046 * I know it's little bit unsystematic, but it works.
2047 */
2048 numhunk = 0;
2049 numelem = 2; /* RI */
2050 fmtbuf[0]='R'; fmtbuf[1]='I'; fmtbuf[2]=0;
2051 for (i =0; i < len; i = i + octets + 5) {
2052 if (data[i] > 32) { /* subnet mask width */
2053 log_error ("wrong subnet mask width in destination descriptor");
2054 break;
2055 }
2056 numhunk++;
2057 octets = ((data[i]+7) / 8);
2058 }
2059 if (i != len) {
2060 log_error ("classless static routes option has wrong size or "
2061 "there's some garbage in format");
2062 }
2063 }
2064
2065 /* Cycle through the array (or hunk) printing the data. */
2066 for (i = 0; i < numhunk; i++) {
2067 if ((a_array == ISC_TRUE) && (i != 0) && (numelem > 0)) {
2068 /*
2069 * For 'a' type of arrays we repeat
2070 * only the last format character
2071 * We should never hit the case of numelem == 0
2072 * but let's include the check to be safe.
2073 */
2074 j = numelem - 1;
2075 } else {
2076 /*
2077 * for other types of arrays or the first
2078 * time through for 'a' types, we go through
2079 * the entire set of format characters.
2080 */
2081 j = 0;
2082 }
2083
2084 for (; j < numelem; j++) {
2085 switch (fmtbuf [j]) {
2086 case 't':
2087 case 'k':
2088 /* endbuf-1 leaves room for NULL. */
2089 k = pretty_text(&op, endbuf - 1, &dp,
2090 data + len, emit_quotes);
2091 if (k == -1) {
2092 log_error("Error printing text.");
2093 break;
2094 }
2095 *op = 0;
2096 break;
2097 case 'd': /* RFC1035 format name */
2098 k = MRns_name_len(data + len, dp);
2099 /* Already tested... */
2100 if (k == -1) {
2101 log_error("invalid domain name.");
2102 return "<error>";
2103 }
2104 pretty_dname(&op, endbuf-1, dp, data + len);
2105 /* pretty_dname does not add the nul */
2106 *op = '\0';
2107 dp += k;
2108 break;
2109 case 'D': /* RFC1035 format name list */
2110 for( ; dp < (data + len) ; dp += k) {
2111 unsigned char nbuff[NS_MAXCDNAME];
2112 const unsigned char *nbp, *nend;
2113
2114 nend = &nbuff[sizeof(nbuff)];
2115
2116 /* If this is for ISC DHCP consumption
2117 * (emit_quotes), lay it out as a list
2118 * of STRING tokens. Otherwise, it is
2119 * a space-separated list of DNS-
2120 * escaped names as /etc/resolv.conf
2121 * might digest.
2122 */
2123 if (dp != data) {
2124 if (op + 2 > endbuf)
2125 break;
2126
2127 if (emit_quotes)
2128 *op++ = ',';
2129 *op++ = ' ';
2130 }
2131
2132 /* XXX: if fmtbuf[j+1] != 'c', we
2133 * should warn if the data was
2134 * compressed anyway.
2135 */
2136 k = MRns_name_unpack(data,
2137 data + len,
2138 dp, nbuff,
2139 sizeof(nbuff));
2140
2141 if (k == -1) {
2142 log_error("Invalid domain "
2143 "list.");
2144 break;
2145 }
2146
2147 /* If emit_quotes, then use ISC DHCP
2148 * escapes. Otherwise, rely only on
2149 * MRns_name_ntop().
2150 */
2151 if (emit_quotes) {
2152 nbp = nbuff;
2153 pretty_domain(&op, endbuf-1,
2154 &nbp, nend);
2155 } else {
2156 /* MRns_name_ntop() includes
2157 * a trailing NUL in its
2158 * count.
2159 */
2160 count = MRns_name_ntop(
2161 nbuff, op,
2162 (endbuf-op)-1);
2163
2164 if (count <= 0) {
2165 log_error("Invalid "
2166 "domain name.");
2167 break;
2168 }
2169
2170 /* Consume all but the trailing
2171 * NUL.
2172 */
2173 op += count - 1;
2174
2175 /* Replace the trailing NUL
2176 * with the implicit root
2177 * (in the unlikely event the
2178 * domain name /is/ the root).
2179 */
2180 *op++ = '.';
2181 }
2182 }
2183 *op = '\0';
2184 break;
2185 /* pretty-printing an array of enums is
2186 going to get ugly. */
2187 case 'N':
2188 if (!enumbuf [j]) {
2189 tval = *dp++;
2190 goto enum_as_num;
2191 }
2192
2193 switch (enumbuf[j]->width) {
2194 case 1:
2195 tval = getUChar(dp);
2196 break;
2197
2198 case 2:
2199 tval = getUShort(dp);
2200 break;
2201
2202 case 4:
2203 tval = getULong(dp);
2204 break;
2205
2206 default:
2207 log_fatal("Impossible case at %s:%d.",
2208 MDL);
2209 return "<double impossible condition>";
2210 }
2211
2212 for (i = 0; ;i++) {
2213 if (!enumbuf [j] -> values [i].name)
2214 goto enum_as_num;
2215 if (enumbuf [j] -> values [i].value ==
2216 tval)
2217 break;
2218 }
2219 strcpy (op, enumbuf [j] -> values [i].name);
2220 dp += enumbuf[j]->width;
2221 break;
2222
2223 enum_as_num:
2224 sprintf(op, "%lu", tval);
2225 break;
2226
2227 case 'I':
2228 iaddr.len = 4;
2229 memcpy(iaddr.iabuf, dp, 4);
2230 strcpy(op, piaddr(iaddr));
2231 dp += 4;
2232 break;
2233
2234 case 'R':
2235 if (dp[0] <= 32)
2236 iaddr.len = (((dp[0]+7)/8)+1);
2237 else {
2238 log_error ("wrong subnet mask width in destination descriptor");
2239 return "<error>";
2240 }
2241
2242 memcpy(iaddr.iabuf, dp, iaddr.len);
2243 strcpy(op, pdestdesc(iaddr));
2244 dp += iaddr.len;
2245 break;
2246
2247 case '6':
2248 iaddr.len = 16;
2249 memcpy(iaddr.iabuf, dp, 16);
2250 strcpy(op, piaddr(iaddr));
2251 dp += 16;
2252 break;
2253 case 'l':
2254 sprintf (op, "%ld", (long)getLong (dp));
2255 dp += 4;
2256 break;
2257 case 'T':
2258 tval = getULong (dp);
2259 if (tval == -1)
2260 sprintf (op, "%s", "infinite");
2261 else
2262 sprintf(op, "%lu", tval);
2263 break;
2264 case 'L':
2265 sprintf(op, "%lu",
2266 (unsigned long)getULong(dp));
2267 dp += 4;
2268 break;
2269 case 's':
2270 sprintf (op, "%d", (int)getShort (dp));
2271 dp += 2;
2272 break;
2273 case 'S':
2274 sprintf(op, "%u", (unsigned)getUShort(dp));
2275 dp += 2;
2276 break;
2277 case 'b':
2278 sprintf (op, "%d", *(const char *)dp++);
2279 break;
2280 case 'B':
2281 sprintf (op, "%d", *dp++);
2282 break;
2283 case 'X':
2284 case 'x':
2285 sprintf (op, "%x", *dp++);
2286 break;
2287 case 'f':
2288 strcpy (op, *dp++ ? "true" : "false");
2289 break;
2290 case 'F':
2291 strcpy (op, "true");
2292 break;
2293 case 'e':
2294 case 'Z':
2295 *op = '\0';
2296 break;
2297 default:
2298 log_error ("Unexpected format code %c",
2299 fmtbuf [j]);
2300 }
2301
2302 op += strlen (op);
2303 if (op >= endbuf) {
2304 log_error ("Option data exceeds"
2305 " maximum size %d", MAX_OUTPUT_SIZE);
2306 return ("<error>");
2307 }
2308
2309 if (dp == data + len)
2310 break;
2311 if (j + 1 < numelem && comma != ':')
2312 *op++ = ' ';
2313 }
2314 if (i + 1 < numhunk) {
2315 *op++ = comma;
2316 }
2317 if (dp == data + len)
2318 break;
2319 }
2320 return optbuf;
2321}
2322
2324 in_options, cfg_options, options, scope, code, file, line)
2325 struct data_string *result;
2326 struct universe *universe;
2327 struct packet *packet;
2328 struct lease *lease;
2329 struct client_state *client_state;
2330 struct option_state *in_options;
2331 struct option_state *cfg_options;
2332 struct option_state *options;
2333 struct binding_scope **scope;
2334 unsigned code;
2335 const char *file;
2336 int line;
2337{
2338 struct option_cache *oc;
2339
2340 if (!universe -> lookup_func)
2341 return 0;
2342 oc = ((*universe -> lookup_func) (universe, options, code));
2343 if (!oc)
2344 return 0;
2346 in_options, cfg_options, scope, oc,
2347 file, line))
2348 return 0;
2349 return 1;
2350}
2351
2352/*
2353 * Look for the option and dig out the value assoicated with it.
2354 * Currently this is used for 1 byte integers, it maybe expanded
2355 * in the future to handle other integers at which point it will
2356 * need a size argument.
2357 */
2359 in_options, cfg_options, options, scope, code, file, line)
2360 int *result;
2361 struct universe *universe;
2362 struct packet *packet;
2363 struct lease *lease;
2364 struct client_state *client_state;
2365 struct option_state *in_options;
2366 struct option_state *cfg_options;
2367 struct option_state *options;
2368 struct binding_scope **scope;
2369 unsigned code;
2370 const char *file;
2371 int line;
2372{
2373 struct option_cache *oc;
2374 struct data_string d1;
2375 int rcode = 0;
2376
2377 /* basic sanity checks */
2378 if ((options == NULL) || (universe->lookup_func == NULL))
2379 return (0);
2380
2381 /* find the option cache */
2382 oc = ((*universe->lookup_func)(universe, options, code));
2383 if (!oc)
2384 return (0);
2385
2386 /* if there is a value get it into the string */
2387 memset(&d1, 0, sizeof(d1));
2389 in_options, cfg_options, scope, oc,
2390 file, line))
2391 return (0);
2392
2393 /* If the length matches extract the value for the return */
2394 if (d1.len == 1) {
2395 *result = d1.data[0];
2396 rcode = 1;
2397 }
2398 data_string_forget(&d1, MDL);
2399
2400 return (rcode);
2401}
2402
2403void set_option (universe, options, option, op)
2404 struct universe *universe;
2405 struct option_state *options;
2406 struct option_cache *option;
2407 enum statement_op op;
2408{
2409 struct option_cache *oc, *noc;
2410
2411 switch (op) {
2412 case if_statement:
2413 case add_statement:
2414 case eval_statement:
2415 case break_statement:
2416 default:
2417 log_error ("bogus statement type in set_option.");
2418 break;
2419
2421 oc = lookup_option (universe, options,
2422 option -> option -> code);
2423 if (oc)
2424 break;
2425 save_option (universe, options, option);
2426 break;
2427
2430 /* Install the option, replacing any existing version. */
2431 save_option (universe, options, option);
2432 break;
2433
2436 oc = lookup_option (universe, options,
2437 option -> option -> code);
2438 if (!oc) {
2439 save_option (universe, options, option);
2440 break;
2441 }
2442 /* If it's not an expression, make it into one. */
2443 if (!oc -> expression && oc -> data.len) {
2444 if (!expression_allocate (&oc -> expression, MDL)) {
2445 log_error ("Can't allocate const expression.");
2446 break;
2447 }
2448 oc -> expression -> op = expr_const_data;
2450 (&oc -> expression -> data.const_data,
2451 &oc -> data, MDL);
2452 data_string_forget (&oc -> data, MDL);
2453 }
2454 noc = (struct option_cache *)0;
2455 if (!option_cache_allocate (&noc, MDL))
2456 break;
2457 if (op == append_option_statement) {
2458 if (!make_concat (&noc -> expression,
2459 oc -> expression,
2460 option -> expression)) {
2462 break;
2463 }
2464 } else {
2465 if (!make_concat (&noc -> expression,
2466 option -> expression,
2467 oc -> expression)) {
2469 break;
2470 }
2471 }
2472
2473 /* If we are trying to combine compressed domain-lists then
2474 * we need to change the expression opcode. The lists must
2475 * be decompressed, combined, and then recompressed to work
2476 * correctly. You cannot simply add two compressed lists
2477 * together. */
2478 switch (((memcmp(option->option->format, "Dc", 2) == 0) +
2479 (memcmp(oc->option->format, "Dc", 2) == 0))) {
2480 case 1:
2481 /* Only one is "Dc", this won't work
2482 * Not sure if you can make this occur, but just
2483 * in case. */
2484 log_error ("Both options must be Dc format");
2486 return;
2487 case 2:
2488 /* Both are "Dc", change the code */
2490 break;
2491 default:
2492 /* Neither are "Dc", so as you were */
2493 break;
2494 }
2495
2496 option_reference(&(noc->option), oc->option, MDL);
2497 save_option (universe, options, noc);
2499 break;
2500 }
2501}
2502
2503struct option_cache *lookup_option (universe, options, code)
2504 struct universe *universe;
2505 struct option_state *options;
2506 unsigned code;
2507{
2508 if (!options)
2509 return (struct option_cache *)0;
2510 if (universe -> lookup_func)
2511 return (*universe -> lookup_func) (universe, options, code);
2512 else
2513 log_error ("can't look up options in %s space.",
2514 universe -> name);
2515 return (struct option_cache *)0;
2516}
2517
2519 struct universe *universe;
2520 struct option_state *options;
2521 unsigned code;
2522{
2523 int hashix;
2524 pair bptr;
2525 pair *hash;
2526
2527 /* Make sure there's a hash table. */
2528 if (universe -> index >= options -> universe_count ||
2529 !(options -> universes [universe -> index]))
2530 return (struct option_cache *)0;
2531
2532 hash = options -> universes [universe -> index];
2533
2534 hashix = compute_option_hash (code);
2535 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
2536 if (((struct option_cache *)(bptr -> car)) -> option -> code ==
2537 code)
2538 return (struct option_cache *)(bptr -> car);
2539 }
2540 return (struct option_cache *)0;
2541}
2542
2543/* Save a specified buffer into an option cache. */
2544int
2546 struct buffer *bp, unsigned char *buffer, unsigned length,
2547 unsigned code, int terminatep)
2548{
2549 struct option_cache *op = NULL;
2550 int status = 1;
2551
2552 status = prepare_option_buffer(universe, bp, buffer, length, code,
2553 terminatep, &op);
2554
2555 if (status == 0)
2556 goto cleanup;
2557
2558 save_option(universe, options, op);
2559
2560 cleanup:
2561 if (op != NULL)
2563
2564 return status;
2565}
2566
2567/* Append a specified buffer onto the tail of an option cache. */
2568int
2570 struct buffer *bp, unsigned char *buffer, unsigned length,
2571 unsigned code, int terminatep)
2572{
2573 struct option_cache *op = NULL;
2574 int status = 1;
2575
2576 status = prepare_option_buffer(universe, bp, buffer, length, code,
2577 terminatep, &op);
2578
2579 if (status == 0)
2580 goto cleanup;
2581
2582 also_save_option(universe, options, op);
2583
2584 cleanup:
2585 if (op != NULL)
2587
2588 return status;
2589}
2590
2591/* Create/copy a buffer into a new option cache. */
2592static int
2593prepare_option_buffer(struct universe *universe, struct buffer *bp,
2594 unsigned char *buffer, unsigned length, unsigned code,
2595 int terminatep, struct option_cache **opp)
2596{
2597 struct buffer *lbp = NULL;
2598 struct option *option = NULL;
2599 struct option_cache *op;
2600 int status = 1;
2601
2602 /* Code sizes of 8, 16, and 32 bits are allowed. */
2603 switch(universe->tag_size) {
2604 case 1:
2605 if (code > 0xff)
2606 return 0;
2607 break;
2608 case 2:
2609 if (code > 0xffff)
2610 return 0;
2611 break;
2612 case 4:
2613 if (code > 0xffffffff)
2614 return 0;
2615 break;
2616
2617 default:
2618 log_fatal("Inconsistent universe tag size at %s:%d.", MDL);
2619 }
2620
2621 option_code_hash_lookup(&option, universe->code_hash, &code, 0, MDL);
2622
2623 /* If we created an option structure for each option a client
2624 * supplied, it's possible we may create > 2^32 option structures.
2625 * That's not feasible. So by failing to enter these option
2626 * structures into the code and name hash tables, references will
2627 * never be more than 1 - when the option cache is destroyed, this
2628 * will be cleaned up.
2629 */
2630 if (!option) {
2631 char nbuf[sizeof("unknown-4294967295")];
2632
2633 sprintf(nbuf, "unknown-%u", code);
2634
2635 option = new_option(nbuf, MDL);
2636
2637 if (!option)
2638 return 0;
2639
2642 option->code = code;
2643
2644 /* new_option() doesn't set references, pretend. */
2645 option->refcnt = 1;
2646 }
2647
2648 if (!option_cache_allocate (opp, MDL)) {
2649 log_error("No memory for option code %s.%s.",
2651 status = 0;
2652 goto cleanup;
2653 }
2654
2655 /* Pointer rather than double pointer makes for less parens. */
2656 op = *opp;
2657
2659
2660 /* If we weren't passed a buffer in which the data are saved and
2661 refcounted, allocate one now. */
2662 if (!bp) {
2663 if (!buffer_allocate (&lbp, length + terminatep, MDL)) {
2664 log_error ("no memory for option buffer.");
2665
2666 status = 0;
2667 goto cleanup;
2668 }
2669 memcpy (lbp -> data, buffer, length + terminatep);
2670 bp = lbp;
2671 buffer = &bp -> data [0]; /* Refer to saved buffer. */
2672 }
2673
2674 /* Reference buffer copy to option cache. */
2675 op -> data.buffer = (struct buffer *)0;
2676 buffer_reference (&op -> data.buffer, bp, MDL);
2677
2678 /* Point option cache into buffer. */
2679 op -> data.data = buffer;
2680 op -> data.len = length;
2681
2682 if (terminatep) {
2683 /* NUL terminate (we can get away with this because we (or
2684 the caller!) allocated one more than the buffer size, and
2685 because the byte following the end of an option is always
2686 the code of the next option, which the caller is getting
2687 out of the *original* buffer. */
2688 buffer [length] = 0;
2689 op -> data.terminated = 1;
2690 } else
2691 op -> data.terminated = 0;
2692
2693 /* If this option is ultimately a text option, null determinate to
2694 * comply with RFC2132 section 2. Mark a flag so this can be sensed
2695 * later to echo NULLs back to clients that supplied them (they
2696 * probably expect them).
2697 */
2699 int min_len = format_min_length(option->format, op);
2700
2701 while ((op->data.len > min_len) &&
2702 (op->data.data[op->data.len-1] == '\0')) {
2703 op->data.len--;
2704 op->flags |= OPTION_HAD_NULLS;
2705 }
2706 }
2707
2708 /* And let go of our references. */
2709 cleanup:
2710 if (lbp != NULL)
2711 buffer_dereference(&lbp, MDL);
2713
2714 return status;
2715}
2716
2717static void
2718count_options(struct option_cache *dummy_oc,
2719 struct packet *dummy_packet,
2720 struct lease *dummy_lease,
2721 struct client_state *dummy_client_state,
2722 struct option_state *dummy_opt_state,
2723 struct option_state *opt_state,
2724 struct binding_scope **dummy_binding_scope,
2725 struct universe *dummy_universe,
2726 void *void_accumulator) {
2727 int *accumulator = (int *)void_accumulator;
2728
2729 *accumulator += 1;
2730}
2731
2732static void
2733collect_oro(struct option_cache *oc,
2734 struct packet *dummy_packet,
2735 struct lease *dummy_lease,
2736 struct client_state *dummy_client_state,
2737 struct option_state *dummy_opt_state,
2738 struct option_state *opt_state,
2739 struct binding_scope **dummy_binding_scope,
2740 struct universe *dummy_universe,
2741 void *void_oro) {
2742 struct data_string *oro = (struct data_string *)void_oro;
2743
2744 putUShort(oro->buffer->data + oro->len, oc->option->code);
2745 oro->len += 2;
2746}
2747
2748/* build_server_oro() is presently unusued, but may be used at a future date
2749 * with support for Reconfigure messages (as a hint to the client about new
2750 * option value contents).
2751 */
2752void
2754 struct option_state *options,
2755 const char *file, int line) {
2756 int num_opts;
2757 int i;
2758 struct option *o;
2759
2760 /*
2761 * Count the number of options, so we can allocate enough memory.
2762 * We want to mention sub-options too, so check all universes.
2763 */
2764 num_opts = 0;
2765 option_space_foreach(NULL, NULL, NULL, NULL, options,
2766 NULL, &dhcpv6_universe, (void *)&num_opts,
2767 count_options);
2768 for (i=0; i < options->universe_count; i++) {
2769 if (options->universes[i] != NULL) {
2770 o = universes[i]->enc_opt;
2771 while (o != NULL) {
2772 if (o->universe == &dhcpv6_universe) {
2773 num_opts++;
2774 break;
2775 }
2776 o = o->universe->enc_opt;
2777 }
2778 }
2779 }
2780
2781 /*
2782 * Allocate space.
2783 */
2784 memset(server_oro, 0, sizeof(*server_oro));
2785 if (!buffer_allocate(&server_oro->buffer, num_opts * 2, MDL)) {
2786 log_fatal("no memory to build server ORO");
2787 }
2788 server_oro->data = server_oro->buffer->data;
2789
2790 /*
2791 * Copy the data in.
2792 * We want to mention sub-options too, so check all universes.
2793 */
2794 server_oro->len = 0; /* gets set in collect_oro */
2795 option_space_foreach(NULL, NULL, NULL, NULL, options,
2796 NULL, &dhcpv6_universe, (void *)server_oro,
2797 collect_oro);
2798 for (i=0; i < options->universe_count; i++) {
2799 if (options->universes[i] != NULL) {
2800 o = universes[i]->enc_opt;
2801 while (o != NULL) {
2802 if (o->universe == &dhcpv6_universe) {
2803 unsigned char *tmp;
2804 tmp = server_oro->buffer->data;
2805 putUShort(tmp + server_oro->len,
2806 o->code);
2807 server_oro->len += 2;
2808 break;
2809 }
2810 o = o->universe->enc_opt;
2811 }
2812 }
2813 }
2814}
2815
2816/* Wrapper function to put an option cache into an option state. */
2817void
2819 struct option_cache *oc)
2820{
2821 if (universe->save_func)
2822 (*universe->save_func)(universe, options, oc, ISC_FALSE);
2823 else
2824 log_error("can't store options in %s space.", universe->name);
2825}
2826
2827/* Wrapper function to append an option cache into an option state's list. */
2828void
2830 struct option_cache *oc)
2831{
2832 if (universe->save_func)
2833 (*universe->save_func)(universe, options, oc, ISC_TRUE);
2834 else
2835 log_error("can't store options in %s space.", universe->name);
2836}
2837
2838void
2840 struct option_cache *oc, isc_boolean_t appendp)
2841{
2842 int hashix;
2843 pair bptr;
2844 pair *hash = options -> universes [universe -> index];
2845 struct option_cache **ocloc;
2846
2847 if (oc -> refcnt == 0)
2848 abort ();
2849
2850 /* Compute the hash. */
2851 hashix = compute_option_hash (oc -> option -> code);
2852
2853 /* If there's no hash table, make one. */
2854 if (!hash) {
2855 hash = (pair *)dmalloc (OPTION_HASH_SIZE * sizeof *hash, MDL);
2856 if (!hash) {
2857 log_error ("no memory to store %s.%s",
2858 universe -> name, oc -> option -> name);
2859 return;
2860 }
2861 memset (hash, 0, OPTION_HASH_SIZE * sizeof *hash);
2862 options -> universes [universe -> index] = (void *)hash;
2863 } else {
2864 /* Try to find an existing option matching the new one. */
2865 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
2866 if (((struct option_cache *)
2867 (bptr -> car)) -> option -> code ==
2868 oc -> option -> code)
2869 break;
2870 }
2871
2872 /* Deal with collisions on the hash list. */
2873 if (bptr) {
2874 ocloc = (struct option_cache **)&bptr->car;
2875
2876 /*
2877 * If appendp is set, append it onto the tail of the
2878 * ->next list. If it is not set, rotate it into
2879 * position at the head of the list.
2880 */
2881 if (appendp) {
2882 do {
2883 ocloc = &(*ocloc)->next;
2884 } while (*ocloc != NULL);
2885 } else {
2887 }
2888
2889 option_cache_reference(ocloc, oc, MDL);
2890 return;
2891 }
2892 }
2893
2894 /* Otherwise, just put the new one at the head of the list. */
2895 bptr = new_pair (MDL);
2896 if (!bptr) {
2897 log_error ("No memory for option_cache reference.");
2898 return;
2899 }
2900 bptr -> cdr = hash [hashix];
2901 bptr -> car = 0;
2902 option_cache_reference ((struct option_cache **)&bptr -> car, oc, MDL);
2903 hash [hashix] = bptr;
2904}
2905
2906void delete_option (universe, options, code)
2907 struct universe *universe;
2908 struct option_state *options;
2909 int code;
2910{
2911 if (universe -> delete_func)
2912 (*universe -> delete_func) (universe, options, code);
2913 else
2914 log_error ("can't delete options from %s space.",
2915 universe -> name);
2916}
2917
2918void delete_hashed_option (universe, options, code)
2919 struct universe *universe;
2920 struct option_state *options;
2921 int code;
2922{
2923 int hashix;
2924 pair bptr, prev = (pair)0;
2925 pair *hash = options -> universes [universe -> index];
2926
2927 /* There may not be any options in this space. */
2928 if (!hash)
2929 return;
2930
2931 /* Try to find an existing option matching the new one. */
2932 hashix = compute_option_hash (code);
2933 for (bptr = hash [hashix]; bptr; bptr = bptr -> cdr) {
2934 if (((struct option_cache *)(bptr -> car)) -> option -> code
2935 == code)
2936 break;
2937 prev = bptr;
2938 }
2939 /* If we found one, wipe it out... */
2940 if (bptr) {
2941 if (prev)
2942 prev -> cdr = bptr -> cdr;
2943 else
2944 hash [hashix] = bptr -> cdr;
2946 ((struct option_cache **)(&bptr -> car), MDL);
2947 free_pair (bptr, MDL);
2948 }
2949}
2950
2951extern struct option_cache *free_option_caches; /* XXX */
2952
2954 struct option_cache **ptr;
2955 const char *file;
2956 int line;
2957{
2958 if (!ptr || !*ptr) {
2959 log_error ("Null pointer in option_cache_dereference: %s(%d)",
2960 file, line);
2961#if defined (POINTER_DEBUG)
2962 abort ();
2963#else
2964 return 0;
2965#endif
2966 }
2967
2968 (*ptr) -> refcnt--;
2969 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
2970 if (!(*ptr) -> refcnt) {
2971 if ((*ptr) -> data.buffer)
2972 data_string_forget (&(*ptr) -> data, file, line);
2973 if ((*ptr)->option)
2974 option_dereference(&(*ptr)->option, MDL);
2975 if ((*ptr) -> expression)
2977 file, line);
2978 if ((*ptr) -> next)
2979 option_cache_dereference (&((*ptr) -> next),
2980 file, line);
2981 /* Put it back on the free list... */
2982 (*ptr) -> expression = (struct expression *)free_option_caches;
2983 free_option_caches = *ptr;
2984 dmalloc_reuse (free_option_caches, (char *)0, 0, 0);
2985 }
2986 if ((*ptr) -> refcnt < 0) {
2987 log_error ("%s(%d): negative refcnt!", file, line);
2988#if defined (DEBUG_RC_HISTORY)
2989 dump_rc_history (*ptr);
2990#endif
2991#if defined (POINTER_DEBUG)
2992 abort ();
2993#else
2994 *ptr = (struct option_cache *)0;
2995 return 0;
2996#endif
2997 }
2998 *ptr = (struct option_cache *)0;
2999 return 1;
3000
3001}
3002
3004 struct universe *universe;
3005 struct option_state *state;
3006 const char *file;
3007 int line;
3008{
3009 pair *heads;
3010 pair cp, next;
3011 int i;
3012
3013 /* Get the pointer to the array of hash table bucket heads. */
3014 heads = (pair *)(state -> universes [universe -> index]);
3015 if (!heads)
3016 return 0;
3017
3018 /* For each non-null head, loop through all the buckets dereferencing
3019 the attached option cache structures and freeing the buckets. */
3020 for (i = 0; i < OPTION_HASH_SIZE; i++) {
3021 for (cp = heads [i]; cp; cp = next) {
3022 next = cp -> cdr;
3024 ((struct option_cache **)&cp -> car,
3025 file, line);
3026 free_pair (cp, file, line);
3027 }
3028 }
3029
3030 dfree (heads, file, line);
3031 state -> universes [universe -> index] = (void *)0;
3032 return 1;
3033}
3034
3035/* The 'data_string' primitive doesn't have an appension mechanism.
3036 * This function must then append a new option onto an existing buffer
3037 * by first duplicating the original buffer and appending the desired
3038 * values, followed by coping the new value into place.
3039 */
3040int
3042 struct option *option, struct data_string *src)
3043{
3044 struct data_string tmp;
3045
3046 if (src->len == 0 && option->format[0] != 'Z')
3047 return 0;
3048
3049 memset(&tmp, 0, sizeof(tmp));
3050
3051 /* Allocate a buffer to hold existing data, the current option's
3052 * tag and length, and the option's content.
3053 */
3054 if (!buffer_allocate(&tmp.buffer,
3055 (dst->len + universe->length_size +
3056 universe->tag_size + src->len), MDL)) {
3057 /* XXX: This kills all options presently stored in the
3058 * destination buffer. This is the way the original code
3059 * worked, and assumes an 'all or nothing' approach to
3060 * eg encapsulated option spaces. It may or may not be
3061 * desirable.
3062 */
3063 data_string_forget(dst, MDL);
3064 return 0;
3065 }
3066 tmp.data = tmp.buffer->data;
3067
3068 /* Copy the existing data off the destination. */
3069 if (dst->len != 0)
3070 memcpy(tmp.buffer->data, dst->data, dst->len);
3071 tmp.len = dst->len;
3072
3073 /* Place the new option tag and length. */
3074 (*universe->store_tag)(tmp.buffer->data + tmp.len, option->code);
3075 tmp.len += universe->tag_size;
3076 (*universe->store_length)(tmp.buffer->data + tmp.len, src->len);
3077 tmp.len += universe->length_size;
3078
3079 /* Copy the option contents onto the end. */
3080 memcpy(tmp.buffer->data + tmp.len, src->data, src->len);
3081 tmp.len += src->len;
3082
3083 /* Play the shell game. */
3084 data_string_forget(dst, MDL);
3085 data_string_copy(dst, &tmp, MDL);
3086 data_string_forget(&tmp, MDL);
3087 return 1;
3088}
3089
3090int
3092 struct packet *packet, struct lease *lease,
3093 struct client_state *client_state,
3094 struct option_state *in_options, struct option_state *cfg_options,
3095 struct binding_scope **scope, struct option_cache *oc)
3096{
3097 struct data_string tmp;
3098 struct universe *subu=NULL;
3099 int status;
3100 char *start, *end;
3101
3102 memset(&tmp, 0, sizeof(tmp));
3103
3105 in_options, cfg_options, scope, oc, MDL)) {
3106 /* If the option is an extended 'e'ncapsulation (not a
3107 * direct 'E'ncapsulation), append the encapsulated space
3108 * onto the currently prepared value.
3109 */
3110 do {
3111 if (oc->option->format &&
3112 oc->option->format[0] == 'e') {
3113 /* Skip forward to the universe name. */
3114 start = strchr(oc->option->format, 'E');
3115 if (start == NULL)
3116 break;
3117
3118 /* Locate the name-terminating '.'. */
3119 end = strchr(++start, '.');
3120
3121 /* A zero-length name is not allowed in
3122 * these kinds of encapsulations.
3123 */
3124 if (end == NULL || start == end)
3125 break;
3126
3127 universe_hash_lookup(&subu, universe_hash,
3128 start, end - start, MDL);
3129
3130 if (subu == NULL) {
3131 log_error("store_option: option %d "
3132 "refers to unknown "
3133 "option space '%.*s'.",
3134 oc->option->code,
3135 (int)(end - start), start);
3136 break;
3137 }
3138
3139 /* Append encapsulations, if any. We
3140 * already have the prepended values, so
3141 * we send those even if there are no
3142 * encapsulated options (and ->encapsulate()
3143 * returns zero).
3144 */
3145 subu->encapsulate(&tmp, packet, lease,
3146 client_state, in_options,
3147 cfg_options, scope, subu);
3148 subu = NULL;
3149 }
3150 } while (ISC_FALSE);
3151
3152 status = append_option(result, universe, oc->option, &tmp);
3153 data_string_forget(&tmp, MDL);
3154
3155 return status;
3156 }
3157
3158 return 0;
3159}
3160
3162 in_options, cfg_options, scope, name)
3163 struct data_string *result;
3164 struct packet *packet;
3165 struct lease *lease;
3166 struct client_state *client_state;
3167 struct option_state *in_options;
3168 struct option_state *cfg_options;
3169 struct binding_scope **scope;
3170 struct data_string *name;
3171{
3172 struct universe *u = NULL;
3173 int status = 0;
3174
3175 universe_hash_lookup(&u, universe_hash,
3176 (const char *)name->data, name->len, MDL);
3177 if (u == NULL) {
3178 log_error("option_space_encapsulate: option space '%.*s' does "
3179 "not exist, but is configured.",
3180 (int)name->len, name->data);
3181 return status;
3182 }
3183
3184 if (u->encapsulate != NULL) {
3185 if (u->encapsulate(result, packet, lease, client_state,
3186 in_options, cfg_options, scope, u))
3187 status = 1;
3188 } else
3189 log_error("encapsulation requested for '%s' with no support.",
3190 name->data);
3191
3192 return status;
3193}
3194
3195/* Attempt to store any 'E'ncapsulated options that have not yet been
3196 * placed on the option buffer by the above (configuring a value in
3197 * the space over-rides any values in the child universe).
3198 *
3199 * Note that there are far fewer universes than there will ever be
3200 * options in any universe. So it is faster to traverse the
3201 * configured universes, checking if each is encapsulated in the
3202 * current universe, and if so attempting to do so.
3203 *
3204 * For each configured universe for this configuration option space,
3205 * which is encapsulated within the current universe, can not be found
3206 * by the lookup function (the universe-specific encapsulation
3207 * functions would already have stored such a value), and encapsulates
3208 * at least one option, append it.
3209 */
3210static int
3211search_subencapsulation(struct data_string *result, struct packet *packet,
3212 struct lease *lease, struct client_state *client_state,
3213 struct option_state *in_options,
3214 struct option_state *cfg_options,
3215 struct binding_scope **scope,
3216 struct universe *universe)
3217{
3218 struct data_string sub;
3219 struct universe *subu;
3220 int i, status = 0;
3221
3222 memset(&sub, 0, sizeof(sub));
3223 for (i = 0 ; i < cfg_options->universe_count ; i++) {
3224 subu = universes[i];
3225
3226 if (subu == NULL)
3227 log_fatal("Impossible condition at %s:%d.", MDL);
3228
3229 if (subu->enc_opt != NULL &&
3230 subu->enc_opt->universe == universe &&
3231 subu->enc_opt->format != NULL &&
3232 subu->enc_opt->format[0] == 'E' &&
3233 lookup_option(universe, cfg_options,
3234 subu->enc_opt->code) == NULL &&
3235 subu->encapsulate(&sub, packet, lease, client_state,
3236 in_options, cfg_options,
3237 scope, subu)) {
3238 if (append_option(result, universe,
3239 subu->enc_opt, &sub))
3240 status = 1;
3241
3242 data_string_forget(&sub, MDL);
3243 }
3244 }
3245
3246 return status;
3247}
3248
3250 in_options, cfg_options, scope, universe)
3251 struct data_string *result;
3252 struct packet *packet;
3253 struct lease *lease;
3254 struct client_state *client_state;
3255 struct option_state *in_options;
3256 struct option_state *cfg_options;
3257 struct binding_scope **scope;
3258 struct universe *universe;
3259{
3260 pair p, *hash;
3261 int status;
3262 int i;
3263
3264 if (universe -> index >= cfg_options -> universe_count)
3265 return 0;
3266
3267 hash = cfg_options -> universes [universe -> index];
3268 if (!hash)
3269 return 0;
3270
3271 /* For each hash bucket, and each configured option cache within
3272 * that bucket, append the option onto the buffer in encapsulated
3273 * format appropriate to the universe.
3274 */
3275 status = 0;
3276 for (i = 0; i < OPTION_HASH_SIZE; i++) {
3277 for (p = hash [i]; p; p = p -> cdr) {
3278 if (store_option(result, universe, packet, lease,
3279 client_state, in_options, cfg_options,
3280 scope, (struct option_cache *)p->car))
3281 status = 1;
3282 }
3283 }
3284
3285 if (search_subencapsulation(result, packet, lease, client_state,
3286 in_options, cfg_options, scope, universe))
3287 status = 1;
3288
3289 return status;
3290}
3291
3293 in_options, cfg_options, scope, universe)
3294 struct data_string *result;
3295 struct packet *packet;
3296 struct lease *lease;
3297 struct client_state *client_state;
3298 struct option_state *in_options;
3299 struct option_state *cfg_options;
3300 struct binding_scope **scope;
3301 struct universe *universe;
3302{
3303 pair ocp;
3304 int status;
3305 static struct option_cache *no_nwip;
3306 struct data_string ds;
3307 struct option_chain_head *head;
3308
3309 if (universe -> index >= cfg_options -> universe_count)
3310 return 0;
3311 head = ((struct option_chain_head *)
3312 cfg_options -> universes [nwip_universe.index]);
3313 if (!head)
3314 return 0;
3315
3316 status = 0;
3317 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
3318 if (store_option (result, universe, packet,
3319 lease, client_state, in_options,
3320 cfg_options, scope,
3321 (struct option_cache *)ocp -> car))
3322 status = 1;
3323 }
3324
3325 /* If there's no data, the nwip suboption is supposed to contain
3326 a suboption saying there's no data. */
3327 if (!status) {
3328 if (!no_nwip) {
3329 unsigned one = 1;
3330 static unsigned char nni [] = { 1, 0 };
3331
3332 memset (&ds, 0, sizeof ds);
3333 ds.data = nni;
3334 ds.len = 2;
3335 if (option_cache_allocate (&no_nwip, MDL))
3336 data_string_copy (&no_nwip -> data, &ds, MDL);
3337 if (!option_code_hash_lookup(&no_nwip->option,
3338 nwip_universe.code_hash,
3339 &one, 0, MDL))
3340 log_fatal("Nwip option hash does not contain "
3341 "1 (%s:%d).", MDL);
3342 }
3343 if (no_nwip) {
3344 if (store_option (result, universe, packet, lease,
3345 client_state, in_options,
3346 cfg_options, scope, no_nwip))
3347 status = 1;
3348 }
3349 } else {
3350 memset (&ds, 0, sizeof ds);
3351
3352 /* If we have nwip options, the first one has to be the
3353 nwip-exists-in-option-area option. */
3354 if (!buffer_allocate (&ds.buffer, result -> len + 2, MDL)) {
3355 data_string_forget (result, MDL);
3356 return 0;
3357 }
3358 ds.data = &ds.buffer -> data [0];
3359 ds.buffer -> data [0] = 2;
3360 ds.buffer -> data [1] = 0;
3361 memcpy (&ds.buffer -> data [2], result -> data, result -> len);
3362 data_string_forget (result, MDL);
3363 data_string_copy (result, &ds, MDL);
3364 data_string_forget (&ds, MDL);
3365 }
3366
3367 return status;
3368}
3369
3370/* We don't want to use MRns_name_pton()...it doesn't tell us how many bytes
3371 * it has consumed, and it plays havoc with our escapes.
3372 *
3373 * So this function does DNS encoding, and returns either the number of
3374 * octects consumed (on success), or -1 on failure.
3375 */
3376static int
3377fqdn_encode(unsigned char *dst, int dstlen, const unsigned char *src,
3378 int srclen)
3379{
3380 unsigned char *out;
3381 int i, j, len, outlen=0;
3382
3383 out = dst;
3384 for (i = 0, j = 0 ; i < srclen ; i = j) {
3385 while ((j < srclen) && (src[j] != '.') && (src[j] != '\0'))
3386 j++;
3387
3388 len = j - i;
3389 if ((outlen + 1 + len) > dstlen)
3390 return -1;
3391
3392 *out++ = len;
3393 outlen++;
3394
3395 /* We only do one FQDN, ending in one root label. */
3396 if (len == 0)
3397 return outlen;
3398
3399 memcpy(out, src + i, len);
3400 out += len;
3401 outlen += len;
3402
3403 /* Advance past the root label. */
3404 j++;
3405 }
3406
3407 if ((outlen + 1) > dstlen)
3408 return -1;
3409
3410 /* Place the root label. */
3411 *out++ = 0;
3412 outlen++;
3413
3414 return outlen;
3415}
3416
3418 in_options, cfg_options, scope, universe)
3419 struct data_string *result;
3420 struct packet *packet;
3421 struct lease *lease;
3422 struct client_state *client_state;
3423 struct option_state *in_options;
3424 struct option_state *cfg_options;
3425 struct binding_scope **scope;
3426 struct universe *universe;
3427{
3428 pair ocp;
3429 struct data_string results [FQDN_SUBOPTION_COUNT + 1];
3430 int status = 1;
3431 int i;
3432 unsigned len;
3433 struct buffer *bp = (struct buffer *)0;
3434 struct option_chain_head *head;
3435
3436 /* If there's no FQDN universe, don't encapsulate. */
3437 if (fqdn_universe.index >= cfg_options -> universe_count)
3438 return 0;
3439 head = ((struct option_chain_head *)
3440 cfg_options -> universes [fqdn_universe.index]);
3441 if (!head)
3442 return 0;
3443
3444 /* Figure out the values of all the suboptions. */
3445 memset (results, 0, sizeof results);
3446 for (ocp = head -> first; ocp; ocp = ocp -> cdr) {
3447 struct option_cache *oc = (struct option_cache *)(ocp -> car);
3448 if (oc -> option -> code > FQDN_SUBOPTION_COUNT)
3449 continue;
3450 /* No need to check the return code, we check the length later */
3451 (void) evaluate_option_cache (&results[oc->option->code],
3453 in_options, cfg_options, scope,
3454 oc, MDL);
3455 }
3456 /* We add a byte for the flags field.
3457 * We add two bytes for the two RCODE fields.
3458 * We add a byte because we will prepend a label count.
3459 * We add a byte because the input len doesn't count null termination,
3460 * and we will add a root label.
3461 */
3462 len = 5 + results [FQDN_FQDN].len;
3463 /* Save the contents of the option in a buffer. */
3464 if (!buffer_allocate (&bp, len, MDL)) {
3465 log_error ("no memory for option buffer.");
3466 status = 0;
3467 goto exit;
3468 }
3469 buffer_reference (&result -> buffer, bp, MDL);
3470 result -> len = 3;
3471 result -> data = &bp -> data [0];
3472
3473 memset (&bp -> data [0], 0, len);
3474 /* XXX: The server should set bit 4 (yes, 4, not 3) to 1 if it is
3475 * not going to perform any ddns updates. The client should set the
3476 * bit if it doesn't want the server to perform any updates.
3477 * The problem is at this layer of abstraction we have no idea if
3478 * the caller is a client or server.
3479 *
3480 * See RFC4702, Section 3.1, 'The "N" bit'.
3481 *
3482 * if (?)
3483 * bp->data[0] |= 8;
3484 */
3485 if (results [FQDN_NO_CLIENT_UPDATE].len &&
3486 results [FQDN_NO_CLIENT_UPDATE].data [0])
3487 bp -> data [0] |= 2;
3488 if (results [FQDN_SERVER_UPDATE].len &&
3489 results [FQDN_SERVER_UPDATE].data [0])
3490 bp -> data [0] |= 1;
3491 if (results [FQDN_RCODE1].len)
3492 bp -> data [1] = results [FQDN_RCODE1].data [0];
3493 if (results [FQDN_RCODE2].len)
3494 bp -> data [2] = results [FQDN_RCODE2].data [0];
3495
3496 if (results [FQDN_ENCODED].len &&
3497 results [FQDN_ENCODED].data [0]) {
3498 bp->data[0] |= 4;
3499 if (results [FQDN_FQDN].len) {
3500 i = fqdn_encode(&bp->data[3], len - 3,
3501 results[FQDN_FQDN].data,
3502 results[FQDN_FQDN].len);
3503
3504 if (i < 0) {
3505 status = 0;
3506 goto exit;
3507 }
3508
3509 result->len += i;
3510 result->terminated = 0;
3511 }
3512 } else {
3513 if (results [FQDN_FQDN].len) {
3514 memcpy (&bp -> data [3], results [FQDN_FQDN].data,
3515 results [FQDN_FQDN].len);
3516 result -> len += results [FQDN_FQDN].len;
3517 result -> terminated = 0;
3518 }
3519 }
3520 exit:
3521 for (i = 1; i <= FQDN_SUBOPTION_COUNT; i++) {
3522 data_string_forget (&results[i], MDL);
3523 }
3524 buffer_dereference (&bp, MDL);
3525 if (!status)
3526 data_string_forget(result, MDL);
3527 return status;
3528}
3529
3530/*
3531 * Trap invalid attempts to inspect FQND6 contents.
3532 */
3533struct option_cache *
3535 unsigned code)
3536{
3537 log_fatal("Impossible condition at %s:%d.", MDL);
3538 return NULL;
3539}
3540
3541/*
3542 * Trap invalid attempts to save options directly to FQDN6 rather than FQDN.
3543 */
3544void
3546 struct option_cache *oc, isc_boolean_t appendp)
3547{
3548 log_fatal("Impossible condition at %s:%d.", MDL);
3549}
3550
3551/*
3552 * Trap invalid attempts to delete an option out of the FQDN6 universe.
3553 */
3554void
3556 int code)
3557{
3558 log_fatal("Impossible condition at %s:%d.", MDL);
3559}
3560
3561/* Shill to the DHCPv4 fqdn option cache any attempts to traverse the
3562 * V6's option cache entry.
3563 *
3564 * This function is called speculatively by dhclient to setup
3565 * environment variables. But it would have already called the
3566 * foreach on the normal fqdn universe, so this is superfluous.
3567 */
3568void
3570 struct client_state *client_state,
3571 struct option_state *in_options,
3572 struct option_state *cfg_options,
3573 struct binding_scope **scope,
3574 struct universe *u, void *stuff,
3575 void (*func)(struct option_cache *,
3576 struct packet *,
3577 struct lease *,
3578 struct client_state *,
3579 struct option_state *,
3580 struct option_state *,
3581 struct binding_scope **,
3582 struct universe *, void *))
3583{
3584 /* Pretend it is empty. */
3585 return;
3586}
3587
3588/* Turn the FQDN option space into a DHCPv6 FQDN option buffer.
3589 */
3590int
3592 struct packet *packet, struct lease *lease,
3593 struct client_state *client_state,
3594 struct option_state *in_options,
3595 struct option_state *cfg_options,
3596 struct binding_scope **scope,
3597 struct universe *universe)
3598{
3599 pair ocp;
3600 struct option_chain_head *head;
3601 struct option_cache *oc;
3602 unsigned char *data;
3603 int i, len, rval = 0, count;
3604 struct data_string results[FQDN_SUBOPTION_COUNT + 1];
3605
3606 if (fqdn_universe.index >= cfg_options->universe_count)
3607 return 0;
3608 head = ((struct option_chain_head *)
3609 cfg_options->universes[fqdn_universe.index]);
3610 if (head == NULL)
3611 return 0;
3612
3613 memset(results, 0, sizeof(results));
3614 for (ocp = head->first ; ocp != NULL ; ocp = ocp->cdr) {
3615 oc = (struct option_cache *)(ocp->car);
3616 if (oc->option->code > FQDN_SUBOPTION_COUNT)
3617 log_fatal("Impossible condition at %s:%d.", MDL);
3618 /* No need to check the return code, we check the length later */
3619 (void) evaluate_option_cache(&results[oc->option->code], packet,
3620 lease, client_state, in_options,
3621 cfg_options, scope, oc, MDL);
3622 }
3623
3624 /* We add a byte for the flags field at the start of the option.
3625 * We add a byte because we will prepend a label count.
3626 * We add a byte because the input length doesn't include a trailing
3627 * NULL, and we will add a root label.
3628 */
3629 len = results[FQDN_FQDN].len + 3;
3630 if (!buffer_allocate(&result->buffer, len, MDL)) {
3631 log_error("No memory for virtual option buffer.");
3632 goto exit;
3633 }
3634 data = result->buffer->data;
3635 result->data = data;
3636
3637 /* The first byte is the flags field. */
3638 result->len = 1;
3639 data[0] = 0;
3640 /* XXX: The server should set bit 3 (yes, 3, not 4) to 1 if we
3641 * are not going to perform any DNS updates. The problem is
3642 * that at this layer of abstraction, we do not know if the caller
3643 * is the client or the server.
3644 *
3645 * See RFC4704 Section 4.1, 'The "N" bit'.
3646 *
3647 * if (?)
3648 * data[0] |= 4;
3649 */
3650 if (results[FQDN_NO_CLIENT_UPDATE].len &&
3651 results[FQDN_NO_CLIENT_UPDATE].data[0])
3652 data[0] |= 2;
3653 if (results[FQDN_SERVER_UPDATE].len &&
3654 results[FQDN_SERVER_UPDATE].data[0])
3655 data[0] |= 1;
3656
3657 /* If there is no name, we're done. */
3658 if (results[FQDN_FQDN].len == 0) {
3659 rval = 1;
3660 goto exit;
3661 }
3662
3663 /* Convert textual representation to DNS format. */
3664 count = fqdn_encode(data + 1, len - 1,
3665 results[FQDN_FQDN].data, results[FQDN_FQDN].len);
3666
3667 if (count < 0) {
3668 rval = 0;
3669 data_string_forget(result, MDL);
3670 goto exit;
3671 }
3672
3673 result->len += count;
3674 result->terminated = 0;
3675
3676 /* Success! */
3677 rval = 1;
3678
3679 exit:
3680 for (i = 1 ; i <= FQDN_SUBOPTION_COUNT ; i++) {
3681 data_string_forget(&results[i], MDL);
3682 }
3683
3684 return rval;
3685}
3686
3687/* Read the DHCPv6 FQDN option's contents into the FQDN virtual space.
3688 */
3689int
3691 const unsigned char *buffer, unsigned length,
3692 struct universe *u)
3693{
3694 struct buffer *bp = NULL;
3695 unsigned char *first_dot;
3696 int len, hlen, dlen;
3697
3698 /* The FQDN option has to be at least 1 byte long. */
3699 if (length < 1)
3700 return 0;
3701
3702 /* Save the contents of the option in a buffer. There are 3
3703 * one-byte values we record from the packet. The input is
3704 * DNS encoded and to be safe we'll assume that each character
3705 * is non-printable and will be converted to an escaped number:
3706 * "\\nnn". Yes, we'll have dead space pretty much all the time
3707 * but the alternative is to basically dry run the conversion
3708 * first to calculate the precise size or reallocate to a smaller
3709 * buffer later, either of which is a bigger performance hit than
3710 * just doing a generous allocation. */
3711 unsigned bp_size = 3 + (length * 4);
3712
3713 if (!buffer_allocate(&bp, bp_size, MDL)) {
3714 log_error("No memory for dhcp6.fqdn option buffer.");
3715 return 0;
3716 }
3717
3718 /* The v6 FQDN is always 'encoded' per DNS. */
3719 bp->data[0] = 1;
3720 if (!save_option_buffer(&fqdn_universe, options, bp,
3721 bp->data, 1, FQDN_ENCODED, 0))
3722 goto error;
3723
3724 /* XXX: We need to process 'The "N" bit'. */
3725 if (buffer[0] & 1) /* server-update. */
3726 bp->data[2] = 1;
3727 else
3728 bp->data[2] = 0;
3729
3730 if (!save_option_buffer(&fqdn_universe, options, bp, bp->data + 2, 1,
3732 goto error;
3733
3734 if (buffer[0] & 2) /* no-client-update. */
3735 bp->data[1] = 1;
3736 else
3737 bp->data[1] = 0;
3738
3739 if (!save_option_buffer(&fqdn_universe, options, bp, bp->data + 1, 1,
3741 goto error;
3742
3743 /* Convert the domain name to textual representation for config. */
3744 len = MRns_name_ntop(buffer + 1, (char *)bp->data + 3, bp_size - 3);
3745 if (len == -1) {
3746 log_error("Unable to convert dhcp6.fqdn domain name to "
3747 "printable form.");
3748 goto error;
3749 }
3750
3751 /* Save the domain name. */
3752 if (len > 0) {
3753 unsigned char *fqdn_start = bp->data + 3;
3754
3755 if (!save_option_buffer(&fqdn_universe, options, bp,
3756 fqdn_start, len, FQDN_FQDN, 1))
3757 goto error;
3758
3759 first_dot = (unsigned char *)strchr((char *)fqdn_start, '.');
3760
3761 if (first_dot != NULL) {
3762 hlen = first_dot - fqdn_start;
3763 dlen = len - hlen;
3764 } else {
3765 hlen = len;
3766 dlen = 0;
3767 }
3768
3769 if (!save_option_buffer(&fqdn_universe, options, bp,
3770 fqdn_start, len, FQDN_FQDN, 1) ||
3771 ((hlen > 0) &&
3772 !save_option_buffer(&fqdn_universe, options, bp,
3773 fqdn_start, hlen,
3774 FQDN_HOSTNAME, 0)) ||
3775 ((dlen > 0) &&
3776 !save_option_buffer(&fqdn_universe, options, bp,
3777 first_dot, dlen, FQDN_DOMAINNAME, 0)))
3778 goto error;
3779 }
3780
3781 buffer_dereference(&bp, MDL);
3782 return 1;
3783
3784 error:
3785 buffer_dereference(&bp, MDL);
3786 return 0;
3787}
3788
3790 struct client_state *client_state,
3791 struct option_state *in_options,
3792 struct option_state *cfg_options,
3793 struct binding_scope **scope,
3794 struct universe *u, void *stuff,
3795 void (*func) (struct option_cache *,
3796 struct packet *,
3797 struct lease *, struct client_state *,
3798 struct option_state *,
3799 struct option_state *,
3800 struct binding_scope **,
3801 struct universe *, void *))
3802{
3803 if (u -> foreach)
3804 (*u -> foreach) (packet, lease, client_state, in_options,
3805 cfg_options, scope, u, stuff, func);
3806}
3807
3809 struct client_state *client_state,
3810 struct option_state *in_options,
3811 struct option_state *cfg_options,
3812 struct binding_scope **scope,
3813 struct universe *u, void *stuff,
3814 void (*func) (struct option_cache *,
3815 struct packet *,
3816 struct lease *, struct client_state *,
3817 struct option_state *,
3818 struct option_state *,
3819 struct binding_scope **,
3820 struct universe *, void *),
3821 struct option_cache *oc,
3822 const char *vsname)
3823{
3825 vsname);
3826 if (universe -> foreach)
3827 (*universe -> foreach) (packet, lease, client_state,
3828 in_options, cfg_options,
3829 scope, universe, stuff, func);
3830}
3831
3833 struct client_state *client_state,
3834 struct option_state *in_options,
3835 struct option_state *cfg_options,
3836 struct binding_scope **scope,
3837 struct universe *u, void *stuff,
3838 void (*func) (struct option_cache *,
3839 struct packet *,
3840 struct lease *,
3841 struct client_state *,
3842 struct option_state *,
3843 struct option_state *,
3844 struct binding_scope **,
3845 struct universe *, void *))
3846{
3847 pair *hash;
3848 int i;
3849 struct option_cache *oc;
3850
3851 if (cfg_options -> universe_count <= u -> index)
3852 return;
3853
3854 hash = cfg_options -> universes [u -> index];
3855 if (!hash)
3856 return;
3857 for (i = 0; i < OPTION_HASH_SIZE; i++) {
3858 pair p;
3859 /* XXX save _all_ options! XXX */
3860 for (p = hash [i]; p; p = p -> cdr) {
3861 oc = (struct option_cache *)p -> car;
3862 (*func) (oc, packet, lease, client_state,
3863 in_options, cfg_options, scope, u, stuff);
3864 }
3865 }
3866}
3867
3868void
3870 struct option_cache *oc, isc_boolean_t appendp)
3871{
3872 pair *tail;
3873 struct option_chain_head *head;
3874 struct option_cache **ocloc;
3875
3876 if (universe -> index >= options -> universe_count)
3877 return;
3878 head = ((struct option_chain_head *)
3879 options -> universes [universe -> index]);
3880 if (!head) {
3882 &options -> universes
3883 [universe -> index]), MDL))
3884 return;
3885 head = ((struct option_chain_head *)
3886 options -> universes [universe -> index]);
3887 }
3888
3889 /* Find the tail of the list. */
3890 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
3891 ocloc = (struct option_cache **)&(*tail)->car;
3892
3893 if (oc->option->code == (*ocloc)->option->code) {
3894 if (appendp) {
3895 do {
3896 ocloc = &(*ocloc)->next;
3897 } while (*ocloc != NULL);
3898 } else {
3900 }
3901 option_cache_reference(ocloc, oc, MDL);
3902 return;
3903 }
3904 }
3905
3906 *tail = cons (0, 0);
3907 if (*tail) {
3909 (&(*tail) -> car), oc, MDL);
3910 }
3911}
3912
3914 in_options, cfg_options, scope, universe)
3915 struct data_string *result;
3916 struct packet *packet;
3917 struct lease *lease;
3918 struct client_state *client_state;
3919 struct option_state *in_options;
3920 struct option_state *cfg_options;
3921 struct binding_scope **scope;
3922 struct universe *universe;
3923{
3924 int status = 0;
3925 pair oc;
3926 struct option_chain_head *head;
3927
3928 if (universe -> index >= cfg_options -> universe_count)
3929 return status;
3930 head = ((struct option_chain_head *)
3931 cfg_options -> universes [universe -> index]);
3932 if (!head)
3933 return status;
3934
3935 for (oc = head -> first; oc; oc = oc -> cdr) {
3936 if (store_option (result, universe, packet,
3937 lease, client_state, in_options, cfg_options,
3938 scope, (struct option_cache *)(oc -> car)))
3939 status = 1;
3940 }
3941
3942 if (search_subencapsulation(result, packet, lease, client_state,
3943 in_options, cfg_options, scope, universe))
3944 status = 1;
3945
3946 return status;
3947}
3948
3949void delete_linked_option (universe, options, code)
3950 struct universe *universe;
3951 struct option_state *options;
3952 int code;
3953{
3954 pair *tail, tmp = (pair)0;
3955 struct option_chain_head *head;
3956
3957 if (universe -> index >= options -> universe_count)
3958 return;
3959 head = ((struct option_chain_head *)
3960 options -> universes [universe -> index]);
3961 if (!head)
3962 return;
3963
3964 for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
3965 if (code ==
3966 ((struct option_cache *)(*tail) -> car) -> option -> code)
3967 {
3968 tmp = (*tail) -> cdr;
3970 (&(*tail) -> car), MDL);
3971 dfree (*tail, MDL);
3972 (*tail) = tmp;
3973 break;
3974 }
3975 }
3976}
3977
3979 struct universe *universe;
3980 struct option_state *options;
3981 unsigned code;
3982{
3983 pair oc;
3984 struct option_chain_head *head;
3985
3986 if (universe -> index >= options -> universe_count)
3987 return 0;
3988 head = ((struct option_chain_head *)
3989 options -> universes [universe -> index]);
3990 if (!head)
3991 return 0;
3992
3993 for (oc = head -> first; oc; oc = oc -> cdr) {
3994 if (code ==
3995 ((struct option_cache *)(oc -> car)) -> option -> code) {
3996 return (struct option_cache *)(oc -> car);
3997 }
3998 }
3999
4000 return (struct option_cache *)0;
4001}
4002
4004 struct universe *universe;
4005 struct option_state *state;
4006 const char *file;
4007 int line;
4008{
4010 ((struct option_chain_head **)
4011 (&state -> universes [universe -> index]), MDL));
4012}
4013
4015 struct client_state *client_state,
4016 struct option_state *in_options,
4017 struct option_state *cfg_options,
4018 struct binding_scope **scope,
4019 struct universe *u, void *stuff,
4020 void (*func) (struct option_cache *,
4021 struct packet *,
4022 struct lease *,
4023 struct client_state *,
4024 struct option_state *,
4025 struct option_state *,
4026 struct binding_scope **,
4027 struct universe *, void *))
4028{
4029 pair car;
4030 struct option_chain_head *head;
4031
4032 if (u -> index >= cfg_options -> universe_count)
4033 return;
4034 head = ((struct option_chain_head *)
4035 cfg_options -> universes [u -> index]);
4036 if (!head)
4037 return;
4038 for (car = head -> first; car; car = car -> cdr) {
4039 (*func) ((struct option_cache *)(car -> car),
4041 in_options, cfg_options, scope, u, stuff);
4042 }
4043}
4044
4045void do_packet (interface, packet, len, from_port, from, hfrom)
4046 struct interface_info *interface;
4047 struct dhcp_packet *packet;
4048 unsigned len;
4049 unsigned int from_port;
4050 struct iaddr from;
4051 struct hardware *hfrom;
4052{
4053 struct option_cache *op;
4054 struct packet *decoded_packet;
4055#if defined (DEBUG_MEMORY_LEAKAGE)
4056 unsigned long previous_outstanding = dmalloc_outstanding;
4057#endif
4058
4059#if defined (TRACING)
4060 trace_inpacket_stash(interface, packet, len, from_port, from, hfrom);
4061#endif
4062
4063 decoded_packet = NULL;
4064 if (!packet_allocate(&decoded_packet, MDL)) {
4065 log_error("do_packet: no memory for incoming packet!");
4066 return;
4067 }
4068 decoded_packet->raw = packet;
4069 decoded_packet->packet_length = len;
4070 decoded_packet->client_port = from_port;
4071 decoded_packet->client_addr = from;
4072 interface_reference(&decoded_packet->interface, interface, MDL);
4073 decoded_packet->haddr = hfrom;
4074
4075 if (packet->hlen > sizeof packet->chaddr) {
4076 packet_dereference(&decoded_packet, MDL);
4077 log_info("Discarding packet with bogus hlen.");
4078 return;
4079 }
4080
4081 /* Allocate packet->options now so it is non-null for all packets */
4082 decoded_packet->options_valid = 0;
4083 if (!option_state_allocate (&decoded_packet->options, MDL)) {
4084 packet_dereference(&decoded_packet, MDL);
4085 return;
4086 }
4087
4088 /* If there's an option buffer, try to parse it. */
4089 if (decoded_packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
4090 if (!parse_options(decoded_packet)) {
4091 packet_dereference (&decoded_packet, MDL);
4092 return;
4093 }
4094
4095 if (decoded_packet->options_valid &&
4097 decoded_packet->options,
4099 struct data_string dp;
4100 memset(&dp, 0, sizeof dp);
4101 evaluate_option_cache(&dp, decoded_packet, NULL, NULL,
4102 decoded_packet->options, NULL,
4103 NULL, op, MDL);
4104 if (dp.len > 0)
4105 decoded_packet->packet_type = dp.data[0];
4106 else
4107 decoded_packet->packet_type = 0;
4108 data_string_forget(&dp, MDL);
4109 }
4110 }
4111
4112 if (validate_packet(decoded_packet) != 0) {
4113 if (decoded_packet->packet_type)
4114 dhcp(decoded_packet);
4115 else
4116 bootp(decoded_packet);
4117 }
4118
4119 /* If the caller kept the packet, they'll have upped the refcnt. */
4120 packet_dereference(&decoded_packet, MDL);
4121
4122#if defined (DEBUG_MEMORY_LEAKAGE)
4123 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4124 dmalloc_generation,
4125 dmalloc_outstanding - previous_outstanding,
4126 dmalloc_outstanding, dmalloc_longterm);
4127 dmalloc_dump_outstanding();
4128#endif
4129#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4130 dump_rc_history(0);
4131#endif
4132}
4133
4134int
4135packet6_len_okay(const char *packet, int len) {
4136 if (len < 1) {
4137 return 0;
4138 }
4139 if ((packet[0] == DHCPV6_RELAY_FORW) ||
4140 (packet[0] == DHCPV6_RELAY_REPL)) {
4141 if (len >= offsetof(struct dhcpv6_relay_packet, options)) {
4142 return 1;
4143 } else {
4144 return 0;
4145 }
4146 } else {
4147 if (len >= offsetof(struct dhcpv6_packet, options)) {
4148 return 1;
4149 } else {
4150 return 0;
4151 }
4152 }
4153}
4154
4155#ifdef DHCPv6
4156void
4157do_packet6(struct interface_info *interface, const char *packet,
4158 int len, int from_port, const struct iaddr *from,
4159 isc_boolean_t was_unicast) {
4160 unsigned char msg_type;
4161 const struct dhcpv6_packet *msg;
4162 const struct dhcpv6_relay_packet *relay;
4163#ifdef DHCP4o6
4164 const struct dhcpv4_over_dhcpv6_packet *msg46;
4165#endif
4166 struct packet *decoded_packet;
4167#if defined (DEBUG_MEMORY_LEAKAGE)
4168 unsigned long previous_outstanding = dmalloc_outstanding;
4169#endif
4170
4171 if (!packet6_len_okay(packet, len)) {
4172 log_info("do_packet6: "
4173 "short packet from %s port %d, len %d, dropped",
4174 piaddr(*from), from_port, len);
4175 return;
4176 }
4177
4178 decoded_packet = NULL;
4179 if (!packet_allocate(&decoded_packet, MDL)) {
4180 log_error("do_packet6: no memory for incoming packet.");
4181 return;
4182 }
4183
4184 if (!option_state_allocate(&decoded_packet->options, MDL)) {
4185 log_error("do_packet6: no memory for options.");
4186 packet_dereference(&decoded_packet, MDL);
4187 return;
4188 }
4189
4190 /* IPv4 information, already set to 0 */
4191 /* decoded_packet->packet_type = 0; */
4192 /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
4193 /* decoded_packet->circuit_id = NULL; */
4194 /* decoded_packet->circuit_id_len = 0; */
4195 /* decoded_packet->remote_id = NULL; */
4196 /* decoded_packet->remote_id_len = 0; */
4197 decoded_packet->raw = (struct dhcp_packet *)packet;
4198 decoded_packet->packet_length = (unsigned)len;
4199 decoded_packet->client_port = from_port;
4200 decoded_packet->client_addr = *from;
4201 interface_reference(&decoded_packet->interface, interface, MDL);
4202
4203 decoded_packet->unicast = was_unicast;
4204
4205 msg_type = packet[0];
4206 if ((msg_type == DHCPV6_RELAY_FORW) ||
4207 (msg_type == DHCPV6_RELAY_REPL)) {
4208 int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
4209 relay = (const struct dhcpv6_relay_packet *)packet;
4210 decoded_packet->dhcpv6_msg_type = relay->msg_type;
4211
4212 /* relay-specific data */
4213 decoded_packet->dhcpv6_hop_count = relay->hop_count;
4214 memcpy(&decoded_packet->dhcpv6_link_address,
4215 relay->link_address, sizeof(relay->link_address));
4216 memcpy(&decoded_packet->dhcpv6_peer_address,
4217 relay->peer_address, sizeof(relay->peer_address));
4218
4219 if (!parse_option_buffer(decoded_packet->options,
4220 relay->options, len - relaylen,
4221 &dhcpv6_universe)) {
4222 /* no logging here, as parse_option_buffer() logs all
4223 cases where it fails */
4224 packet_dereference(&decoded_packet, MDL);
4225 return;
4226 }
4227#ifdef DHCP4o6
4228 } else if ((msg_type == DHCPV6_DHCPV4_QUERY) ||
4230 int msglen =
4231 (int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
4232 msg46 = (struct dhcpv4_over_dhcpv6_packet *)packet;
4233 decoded_packet->dhcpv6_msg_type = msg46->msg_type;
4234
4235 /* message-specific data */
4236 memcpy(decoded_packet->dhcp4o6_flags,
4237 msg46->flags,
4238 sizeof(decoded_packet->dhcp4o6_flags));
4239
4240 if (!parse_option_buffer(decoded_packet->options,
4241 msg46->options, len - msglen,
4242 &dhcpv6_universe)) {
4243 /* no logging here, as parse_option_buffer() logs all
4244 cases where it fails */
4245 packet_dereference(&decoded_packet, MDL);
4246 return;
4247 }
4248#endif
4249 } else {
4250 int msglen = (int)(offsetof(struct dhcpv6_packet, options));
4251 msg = (const struct dhcpv6_packet *)packet;
4252 decoded_packet->dhcpv6_msg_type = msg->msg_type;
4253
4254 /* message-specific data */
4255 memcpy(decoded_packet->dhcpv6_transaction_id,
4256 msg->transaction_id,
4257 sizeof(decoded_packet->dhcpv6_transaction_id));
4258
4259 if (!parse_option_buffer(decoded_packet->options,
4260 msg->options, len - msglen,
4261 &dhcpv6_universe)) {
4262 /* no logging here, as parse_option_buffer() logs all
4263 cases where it fails */
4264 packet_dereference(&decoded_packet, MDL);
4265 return;
4266 }
4267 }
4268
4269 dhcpv6(decoded_packet);
4270
4271 packet_dereference(&decoded_packet, MDL);
4272
4273#if defined (DEBUG_MEMORY_LEAKAGE)
4274 log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4275 dmalloc_generation,
4276 dmalloc_outstanding - previous_outstanding,
4277 dmalloc_outstanding, dmalloc_longterm);
4278 dmalloc_dump_outstanding();
4279#endif
4280#if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4281 dump_rc_history(0);
4282#endif
4283}
4284#endif /* DHCPv6 */
4285
4286int
4287pretty_escape(char **dst, char *dend, const unsigned char **src,
4288 const unsigned char *send)
4289{
4290 int count = 0;
4291
4292 /* If there aren't as many bytes left as there are in the source
4293 * buffer, don't even bother entering the loop.
4294 */
4295 if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4296 *dst == NULL || *src == NULL || (*dst >= dend) || (*src > send) ||
4297 ((send - *src) > (dend - *dst)))
4298 return -1;
4299
4300 for ( ; *src < send ; (*src)++) {
4301 if (!isascii (**src) || !isprint (**src)) {
4302 /* Skip trailing NUL. */
4303 if ((*src + 1) != send || **src != '\0') {
4304 if (*dst + 4 > dend)
4305 return -1;
4306
4307 sprintf(*dst, "\\%03o",
4308 **src);
4309 (*dst) += 4;
4310 count += 4;
4311 }
4312 } else if (**src == '"' || **src == '\'' || **src == '$' ||
4313 **src == '`' || **src == '\\' || **src == '|' ||
4314 **src == '&') {
4315 if (*dst + 2 > dend)
4316 return -1;
4317
4318 **dst = '\\';
4319 (*dst)++;
4320 **dst = **src;
4321 (*dst)++;
4322 count += 2;
4323 } else {
4324 if (*dst + 1 > dend)
4325 return -1;
4326
4327 **dst = **src;
4328 (*dst)++;
4329 count++;
4330 }
4331 }
4332
4333 return count;
4334}
4335
4336static int
4337pretty_text(char **dst, char *dend, const unsigned char **src,
4338 const unsigned char *send, int emit_quotes)
4339{
4340 int count;
4341
4342 if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4343 *dst == NULL || *src == NULL ||
4344 ((*dst + (emit_quotes ? 2 : 0)) > dend) || (*src > send))
4345 return -1;
4346
4347 if (emit_quotes) {
4348 **dst = '"';
4349 (*dst)++;
4350 }
4351
4352 /* dend-1 leaves 1 byte for the closing quote. */
4353 count = pretty_escape(dst, dend - (emit_quotes ? 1 : 0), src, send);
4354
4355 if (count == -1)
4356 return -1;
4357
4358 if (emit_quotes && (*dst < dend)) {
4359 **dst = '"';
4360 (*dst)++;
4361
4362 /* Includes quote prior to pretty_escape(); */
4363 count += 2;
4364 }
4365
4366 return count;
4367}
4368
4369static int
4370pretty_dname(char **dst, char *dend, const unsigned char *src,
4371 const unsigned char *send)
4372{
4373 const unsigned char *tend;
4374 const unsigned char *srcp = src;
4375 int count = 0;
4376 int tsiz, status;
4377
4378 if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4379 *dst == NULL || ((*dst + 1) > dend) || (src >= send))
4380 return -1;
4381
4382 do {
4383 /* Continue loop until end of src buffer. */
4384 if (srcp >= send)
4385 break;
4386
4387 /* Consume tag size. */
4388 tsiz = *srcp;
4389 srcp++;
4390
4391 /* At root, finis. */
4392 if (tsiz == 0)
4393 break;
4394
4395 tend = srcp + tsiz;
4396
4397 /* If the tag exceeds the source buffer, it's illegal.
4398 * This should also trap compression pointers (which should
4399 * not be in these buffers).
4400 */
4401 if (tend > send)
4402 return -1;
4403
4404 /* dend-1 leaves room for a trailing dot and quote. */
4405 status = pretty_escape(dst, dend-1, &srcp, tend);
4406
4407 if ((status == -1) || ((*dst + 1) > dend))
4408 return -1;
4409
4410 **dst = '.';
4411 (*dst)++;
4412 count += status + 1;
4413 }
4414 while(1);
4415
4416 return count;
4417}
4418
4419static int
4420pretty_domain(char **dst, char *dend, const unsigned char **src,
4421 const unsigned char *send)
4422{
4423 const unsigned char *tend;
4424 int count = 2;
4425 int tsiz, status;
4426
4427 if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4428 *dst == NULL || *src == NULL ||
4429 ((*dst + 2) > dend) || (*src >= send))
4430 return -1;
4431
4432 **dst = '"';
4433 (*dst)++;
4434
4435 do {
4436 /* Continue loop until end of src buffer. */
4437 if (*src >= send)
4438 break;
4439
4440 /* Consume tag size. */
4441 tsiz = **src;
4442 (*src)++;
4443
4444 /* At root, finis. */
4445 if (tsiz == 0)
4446 break;
4447
4448 tend = (*src) + tsiz;
4449
4450 /* If the tag exceeds the source buffer, it's illegal.
4451 * This should also trap compression pointers (which should
4452 * not be in these buffers).
4453 */
4454 if (tend > send)
4455 return -1;
4456
4457 /* dend-2 leaves room for a trailing dot and quote. */
4458 status = pretty_escape(dst, dend-2, src, tend);
4459
4460 if ((status == -1) || ((*dst + 2) > dend))
4461 return -1;
4462
4463 **dst = '.';
4464 (*dst)++;
4465 count += status + 1;
4466 }
4467 while(1);
4468
4469 **dst = '"';
4470 (*dst)++;
4471
4472 return count;
4473}
4474
4475/*
4476 * Add the option identified with the option number and data to the
4477 * options state.
4478 */
4479int
4481 unsigned int option_num,
4482 void *data,
4483 unsigned int data_len)
4484{
4485 struct option_cache *oc;
4486 struct option *option;
4487
4488 /* INSIST(options != NULL); */
4489 /* INSIST(data != NULL); */
4490
4491 option = NULL;
4492 if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
4493 &option_num, 0, MDL)) {
4494 log_error("Attempting to add unknown option %d.", option_num);
4495 return 0;
4496 }
4497
4498 oc = NULL;
4499 if (!option_cache_allocate(&oc, MDL)) {
4500 log_error("No memory for option cache adding %s (option %d).",
4501 option->name, option_num);
4502 /* Get rid of reference created during hash lookup. */
4504 return 0;
4505 }
4506
4507 if (!make_const_data(&oc->expression,
4508 data,
4509 data_len,
4510 0,
4511 0,
4512 MDL)) {
4513 log_error("No memory for constant data adding %s (option %d).",
4514 option->name, option_num);
4515 /* Get rid of reference created during hash lookup. */
4518 return 0;
4519 }
4520
4522 save_option(&dhcp_universe, options, oc);
4524
4525 /* Get rid of reference created during hash lookup. */
4527
4528 return 1;
4529}
4530
4539{
4540 struct option_cache *oc = NULL;
4541
4544 if (oc) {
4545 /* Let's check if client-identifier is sane */
4546 if (oc->data.len == 0) {
4547 log_debug("Dropped DHCPv4 packet with zero-length client-id");
4548 return (0);
4549
4550 } else if (oc->data.len == 1) {
4551 /*
4552 * RFC2132, section 9.14 states that minimum length of client-id
4553 * is 2. We will allow single-character client-ids for now (for
4554 * backwards compatibility), but warn the user that support for
4555 * this is against the standard.
4556 */
4557 log_debug("Accepted DHCPv4 packet with one-character client-id - "
4558 "a future version of ISC DHCP will reject this");
4559 }
4560 } else {
4563 if (oc) {
4564 /* Let's check if pxe-client-id is sane */
4565 if ((oc->data.len < 2) ||
4566 (oc->data.data[0] == '\0' &&
4567 oc->data.len != 17)) {
4568 log_debug("Dropped DHCPv4 packet with wrong "
4569 "(len == %d) pxe-client-id", oc->data.len);
4570 return (0);
4571 }
4572 } else {
4573 /*
4574 * If hlen is 0 we don't have any identifier, we warn the user
4575 * but continue processing the packet as we can.
4576 */
4577 if (packet->raw->hlen == 0) {
4578 log_debug("Received DHCPv4 packet without client-id"
4579 " option and empty hlen field.");
4580 }
4581 }
4582 }
4583
4584 /* @todo: Add checks for other received options */
4585
4586 return (1);
4587}
4588
4619 out_options, scope)
4620 struct packet *packet;
4621 struct lease *lease;
4622 struct client_state *client_state;
4623 struct option_state *in_options;
4624 struct option_state *out_options;
4625 struct binding_scope **scope;
4626{
4627 struct option_cache *oc = NULL;
4628 struct data_string name;
4629 struct option *option = NULL;
4631
4632 /* check if we are processing a packet, if not we can return */
4633 if ((packet == NULL) || (in_options == NULL) || (out_options == NULL))
4634 return;
4635
4636 /* Do we have any vendor option spaces? */
4637 if (vendor_cfg_option == NULL)
4638 return;
4639
4640 /* See if the admin has set a vendor option space name */
4641 oc = lookup_option(vendor_cfg_option->universe,
4642 out_options, vendor_cfg_option->code);
4643 if (oc == NULL)
4644 return;
4645
4646 memset(&name, 0, sizeof(name));
4648 in_options, out_options, scope, oc, MDL);
4649
4650 /* No name, all done */
4651 if (name.len == 0) {
4653 return;
4654 }
4655
4656 /* Get any vendor option information from the request */
4657 oc = lookup_option(&dhcp_universe, in_options, code);
4658
4659 /* No vendor option, all done */
4660 if ((oc == NULL) || (oc->data.len == 0)) {
4662 return;
4663 }
4664
4665 /* Get the proper option to pass to the parse routine */
4666 option_code_hash_lookup(&option, dhcp_universe.code_hash,
4667 &code, 0, MDL);
4668
4669 /* Now that we have the data from the vendor option and a vendor
4670 * option space try to parse things. On success the parsed options
4671 * will be added to the in_options list for future use. A return
4672 * return of 1 indicates success, but not much we can do on error */
4673 (void) parse_encapsulated_suboptions(in_options, option,
4674 oc->data.data, oc->data.len,
4676 (const char *)name.data);
4677
4678 /* Lastly clean up any left overs */
4681 return;
4682}
#define RC_MISC
Definition alloc.h:56
#define rc_register(file, line, reference, addr, refcnt, d, f)
Definition alloc.h:88
int buffer_reference(struct buffer **ptr, struct buffer *bp, const char *file, int line)
Definition alloc.c:698
int expression_allocate(struct expression **cptr, const char *file, int line)
Definition alloc.c:426
int option_cache_reference(struct option_cache **ptr, struct option_cache *src, const char *file, int line)
Definition alloc.c:651
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition alloc.c:679
int option_chain_head_allocate(struct option_chain_head **ptr, const char *file, int line)
Definition alloc.c:35
void free_pair(pair foo, const char *file, int line)
Definition alloc.c:400
void data_string_forget(struct data_string *data, const char *file, int line)
Definition alloc.c:1339
int option_state_allocate(struct option_state **ptr, const char *file, int line)
Definition alloc.c:846
void data_string_truncate(struct data_string *dp, int len)
Definition alloc.c:1352
int packet_dereference(struct packet **ptr, const char *file, int line)
Definition alloc.c:1081
struct option_cache * free_option_caches
Definition alloc.c:614
struct option * new_option(char *name, const char *file, int line) const
Definition alloc.c:300
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition alloc.c:1323
int packet_allocate(struct packet **ptr, const char *file, int line)
Definition alloc.c:1015
pair new_pair(char *file, int line) const
Definition alloc.c:379
int option_cache_allocate(struct option_cache **cptr, const char *file, int line)
Definition alloc.c:630
int option_chain_head_dereference(struct option_chain_head **ptr, const char *file, int line)
Definition alloc.c:95
int buffer_dereference(struct buffer **ptr, const char *file, int line)
Definition alloc.c:726
void save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
Definition options.c:2818
void delete_fqdn6_option(struct universe *universe, struct option_state *options, int code)
Definition options.c:3555
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition options.c:2953
const char * pretty_print_option(struct option *option, const unsigned char *data, unsigned len, int emit_commas, int emit_quotes)
Definition options.c:1793
int nwip_option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *universe)
Definition options.c:3292
void fqdn6_option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
Definition options.c:3569
void save_hashed_option(struct universe *universe, struct option_state *options, struct option_cache *oc, isc_boolean_t appendp)
Definition options.c:2839
void delete_option(struct universe *universe, struct option_state *options, int code)
Definition options.c:2906
struct universe * find_option_universe(struct option *eopt, const char *uname)
Definition options.c:292
int hashed_option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *universe)
Definition options.c:3249
#define MAX_OUTPUT_SIZE
Definition options.c:1792
#define PRIORITY_COUNT
int fqdn_universe_decode(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *u)
Definition options.c:366
int parse_encapsulated_suboptions(struct option_state *options, struct option *eopt, const unsigned char *buffer, unsigned len, struct universe *eu, const char *uname)
Definition options.c:337
int hashed_option_state_dereference(struct universe *universe, struct option_state *state, const char *file, int line)
Definition options.c:3003
int store_options(int *ocount, unsigned char *buffer, unsigned index, unsigned buflen, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, unsigned *priority_list, int priority_len, unsigned first_cutoff, int second_cutoff, int terminate, const char *vuname)
Definition options.c:1236
int linked_option_state_dereference(struct universe *universe, struct option_state *state, const char *file, int line)
Definition options.c:4003
void set_option(struct universe *universe, struct option_state *options, struct option_cache *option, enum statement_op op)
Definition options.c:2403
void suboption_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *), struct option_cache *oc, const char *vsname)
Definition options.c:3808
void hashed_option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
Definition options.c:3832
int option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct data_string *name)
Definition options.c:3161
struct option_cache * lookup_fqdn6_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:3534
int linked_option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *universe)
Definition options.c:3913
int append_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
Definition options.c:2569
int parse_options(struct packet *packet)
Definition options.c:49
void option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
Definition options.c:3789
int format_has_text(char *format) const
Definition options.c:1629
int save_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
Definition options.c:2545
int get_option(struct data_string *result, struct universe *universe, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct option_state *options, struct binding_scope **scope, unsigned code, const char *file, int line)
Definition options.c:2323
void linked_option_space_foreach(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *u, void *stuff, void(*func)(struct option_cache *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *, void *))
Definition options.c:4014
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:2503
void do_packet(struct interface_info *interface, struct dhcp_packet *packet, unsigned len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
Definition options.c:4045
struct option_cache * lookup_hashed_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:2518
int append_option(struct data_string *dst, struct universe *universe, struct option *option, struct data_string *src)
Definition options.c:3041
int pretty_escape(char **dst, char *dend, const unsigned char **src, const unsigned char *send)
Definition options.c:4287
struct option_cache * lookup_linked_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:3978
void delete_hashed_option(struct universe *universe, struct option_state *options, int code)
Definition options.c:2918
struct option * vendor_cfg_option
Definition options.c:34
void save_linked_option(struct universe *universe, struct option_state *options, struct option_cache *oc, isc_boolean_t appendp)
Definition options.c:3869
int get_option_int(int *result, struct universe *universe, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct option_state *options, struct binding_scope **scope, unsigned code, const char *file, int line)
Definition options.c:2358
int store_options6(char *buf, int buflen, struct option_state *opt_state, struct packet *packet, const int *required_opts, struct data_string *oro)
Definition options.c:1048
void also_save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
Definition options.c:2829
int fqdn_option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *universe)
Definition options.c:3417
int store_option(struct data_string *result, struct universe *universe, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc)
Definition options.c:3091
int add_option(struct option_state *options, unsigned int option_num, void *data, unsigned int data_len)
Definition options.c:4480
int fqdn6_universe_decode(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *u)
Definition options.c:3690
int fqdn6_option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct universe *universe)
Definition options.c:3591
int packet6_len_okay(const char *packet, int len)
Definition options.c:4135
void build_server_oro(struct data_string *server_oro, struct option_state *options, const char *file, int line)
Definition options.c:2753
int parse_option_buffer(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *universe)
Definition options.c:119
int cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, struct lease *lease, struct client_state *client_state, int mms, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, int overload_avail, int terminate, int bootpp, struct data_string *prl, const char *vuname)
Definition options.c:538
int validate_packet(struct packet *packet)
Definition options.c:4538
void save_fqdn6_option(struct universe *universe, struct option_state *options, struct option_cache *oc, isc_boolean_t appendp)
Definition options.c:3545
void parse_vendor_option(struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope)
Parse a vendor option (option 43)
Definition options.c:4618
int format_min_length(char *format, struct option_cache *oc) const
Definition options.c:1692
void delete_linked_option(struct universe *universe, struct option_state *options, int code)
Definition options.c:3949
struct enumeration * find_enumeration(const char *name, int length)
Definition parse.c:47
int32_t getLong(const unsigned char *)
u_int32_t getUShort(const unsigned char *)
void putUShort(unsigned char *, u_int32_t)
Definition convert.c:86
u_int32_t getULong(const unsigned char *)
int32_t getShort(const unsigned char *)
u_int32_t getUChar(const unsigned char *)
void putULong(unsigned char *, u_int32_t)
Definition convert.c:70
void trace_inpacket_stash(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
isc_boolean_t
Definition data.h:150
#define ISC_TRUE
Definition data.h:153
#define ISC_FALSE
Definition data.h:152
void bootp(struct packet *packet)
Definition dhclient.c:2256
void dhcp(struct packet *packet)
Definition dhclient.c:2289
#define DHCPV6_RELAY_REPL
Definition dhcp6.h:152
#define DHCPV6_RELAY_FORW
Definition dhcp6.h:151
#define DHCPV6_DHCPV4_QUERY
Definition dhcp6.h:159
#define DHCPV6_DHCPV4_RESPONSE
Definition dhcp6.h:160
#define DHO_DHCP_MESSAGE
Definition dhcp.h:145
#define DHCPREQUEST
Definition dhcp.h:172
#define DHO_DHCP_MAX_MESSAGE_SIZE
Definition dhcp.h:146
#define DHO_VENDOR_ENCAPSULATED_OPTIONS
Definition dhcp.h:132
#define FQDN_FQDN
Definition dhcp.h:200
#define DHCPNAK
Definition dhcp.h:175
#define DHCP_SNAME_LEN
Definition dhcp.h:34
#define FQDN_RCODE1
Definition dhcp.h:196
#define DHCPACK
Definition dhcp.h:174
#define DHCP_FILE_LEN
Definition dhcp.h:35
#define DHO_SUBNET_SELECTION
Definition dhcp.h:161
#define DHO_DHCP_AGENT_OPTIONS
Definition dhcp.h:155
#define DHO_PAD
Definition dhcp.h:89
#define DHO_HOST_NAME
Definition dhcp.h:101
#define FQDN_SERVER_UPDATE
Definition dhcp.h:194
#define FQDN_SUBOPTION_COUNT
Definition dhcp.h:201
#define DHCP_FIXED_NON_UDP
Definition dhcp.h:36
#define DHO_DHCP_CLIENT_IDENTIFIER
Definition dhcp.h:150
#define FQDN_NO_CLIENT_UPDATE
Definition dhcp.h:193
#define DHO_ASSOCIATED_IP
Definition dhcp.h:158
#define DHO_PXE_CLIENT_ID
Definition dhcp.h:159
#define DHO_DHCP_MESSAGE_TYPE
Definition dhcp.h:142
#define DHCPDISCOVER
Definition dhcp.h:170
#define DHCP_OPTIONS_COOKIE
Definition dhcp.h:85
#define FQDN_ENCODED
Definition dhcp.h:195
#define DHO_CLASSLESS_STATIC_ROUTES
Definition dhcp.h:163
#define DHCP_MTU_MIN
Definition dhcp.h:42
#define DHO_END
Definition dhcp.h:167
#define DHO_DHCP_RENEWAL_TIME
Definition dhcp.h:147
#define DHCPOFFER
Definition dhcp.h:171
#define FQDN_HOSTNAME
Definition dhcp.h:198
#define DHCP_MIN_OPTION_LEN
Definition dhcp.h:45
#define DHO_DOMAIN_NAME_SERVERS
Definition dhcp.h:95
#define DHO_DHCP_REBINDING_TIME
Definition dhcp.h:148
#define DHO_DHCP_OPTION_OVERLOAD
Definition dhcp.h:141
#define DHO_DHCP_SERVER_IDENTIFIER
Definition dhcp.h:143
#define DHO_ROUTERS
Definition dhcp.h:92
#define FQDN_RCODE2
Definition dhcp.h:197
#define DHO_FQDN
Definition dhcp.h:154
#define DHO_DHCP_REQUESTED_ADDRESS
Definition dhcp.h:139
#define DHO_DHCP_LEASE_TIME
Definition dhcp.h:140
#define DHO_SUBNET_MASK
Definition dhcp.h:90
#define DHCP_FIXED_LEN
Definition dhcp.h:37
#define DHCP_MAX_OPTION_LEN
Definition dhcp.h:44
#define DHCP_MTU_MAX
Definition dhcp.h:41
#define FQDN_DOMAINNAME
Definition dhcp.h:199
void do_packet6(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
#define OPTION_HAD_NULLS
Definition dhcpd.h:392
#define OPTION_HASH_SIZE
Definition dhcpd.h:223
#define compute_option_hash(x)
Definition dhcpd.h:228
struct universe dhcp_universe
const char int line
Definition dhcpd.h:3802
void dhcpv6(struct packet *)
void cleanup(void)
const char * file
Definition dhcpd.h:3802
const char * piaddr(const struct iaddr addr)
Definition inet.c:579
const char * pdestdesc(const struct iaddr addr)
Definition inet.c:557
statement_op
Definition keama.h:163
@ supersede_option_statement
Definition keama.h:170
@ if_statement
Definition keama.h:165
@ eval_statement
Definition keama.h:167
@ default_option_statement
Definition keama.h:169
@ prepend_option_statement
Definition keama.h:172
@ send_option_statement
Definition keama.h:173
@ append_option_statement
Definition keama.h:171
@ break_statement
Definition keama.h:168
@ add_statement
Definition keama.h:166
#define NS_MAXCDNAME
Definition nameser.h:75
int MRns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
Definition ns_name.c:93
int MRns_name_len(const u_char *eom, const u_char *src)
Definition ns_name.c:57
int MRns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, u_char *dst, size_t dstsiz)
Definition ns_name.c:327
#define MDL
Definition omapip.h:567
const char int
Definition omapip.h:442
#define dmalloc_reuse(x, y, l, z)
Definition omapip.h:565
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
void dfree(void *, const char *, int)
Definition alloc.c:145
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
struct _pair * cdr
Definition tree.h:32
caddr_t car
Definition tree.h:31
Definition tree.h:60
unsigned char data[1]
Definition tree.h:62
struct buffer * buffer
Definition tree.h:77
const unsigned char * data
Definition tree.h:78
int terminated
Definition tree.h:80
unsigned len
Definition tree.h:79
char file[DHCP_FILE_LEN]
Definition dhcp.h:61
unsigned char options[DHCP_MAX_OPTION_LEN]
Definition dhcp.h:62
u_int8_t hlen
Definition dhcp.h:50
char sname[DHCP_SNAME_LEN]
Definition dhcp.h:60
unsigned char msg_type
Definition dhcp6.h:252
unsigned char flags[3]
Definition dhcp6.h:253
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
Definition dhcp6.h:254
unsigned char transaction_id[3]
Definition dhcp6.h:229
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
Definition dhcp6.h:230
unsigned char msg_type
Definition dhcp6.h:228
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
Definition dhcp6.h:244
unsigned char link_address[16]
Definition dhcp6.h:242
unsigned char hop_count
Definition dhcp6.h:241
unsigned char msg_type
Definition dhcp6.h:240
unsigned char peer_address[16]
Definition dhcp6.h:243
struct enumeration_value * values
Definition tree.h:49
unsigned width
Definition tree.h:48
const char * name
Definition tree.h:47
enum expr_op op
Definition tree.h:199
int refcnt
Definition tree.h:198
Definition inet.h:31
unsigned char iabuf[16]
Definition inet.h:33
unsigned len
Definition inet.h:32
Definition dhcpd.h:560
struct data_string data
Definition dhcpd.h:390
struct option * option
Definition dhcpd.h:389
struct option_cache * next
Definition dhcpd.h:387
u_int32_t flags
Definition dhcpd.h:393
int refcnt
Definition dhcpd.h:386
struct expression * expression
Definition dhcpd.h:388
int universe_count
Definition dhcpd.h:398
void * universes[1]
Definition dhcpd.h:401
int site_code_min
Definition dhcpd.h:400
int site_universe
Definition dhcpd.h:399
Definition tree.h:345
const char * format
Definition tree.h:347
unsigned code
Definition tree.h:349
int refcnt
Definition tree.h:350
struct universe * universe
Definition tree.h:348
const char * name
Definition tree.h:346
struct hardware * haddr
Definition dhcpd.h:435
struct in6_addr dhcpv6_link_address
Definition dhcpd.h:418
int client_port
Definition dhcpd.h:431
struct dhcp_packet * raw
Definition dhcpd.h:406
unsigned char dhcp4o6_flags[3]
Definition dhcpd.h:425
unsigned char dhcpv6_msg_type
Definition dhcpd.h:411
int sv_echo_client_id
Definition dhcpd.h:474
isc_boolean_t unicast
Definition dhcpd.h:470
unsigned char dhcpv6_hop_count
Definition dhcpd.h:417
struct interface_info * interface
Definition dhcpd.h:433
struct in6_addr dhcpv6_peer_address
Definition dhcpd.h:419
struct option_state * options
Definition dhcpd.h:449
unsigned packet_length
Definition dhcpd.h:408
int options_valid
Definition dhcpd.h:430
unsigned char dhcpv6_transaction_id[3]
Definition dhcpd.h:414
int packet_type
Definition dhcpd.h:409
struct iaddr client_addr
Definition dhcpd.h:432
int(* decode)(struct option_state *, const unsigned char *, unsigned, struct universe *)
Definition tree.h:323
void(* store_length)(unsigned char *, u_int32_t)
Definition tree.h:333
int tag_size
Definition tree.h:334
void(* save_func)(struct universe *, struct option_state *, struct option_cache *, isc_boolean_t)
Definition tree.h:306
int(* encapsulate)(struct data_string *, struct packet *, struct lease *, struct client_state *, struct option_state *, struct option_state *, struct binding_scope **, struct universe *)
Definition tree.h:325
void(* store_tag)(unsigned char *, u_int32_t)
Definition tree.h:331
int index
Definition tree.h:339
int concat_duplicates
Definition tree.h:342
option_code_hash_t * code_hash
Definition tree.h:337
u_int32_t(* get_tag)(const unsigned char *)
Definition tree.h:330
u_int32_t(* get_length)(const unsigned char *)
Definition tree.h:332
struct option * enc_opt
Definition tree.h:338
int length_size
Definition tree.h:334
const char * name
Definition tree.h:302
unsigned end
Definition tree.h:335
struct option_cache *(* lookup_func)(struct universe *, struct option_state *, unsigned)
Definition tree.h:303
char * buf
Definition options.c:884
int bufpos
Definition options.c:886
int buflen
Definition options.c:885
struct universe fqdn_universe
Definition tables.c:318
struct universe nwip_universe
Definition tables.c:290
char * default_option_format
Definition tables.c:988
struct universe vsio_universe
Definition tables.c:701
int universe_count
Definition tables.c:976
int option_reference(struct option **dest, struct option *src, const char *file, int line)
Definition tables.c:992
int option_dereference(struct option **dest, const char *file, int line)
Definition tables.c:1014
universe_hash_t * universe_hash
Definition tables.c:974
struct universe dhcpv6_universe
Definition tables.c:351
struct universe ** universes
Definition tables.c:975
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2699
int make_const_data(struct expression **expr, const unsigned char *data, unsigned len, int terminated, int allocate, const char *file, int line)
Definition tree.c:219
void expression_dereference(struct expression **eptr, const char *file, int line)
Definition tree.c:2813
struct binding_scope * global_scope
Definition tree.c:38
pair cons(caddr_t car, pair cdr)
Definition tree.c:137
int make_concat(struct expression **expr, struct expression *left, struct expression *right)
Definition tree.c:268
struct _pair * pair
@ expr_concat_dclist
Definition tree.h:194
@ expr_const_data
Definition tree.h:146
Definition data.h:205