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