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