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