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