ISC DHCP  4.3.5
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-2016 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  * ns_name_ntop().
2092  */
2093  if (emit_quotes) {
2094  nbp = nbuff;
2095  pretty_domain(&op, endbuf-1,
2096  &nbp, nend);
2097  } else {
2098  /* ns_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  */
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 
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
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
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 
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 ns_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, so we go ahead
3641  * and allocate a bigger buffer to accommodate them. But the
3642  * 'length' we got (because it is a DNS encoded string) is
3643  * one longer than we need...so we only add two extra octets.
3644  */
3645  if (!buffer_allocate(&bp, length + 2, MDL)) {
3646  log_error("No memory for dhcp6.fqdn option buffer.");
3647  return 0;
3648  }
3649 
3650  /* The v6 FQDN is always 'encoded' per DNS. */
3651  bp->data[0] = 1;
3652  if (!save_option_buffer(&fqdn_universe, options, bp,
3653  bp->data, 1, FQDN_ENCODED, 0))
3654  goto error;
3655 
3656  /* XXX: We need to process 'The "N" bit'. */
3657 
3658  if (buffer[0] & 1) /* server-update. */
3659  bp->data[2] = 1;
3660  else
3661  bp->data[2] = 0;
3662 
3663  if (!save_option_buffer(&fqdn_universe, options, bp, bp->data + 2, 1,
3664  FQDN_SERVER_UPDATE, 0))
3665  goto error;
3666 
3667  if (buffer[0] & 2) /* no-client-update. */
3668  bp->data[1] = 1;
3669  else
3670  bp->data[1] = 0;
3671 
3672  if (!save_option_buffer(&fqdn_universe, options, bp, bp->data + 1, 1,
3674  goto error;
3675 
3676  /* Convert the domain name to textual representation for config. */
3677  len = MRns_name_ntop(buffer + 1, (char *)bp->data + 3, length - 1);
3678  if (len == -1) {
3679  log_error("Unable to convert dhcp6.fqdn domain name to "
3680  "printable form.");
3681  goto error;
3682  }
3683 
3684  /* Save the domain name. */
3685  if (len > 0) {
3686  unsigned char *fqdn_start = bp->data + 3;
3687 
3688  if (!save_option_buffer(&fqdn_universe, options, bp,
3689  fqdn_start, len, FQDN_FQDN, 1))
3690  goto error;
3691 
3692  first_dot = (unsigned char *)strchr((char *)fqdn_start, '.');
3693 
3694  if (first_dot != NULL) {
3695  hlen = first_dot - fqdn_start;
3696  dlen = len - hlen;
3697  } else {
3698  hlen = len;
3699  dlen = 0;
3700  }
3701 
3702  if (!save_option_buffer(&fqdn_universe, options, bp,
3703  fqdn_start, len, FQDN_FQDN, 1) ||
3704  ((hlen > 0) &&
3705  !save_option_buffer(&fqdn_universe, options, bp,
3706  fqdn_start, hlen,
3707  FQDN_HOSTNAME, 0)) ||
3708  ((dlen > 0) &&
3709  !save_option_buffer(&fqdn_universe, options, bp,
3710  first_dot, dlen, FQDN_DOMAINNAME, 0)))
3711  goto error;
3712  }
3713 
3714  buffer_dereference(&bp, MDL);
3715  return 1;
3716 
3717  error:
3718  buffer_dereference(&bp, MDL);
3719  return 0;
3720 }
3721 
3722 void option_space_foreach (struct packet *packet, struct lease *lease,
3723  struct client_state *client_state,
3724  struct option_state *in_options,
3725  struct option_state *cfg_options,
3726  struct binding_scope **scope,
3727  struct universe *u, void *stuff,
3728  void (*func) (struct option_cache *,
3729  struct packet *,
3730  struct lease *, struct client_state *,
3731  struct option_state *,
3732  struct option_state *,
3733  struct binding_scope **,
3734  struct universe *, void *))
3735 {
3736  if (u -> foreach)
3737  (*u -> foreach) (packet, lease, client_state, in_options,
3738  cfg_options, scope, u, stuff, func);
3739 }
3740 
3741 void suboption_foreach (struct packet *packet, struct lease *lease,
3742  struct client_state *client_state,
3743  struct option_state *in_options,
3744  struct option_state *cfg_options,
3745  struct binding_scope **scope,
3746  struct universe *u, void *stuff,
3747  void (*func) (struct option_cache *,
3748  struct packet *,
3749  struct lease *, struct client_state *,
3750  struct option_state *,
3751  struct option_state *,
3752  struct binding_scope **,
3753  struct universe *, void *),
3754  struct option_cache *oc,
3755  const char *vsname)
3756 {
3757  struct universe *universe = find_option_universe (oc -> option,
3758  vsname);
3759  if (universe -> foreach)
3760  (*universe -> foreach) (packet, lease, client_state,
3761  in_options, cfg_options,
3762  scope, universe, stuff, func);
3763 }
3764 
3765 void hashed_option_space_foreach (struct packet *packet, struct lease *lease,
3766  struct client_state *client_state,
3767  struct option_state *in_options,
3768  struct option_state *cfg_options,
3769  struct binding_scope **scope,
3770  struct universe *u, void *stuff,
3771  void (*func) (struct option_cache *,
3772  struct packet *,
3773  struct lease *,
3774  struct client_state *,
3775  struct option_state *,
3776  struct option_state *,
3777  struct binding_scope **,
3778  struct universe *, void *))
3779 {
3780  pair *hash;
3781  int i;
3782  struct option_cache *oc;
3783 
3784  if (cfg_options -> universe_count <= u -> index)
3785  return;
3786 
3787  hash = cfg_options -> universes [u -> index];
3788  if (!hash)
3789  return;
3790  for (i = 0; i < OPTION_HASH_SIZE; i++) {
3791  pair p;
3792  /* XXX save _all_ options! XXX */
3793  for (p = hash [i]; p; p = p -> cdr) {
3794  oc = (struct option_cache *)p -> car;
3795  (*func) (oc, packet, lease, client_state,
3796  in_options, cfg_options, scope, u, stuff);
3797  }
3798  }
3799 }
3800 
3801 void
3802 save_linked_option(struct universe *universe, struct option_state *options,
3803  struct option_cache *oc, isc_boolean_t appendp)
3804 {
3805  pair *tail;
3806  struct option_chain_head *head;
3807  struct option_cache **ocloc;
3808 
3809  if (universe -> index >= options -> universe_count)
3810  return;
3811  head = ((struct option_chain_head *)
3812  options -> universes [universe -> index]);
3813  if (!head) {
3815  &options -> universes
3816  [universe -> index]), MDL))
3817  return;
3818  head = ((struct option_chain_head *)
3819  options -> universes [universe -> index]);
3820  }
3821 
3822  /* Find the tail of the list. */
3823  for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
3824  ocloc = (struct option_cache **)&(*tail)->car;
3825 
3826  if (oc->option->code == (*ocloc)->option->code) {
3827  if (appendp) {
3828  do {
3829  ocloc = &(*ocloc)->next;
3830  } while (*ocloc != NULL);
3831  } else {
3832  option_cache_dereference(ocloc, MDL);
3833  }
3834  option_cache_reference(ocloc, oc, MDL);
3835  return;
3836  }
3837  }
3838 
3839  *tail = cons (0, 0);
3840  if (*tail) {
3842  (&(*tail) -> car), oc, MDL);
3843  }
3844 }
3845 
3846 int linked_option_space_encapsulate (result, packet, lease, client_state,
3847  in_options, cfg_options, scope, universe)
3848  struct data_string *result;
3849  struct packet *packet;
3850  struct lease *lease;
3851  struct client_state *client_state;
3852  struct option_state *in_options;
3853  struct option_state *cfg_options;
3854  struct binding_scope **scope;
3855  struct universe *universe;
3856 {
3857  int status = 0;
3858  pair oc;
3859  struct option_chain_head *head;
3860 
3861  if (universe -> index >= cfg_options -> universe_count)
3862  return status;
3863  head = ((struct option_chain_head *)
3864  cfg_options -> universes [universe -> index]);
3865  if (!head)
3866  return status;
3867 
3868  for (oc = head -> first; oc; oc = oc -> cdr) {
3869  if (store_option (result, universe, packet,
3870  lease, client_state, in_options, cfg_options,
3871  scope, (struct option_cache *)(oc -> car)))
3872  status = 1;
3873  }
3874 
3875  if (search_subencapsulation(result, packet, lease, client_state,
3876  in_options, cfg_options, scope, universe))
3877  status = 1;
3878 
3879  return status;
3880 }
3881 
3882 void delete_linked_option (universe, options, code)
3883  struct universe *universe;
3884  struct option_state *options;
3885  int code;
3886 {
3887  pair *tail, tmp = (pair)0;
3888  struct option_chain_head *head;
3889 
3890  if (universe -> index >= options -> universe_count)
3891  return;
3892  head = ((struct option_chain_head *)
3893  options -> universes [universe -> index]);
3894  if (!head)
3895  return;
3896 
3897  for (tail = &head -> first; *tail; tail = &((*tail) -> cdr)) {
3898  if (code ==
3899  ((struct option_cache *)(*tail) -> car) -> option -> code)
3900  {
3901  tmp = (*tail) -> cdr;
3903  (&(*tail) -> car), MDL);
3904  dfree (*tail, MDL);
3905  (*tail) = tmp;
3906  break;
3907  }
3908  }
3909 }
3910 
3911 struct option_cache *lookup_linked_option (universe, options, code)
3912  struct universe *universe;
3913  struct option_state *options;
3914  unsigned code;
3915 {
3916  pair oc;
3917  struct option_chain_head *head;
3918 
3919  if (universe -> index >= options -> universe_count)
3920  return 0;
3921  head = ((struct option_chain_head *)
3922  options -> universes [universe -> index]);
3923  if (!head)
3924  return 0;
3925 
3926  for (oc = head -> first; oc; oc = oc -> cdr) {
3927  if (code ==
3928  ((struct option_cache *)(oc -> car)) -> option -> code) {
3929  return (struct option_cache *)(oc -> car);
3930  }
3931  }
3932 
3933  return (struct option_cache *)0;
3934 }
3935 
3937  struct universe *universe;
3938  struct option_state *state;
3939  const char *file;
3940  int line;
3941 {
3943  ((struct option_chain_head **)
3944  (&state -> universes [universe -> index]), MDL));
3945 }
3946 
3947 void linked_option_space_foreach (struct packet *packet, struct lease *lease,
3948  struct client_state *client_state,
3949  struct option_state *in_options,
3950  struct option_state *cfg_options,
3951  struct binding_scope **scope,
3952  struct universe *u, void *stuff,
3953  void (*func) (struct option_cache *,
3954  struct packet *,
3955  struct lease *,
3956  struct client_state *,
3957  struct option_state *,
3958  struct option_state *,
3959  struct binding_scope **,
3960  struct universe *, void *))
3961 {
3962  pair car;
3963  struct option_chain_head *head;
3964 
3965  if (u -> index >= cfg_options -> universe_count)
3966  return;
3967  head = ((struct option_chain_head *)
3968  cfg_options -> universes [u -> index]);
3969  if (!head)
3970  return;
3971  for (car = head -> first; car; car = car -> cdr) {
3972  (*func) ((struct option_cache *)(car -> car),
3973  packet, lease, client_state,
3974  in_options, cfg_options, scope, u, stuff);
3975  }
3976 }
3977 
3978 void do_packet (interface, packet, len, from_port, from, hfrom)
3979  struct interface_info *interface;
3980  struct dhcp_packet *packet;
3981  unsigned len;
3982  unsigned int from_port;
3983  struct iaddr from;
3984  struct hardware *hfrom;
3985 {
3986  struct option_cache *op;
3987  struct packet *decoded_packet;
3988 #if defined (DEBUG_MEMORY_LEAKAGE)
3989  unsigned long previous_outstanding = dmalloc_outstanding;
3990 #endif
3991 
3992 #if defined (TRACING)
3993  trace_inpacket_stash(interface, packet, len, from_port, from, hfrom);
3994 #endif
3995 
3996  decoded_packet = NULL;
3997  if (!packet_allocate(&decoded_packet, MDL)) {
3998  log_error("do_packet: no memory for incoming packet!");
3999  return;
4000  }
4001  decoded_packet->raw = packet;
4002  decoded_packet->packet_length = len;
4003  decoded_packet->client_port = from_port;
4004  decoded_packet->client_addr = from;
4005  interface_reference(&decoded_packet->interface, interface, MDL);
4006  decoded_packet->haddr = hfrom;
4007 
4008  if (packet->hlen > sizeof packet->chaddr) {
4009  packet_dereference(&decoded_packet, MDL);
4010  log_info("Discarding packet with bogus hlen.");
4011  return;
4012  }
4013 
4014  /* Allocate packet->options now so it is non-null for all packets */
4015  decoded_packet->options_valid = 0;
4016  if (!option_state_allocate (&decoded_packet->options, MDL)) {
4017  packet_dereference(&decoded_packet, MDL);
4018  return;
4019  }
4020 
4021  /* If there's an option buffer, try to parse it. */
4022  if (decoded_packet->packet_length >= DHCP_FIXED_NON_UDP + 4) {
4023  if (!parse_options(decoded_packet)) {
4024  packet_dereference (&decoded_packet, MDL);
4025  return;
4026  }
4027 
4028  if (decoded_packet->options_valid &&
4030  decoded_packet->options,
4032  struct data_string dp;
4033  memset(&dp, 0, sizeof dp);
4034  evaluate_option_cache(&dp, decoded_packet, NULL, NULL,
4035  decoded_packet->options, NULL,
4036  NULL, op, MDL);
4037  if (dp.len > 0)
4038  decoded_packet->packet_type = dp.data[0];
4039  else
4040  decoded_packet->packet_type = 0;
4041  data_string_forget(&dp, MDL);
4042  }
4043  }
4044 
4045  if (validate_packet(decoded_packet) != 0) {
4046  if (decoded_packet->packet_type)
4047  dhcp(decoded_packet);
4048  else
4049  bootp(decoded_packet);
4050  }
4051 
4052  /* If the caller kept the packet, they'll have upped the refcnt. */
4053  packet_dereference(&decoded_packet, MDL);
4054 
4055 #if defined (DEBUG_MEMORY_LEAKAGE)
4056  log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4057  dmalloc_generation,
4058  dmalloc_outstanding - previous_outstanding,
4059  dmalloc_outstanding, dmalloc_longterm);
4060  dmalloc_dump_outstanding();
4061 #endif
4062 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4063  dump_rc_history(0);
4064 #endif
4065 }
4066 
4067 int
4068 packet6_len_okay(const char *packet, int len) {
4069  if (len < 1) {
4070  return 0;
4071  }
4072  if ((packet[0] == DHCPV6_RELAY_FORW) ||
4073  (packet[0] == DHCPV6_RELAY_REPL)) {
4074  if (len >= offsetof(struct dhcpv6_relay_packet, options)) {
4075  return 1;
4076  } else {
4077  return 0;
4078  }
4079  } else {
4080  if (len >= offsetof(struct dhcpv6_packet, options)) {
4081  return 1;
4082  } else {
4083  return 0;
4084  }
4085  }
4086 }
4087 
4088 #ifdef DHCPv6
4089 void
4090 do_packet6(struct interface_info *interface, const char *packet,
4091  int len, int from_port, const struct iaddr *from,
4092  isc_boolean_t was_unicast) {
4093  unsigned char msg_type;
4094  const struct dhcpv6_packet *msg;
4095  const struct dhcpv6_relay_packet *relay;
4096 #ifdef DHCP4o6
4097  const struct dhcpv4_over_dhcpv6_packet *msg46;
4098 #endif
4099  struct packet *decoded_packet;
4100 #if defined (DEBUG_MEMORY_LEAKAGE)
4101  unsigned long previous_outstanding = dmalloc_outstanding;
4102 #endif
4103 
4104  if (!packet6_len_okay(packet, len)) {
4105  log_info("do_packet6: "
4106  "short packet from %s port %d, len %d, dropped",
4107  piaddr(*from), from_port, len);
4108  return;
4109  }
4110 
4111  decoded_packet = NULL;
4112  if (!packet_allocate(&decoded_packet, MDL)) {
4113  log_error("do_packet6: no memory for incoming packet.");
4114  return;
4115  }
4116 
4117  if (!option_state_allocate(&decoded_packet->options, MDL)) {
4118  log_error("do_packet6: no memory for options.");
4119  packet_dereference(&decoded_packet, MDL);
4120  return;
4121  }
4122 
4123  /* IPv4 information, already set to 0 */
4124  /* decoded_packet->packet_type = 0; */
4125  /* memset(&decoded_packet->haddr, 0, sizeof(decoded_packet->haddr)); */
4126  /* decoded_packet->circuit_id = NULL; */
4127  /* decoded_packet->circuit_id_len = 0; */
4128  /* decoded_packet->remote_id = NULL; */
4129  /* decoded_packet->remote_id_len = 0; */
4130  decoded_packet->raw = (struct dhcp_packet *)packet;
4131  decoded_packet->packet_length = (unsigned)len;
4132  decoded_packet->client_port = from_port;
4133  decoded_packet->client_addr = *from;
4134  interface_reference(&decoded_packet->interface, interface, MDL);
4135 
4136  decoded_packet->unicast = was_unicast;
4137 
4138  msg_type = packet[0];
4139  if ((msg_type == DHCPV6_RELAY_FORW) ||
4140  (msg_type == DHCPV6_RELAY_REPL)) {
4141  int relaylen = (int)(offsetof(struct dhcpv6_relay_packet, options));
4142  relay = (const struct dhcpv6_relay_packet *)packet;
4143  decoded_packet->dhcpv6_msg_type = relay->msg_type;
4144 
4145  /* relay-specific data */
4146  decoded_packet->dhcpv6_hop_count = relay->hop_count;
4147  memcpy(&decoded_packet->dhcpv6_link_address,
4148  relay->link_address, sizeof(relay->link_address));
4149  memcpy(&decoded_packet->dhcpv6_peer_address,
4150  relay->peer_address, sizeof(relay->peer_address));
4151 
4152  if (!parse_option_buffer(decoded_packet->options,
4153  relay->options, len - relaylen,
4154  &dhcpv6_universe)) {
4155  /* no logging here, as parse_option_buffer() logs all
4156  cases where it fails */
4157  packet_dereference(&decoded_packet, MDL);
4158  return;
4159  }
4160 #ifdef DHCP4o6
4161  } else if ((msg_type == DHCPV6_DHCPV4_QUERY) ||
4162  (msg_type == DHCPV6_DHCPV4_RESPONSE)) {
4163  int msglen =
4164  (int)(offsetof(struct dhcpv4_over_dhcpv6_packet, options));
4165  msg46 = (struct dhcpv4_over_dhcpv6_packet *)packet;
4166  decoded_packet->dhcpv6_msg_type = msg46->msg_type;
4167 
4168  /* message-specific data */
4169  memcpy(decoded_packet->dhcp4o6_flags,
4170  msg46->flags,
4171  sizeof(decoded_packet->dhcp4o6_flags));
4172 
4173  if (!parse_option_buffer(decoded_packet->options,
4174  msg46->options, len - msglen,
4175  &dhcpv6_universe)) {
4176  /* no logging here, as parse_option_buffer() logs all
4177  cases where it fails */
4178  packet_dereference(&decoded_packet, MDL);
4179  return;
4180  }
4181 #endif
4182  } else {
4183  int msglen = (int)(offsetof(struct dhcpv6_packet, options));
4184  msg = (const struct dhcpv6_packet *)packet;
4185  decoded_packet->dhcpv6_msg_type = msg->msg_type;
4186 
4187  /* message-specific data */
4188  memcpy(decoded_packet->dhcpv6_transaction_id,
4189  msg->transaction_id,
4190  sizeof(decoded_packet->dhcpv6_transaction_id));
4191 
4192  if (!parse_option_buffer(decoded_packet->options,
4193  msg->options, len - msglen,
4194  &dhcpv6_universe)) {
4195  /* no logging here, as parse_option_buffer() logs all
4196  cases where it fails */
4197  packet_dereference(&decoded_packet, MDL);
4198  return;
4199  }
4200  }
4201 
4202  dhcpv6(decoded_packet);
4203 
4204  packet_dereference(&decoded_packet, MDL);
4205 
4206 #if defined (DEBUG_MEMORY_LEAKAGE)
4207  log_info("generation %ld: %ld new, %ld outstanding, %ld long-term",
4208  dmalloc_generation,
4209  dmalloc_outstanding - previous_outstanding,
4210  dmalloc_outstanding, dmalloc_longterm);
4211  dmalloc_dump_outstanding();
4212 #endif
4213 #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
4214  dump_rc_history(0);
4215 #endif
4216 }
4217 #endif /* DHCPv6 */
4218 
4219 int
4220 pretty_escape(char **dst, char *dend, const unsigned char **src,
4221  const unsigned char *send)
4222 {
4223  int count = 0;
4224 
4225  /* If there aren't as many bytes left as there are in the source
4226  * buffer, don't even bother entering the loop.
4227  */
4228  if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4229  *dst == NULL || *src == NULL || (*dst >= dend) || (*src > send) ||
4230  ((send - *src) > (dend - *dst)))
4231  return -1;
4232 
4233  for ( ; *src < send ; (*src)++) {
4234  if (!isascii (**src) || !isprint (**src)) {
4235  /* Skip trailing NUL. */
4236  if ((*src + 1) != send || **src != '\0') {
4237  if (*dst + 4 > dend)
4238  return -1;
4239 
4240  sprintf(*dst, "\\%03o",
4241  **src);
4242  (*dst) += 4;
4243  count += 4;
4244  }
4245  } else if (**src == '"' || **src == '\'' || **src == '$' ||
4246  **src == '`' || **src == '\\' || **src == '|' ||
4247  **src == '&') {
4248  if (*dst + 2 > dend)
4249  return -1;
4250 
4251  **dst = '\\';
4252  (*dst)++;
4253  **dst = **src;
4254  (*dst)++;
4255  count += 2;
4256  } else {
4257  if (*dst + 1 > dend)
4258  return -1;
4259 
4260  **dst = **src;
4261  (*dst)++;
4262  count++;
4263  }
4264  }
4265 
4266  return count;
4267 }
4268 
4269 static int
4270 pretty_text(char **dst, char *dend, const unsigned char **src,
4271  const unsigned char *send, int emit_quotes)
4272 {
4273  int count;
4274 
4275  if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4276  *dst == NULL || *src == NULL ||
4277  ((*dst + (emit_quotes ? 2 : 0)) > dend) || (*src > send))
4278  return -1;
4279 
4280  if (emit_quotes) {
4281  **dst = '"';
4282  (*dst)++;
4283  }
4284 
4285  /* dend-1 leaves 1 byte for the closing quote. */
4286  count = pretty_escape(dst, dend - (emit_quotes ? 1 : 0), src, send);
4287 
4288  if (count == -1)
4289  return -1;
4290 
4291  if (emit_quotes && (*dst < dend)) {
4292  **dst = '"';
4293  (*dst)++;
4294 
4295  /* Includes quote prior to pretty_escape(); */
4296  count += 2;
4297  }
4298 
4299  return count;
4300 }
4301 
4302 static int
4303 pretty_domain(char **dst, char *dend, const unsigned char **src,
4304  const unsigned char *send)
4305 {
4306  const unsigned char *tend;
4307  int count = 2;
4308  int tsiz, status;
4309 
4310  if (dst == NULL || dend == NULL || src == NULL || send == NULL ||
4311  *dst == NULL || *src == NULL ||
4312  ((*dst + 2) > dend) || (*src >= send))
4313  return -1;
4314 
4315  **dst = '"';
4316  (*dst)++;
4317 
4318  do {
4319  /* Continue loop until end of src buffer. */
4320  if (*src >= send)
4321  break;
4322 
4323  /* Consume tag size. */
4324  tsiz = **src;
4325  (*src)++;
4326 
4327  /* At root, finis. */
4328  if (tsiz == 0)
4329  break;
4330 
4331  tend = (*src) + tsiz;
4332 
4333  /* If the tag exceeds the source buffer, it's illegal.
4334  * This should also trap compression pointers (which should
4335  * not be in these buffers).
4336  */
4337  if (tend > send)
4338  return -1;
4339 
4340  /* dend-2 leaves room for a trailing dot and quote. */
4341  status = pretty_escape(dst, dend-2, src, tend);
4342 
4343  if ((status == -1) || ((*dst + 2) > dend))
4344  return -1;
4345 
4346  **dst = '.';
4347  (*dst)++;
4348  count += status + 1;
4349  }
4350  while(1);
4351 
4352  **dst = '"';
4353  (*dst)++;
4354 
4355  return count;
4356 }
4357 
4358 /*
4359  * Add the option identified with the option number and data to the
4360  * options state.
4361  */
4362 int
4364  unsigned int option_num,
4365  void *data,
4366  unsigned int data_len)
4367 {
4368  struct option_cache *oc;
4369  struct option *option;
4370 
4371  /* INSIST(options != NULL); */
4372  /* INSIST(data != NULL); */
4373 
4374  option = NULL;
4375  if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
4376  &option_num, 0, MDL)) {
4377  log_error("Attempting to add unknown option %d.", option_num);
4378  return 0;
4379  }
4380 
4381  oc = NULL;
4382  if (!option_cache_allocate(&oc, MDL)) {
4383  log_error("No memory for option cache adding %s (option %d).",
4384  option->name, option_num);
4385  return 0;
4386  }
4387 
4388  if (!make_const_data(&oc->expression,
4389  data,
4390  data_len,
4391  0,
4392  0,
4393  MDL)) {
4394  log_error("No memory for constant data adding %s (option %d).",
4395  option->name, option_num);
4397  return 0;
4398  }
4399 
4400  option_reference(&(oc->option), option, MDL);
4401  save_option(&dhcp_universe, options, oc);
4403 
4404  return 1;
4405 }
4406 
4414 int validate_packet(struct packet *packet)
4415 {
4416  struct option_cache *oc = NULL;
4417 
4418  oc = lookup_option (&dhcp_universe, packet->options,
4420  if (oc) {
4421  /* Let's check if client-identifier is sane */
4422  if (oc->data.len == 0) {
4423  log_debug("Dropped DHCPv4 packet with zero-length client-id");
4424  return (0);
4425 
4426  } else if (oc->data.len == 1) {
4427  /*
4428  * RFC2132, section 9.14 states that minimum length of client-id
4429  * is 2. We will allow single-character client-ids for now (for
4430  * backwards compatibility), but warn the user that support for
4431  * this is against the standard.
4432  */
4433  log_debug("Accepted DHCPv4 packet with one-character client-id - "
4434  "a future version of ISC DHCP will reject this");
4435  }
4436  } else {
4437  oc = lookup_option (&dhcp_universe, packet->options,
4439  if (oc) {
4440  /* Let's check if pxe-client-id is sane */
4441  if ((oc->data.len < 2) ||
4442  (oc->data.data[0] == '\0' &&
4443  oc->data.len != 17)) {
4444  log_debug("Dropped DHCPv4 packet with wrong "
4445  "(len == %d) pxe-client-id", oc->data.len);
4446  return (0);
4447  }
4448  } else {
4449  /*
4450  * If hlen is 0 we don't have any identifier, we warn the user
4451  * but continue processing the packet as we can.
4452  */
4453  if (packet->raw->hlen == 0) {
4454  log_debug("Received DHCPv4 packet without client-id"
4455  " option and empty hlen field.");
4456  }
4457  }
4458  }
4459 
4460  /* @todo: Add checks for other received options */
4461 
4462  return (1);
4463 }
4494 void parse_vendor_option(packet, lease, client_state, in_options,
4495  out_options, scope)
4496  struct packet *packet;
4497  struct lease *lease;
4498  struct client_state *client_state;
4499  struct option_state *in_options;
4500  struct option_state *out_options;
4501  struct binding_scope **scope;
4502 {
4503  struct option_cache *oc = NULL;
4504  struct data_string name;
4505  struct option *option = NULL;
4506  unsigned int code = DHO_VENDOR_ENCAPSULATED_OPTIONS;
4507 
4508  /* check if we are processing a packet, if not we can return */
4509  if ((packet == NULL) || (in_options == NULL) || (out_options == NULL))
4510  return;
4511 
4512  /* Do we have any vendor option spaces? */
4513  if (vendor_cfg_option == NULL)
4514  return;
4515 
4516  /* See if the admin has set a vendor option space name */
4517  oc = lookup_option(vendor_cfg_option->universe,
4518  out_options, vendor_cfg_option->code);
4519  if (oc == NULL)
4520  return;
4521 
4522  memset(&name, 0, sizeof(name));
4523  (void) evaluate_option_cache(&name, packet, lease, client_state,
4524  in_options, out_options, scope, oc, MDL);
4525 
4526  /* No name, all done */
4527  if (name.len == 0)
4528  return;
4529 
4530  /* Get any vendor option information from the request */
4531  oc = lookup_option(&dhcp_universe, in_options, code);
4532 
4533  /* No vendor option, all done */
4534  if ((oc == NULL) || (oc->data.len == 0)) {
4535  data_string_forget(&name, MDL);
4536  return;
4537  }
4538 
4539  /* Get the proper option to pass to the parse routine */
4540  option_code_hash_lookup(&option, dhcp_universe.code_hash,
4541  &code, 0, MDL);
4542 
4543  /* Now that we have the data from the vendor option and a vendor
4544  * option space try to parse things. On success the parsed options
4545  * will be added to the in_options list for future use. A return
4546  * return of 1 indicates success, but not much we can do on error */
4547  (void) parse_encapsulated_suboptions(in_options, option,
4548  oc->data.data, oc->data.len,
4549  &dhcp_universe,
4550  (const char *)name.data);
4551 
4552  /* Lastly clean up any left overs */
4553  data_string_forget(&name, MDL);
4554  option_dereference(&option, MDL);
4555  return;
4556 }
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:3802
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:3882
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:4494
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:1987
#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:3978
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:3936
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:3947
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:3846
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:4220
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:131
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:4363
#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:4068
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:56
#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:4414
#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:3741
#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:3722
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:3765
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:2020
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:3911
#define compute_option_hash(x)
Definition: dhcpd.h:228