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