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