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