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