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