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