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