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