xref: /netbsd/external/mpl/dhcp/dist/common/options.c (revision 8272f735)
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