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