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