ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
dhcpleasequery.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2017 by Internet Systems Consortium, Inc. ("ISC")
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "dhcpd.h"
18 
19 /*
20  * TODO: RFC4388 specifies that the server SHOULD return the same
21  * options it would for a DHCREQUEST message, if no Parameter
22  * Request List option (option 55) is passed. We do not do that.
23  *
24  * TODO: RFC4388 specifies the creation of a "non-sensitive options"
25  * configuration list, and that these SHOULD be returned. We
26  * have no such list.
27  *
28  * TODO: RFC4388 says the server SHOULD use RFC3118, "Authentication
29  * for DHCP Messages".
30  *
31  * TODO: RFC4388 specifies that you SHOULD insure that you cannot be
32  * DoS'ed by DHCPLEASEQUERY message.
33  */
34 
35 /*
36  * If you query by hardware address or by client ID, then you may have
37  * more than one IP address for your query argument. We need to do two
38  * things:
39  *
40  * 1. Find the most recent lease.
41  * 2. Find all additional IP addresses for the query argument.
42  *
43  * We do this by looking through all of the leases associated with a
44  * given hardware address or client ID. We use the cltt (client last
45  * transaction time) of the lease, which only has a resolution of one
46  * second, so we might not actually give the very latest IP.
47  */
48 
49 static struct lease*
50 next_hw(const struct lease *lease) {
51  /* INSIST(lease != NULL); */
52  return lease->n_hw;
53 }
54 
55 static struct lease*
56 next_uid(const struct lease *lease) {
57  /* INSIST(lease != NULL); */
58  return lease->n_uid;
59 }
60 
61 void
62 get_newest_lease(struct lease **retval,
63  struct lease *lease,
64  struct lease *(*next)(const struct lease *)) {
65 
66  struct lease *p;
67  struct lease *newest;
68 
69  /* INSIST(newest != NULL); */
70  /* INSIST(next != NULL); */
71 
72  *retval = NULL;
73 
74  if (lease == NULL) {
75  return;
76  }
77 
78  newest = lease;
79  for (p=next(lease); p != NULL; p=next(p)) {
80  if (newest->binding_state == FTS_ACTIVE) {
81  if ((p->binding_state == FTS_ACTIVE) &&
82  (p->cltt > newest->cltt)) {
83  newest = p;
84  }
85  } else {
86  if (p->ends > newest->ends) {
87  newest = p;
88  }
89  }
90  }
91 
92  lease_reference(retval, newest, MDL);
93 }
94 
95 static int
96 get_associated_ips(const struct lease *lease,
97  struct lease *(*next)(const struct lease *),
98  const struct lease *newest,
99  u_int32_t *associated_ips,
100  unsigned int associated_ips_size) {
101 
102  const struct lease *p;
103  int cnt;
104 
105  /* INSIST(next != NULL); */
106  /* INSIST(associated_ips != NULL); */
107 
108  if (lease == NULL) {
109  return 0;
110  }
111 
112  cnt = 0;
113  for (p=lease; p != NULL; p=next(p)) {
114  if ((p->binding_state == FTS_ACTIVE) && (p != newest)) {
115  if (cnt < associated_ips_size) {
116  memcpy(&associated_ips[cnt],
117  p->ip_addr.iabuf,
118  sizeof(associated_ips[cnt]));
119  }
120  cnt++;
121  }
122  }
123  return cnt;
124 }
125 
126 
127 void
128 dhcpleasequery(struct packet *packet, int ms_nulltp) {
129  char msgbuf[256];
130  char dbg_info[128];
131  struct iaddr cip;
132  struct iaddr gip;
133  struct data_string uid;
134  struct hardware h;
135  struct lease *tmp_lease;
136  struct lease *lease;
137  int want_associated_ip;
138  int assoc_ip_cnt;
139  u_int32_t assoc_ips[40]; /* XXXSK: arbitrary maximum number of IPs */
140  const int nassoc_ips = sizeof(assoc_ips) / sizeof(assoc_ips[0]);
141 
142  unsigned char dhcpMsgType;
143  const char *dhcp_msg_type_name;
144  struct subnet *subnet;
145  struct group *relay_group;
146  struct option_state *options;
147  struct option_cache *oc;
148  int allow_leasequery;
149  int ignorep;
150  u_int32_t lease_duration;
151  u_int32_t time_renewal;
152  u_int32_t time_rebinding;
153  u_int32_t time_expiry;
154  u_int32_t client_last_transaction_time;
155 #if defined(RELAY_PORT)
156  u_int16_t relay_port = 0;
157 #endif
158  struct sockaddr_in to;
159  struct in_addr siaddr;
160  struct data_string prl;
161  struct data_string *prl_ptr;
162 
163  int i;
164  struct interface_info *interface;
165 
166  /* INSIST(packet != NULL); */
167 
168  /*
169  * Prepare log information.
170  */
171  snprintf(msgbuf, sizeof(msgbuf),
172  "DHCPLEASEQUERY from %s", inet_ntoa(packet->raw->giaddr));
173 
174  /*
175  * We can't reply if there is no giaddr field.
176  */
177  /*
178  * Note: this makes DHCPv4-over-DHCPv6 always fail but it should not
179  * really be a problem because it is not a specified use case
180  * (or even one that makes sense).
181  */
182  if (!packet->raw->giaddr.s_addr) {
183  log_info("%s: missing giaddr, ciaddr is %s, no reply sent",
184  msgbuf, inet_ntoa(packet->raw->ciaddr));
185  return;
186  }
187 
188  /*
189  * Initially we use the 'giaddr' subnet options scope to determine if
190  * the giaddr-identified relay agent is permitted to perform a
191  * leasequery. The subnet is not required, and may be omitted, in
192  * which case we are essentially interrogating the root options class
193  * to find a globally permit.
194  */
195  gip.len = sizeof(packet->raw->giaddr);
196  memcpy(gip.iabuf, &packet->raw->giaddr, sizeof(packet->raw->giaddr));
197 
198  subnet = NULL;
199  find_subnet(&subnet, gip, MDL);
200  if (subnet != NULL)
201  relay_group = subnet->group;
202  else
203  relay_group = root_group;
204 
205  subnet_dereference(&subnet, MDL);
206 
207  options = NULL;
208  if (!option_state_allocate(&options, MDL)) {
209  log_error("No memory for option state.");
210  log_info("%s: out of memory, no reply sent", msgbuf);
211  return;
212  }
213 
214  execute_statements_in_scope(NULL, packet, NULL, NULL, packet->options,
215  options, &global_scope, relay_group,
216  NULL, NULL);
217 
218  for (i=packet->class_count-1; i>=0; i--) {
219  execute_statements_in_scope(NULL, packet, NULL, NULL,
220  packet->options, options,
221  &global_scope,
222  packet->classes[i]->group,
223  relay_group, NULL);
224  }
225 
226  /*
227  * Because LEASEQUERY has some privacy concerns, default to deny.
228  */
229  allow_leasequery = 0;
230 
231  /*
232  * See if we are authorized to do LEASEQUERY.
233  */
235  if (oc != NULL) {
236  allow_leasequery = evaluate_boolean_option_cache(&ignorep,
237  packet, NULL, NULL, packet->options,
238  options, &global_scope, oc, MDL);
239  }
240 
241  if (!allow_leasequery) {
242  log_info("%s: LEASEQUERY not allowed, query ignored", msgbuf);
243  option_state_dereference(&options, MDL);
244  return;
245  }
246 
247 
248  /*
249  * Copy out the client IP address.
250  */
251  cip.len = sizeof(packet->raw->ciaddr);
252  memcpy(cip.iabuf, &packet->raw->ciaddr, sizeof(packet->raw->ciaddr));
253 
254  /*
255  * If the client IP address is valid (not all zero), then we
256  * are looking for information about that IP address.
257  */
258  assoc_ip_cnt = 0;
259  lease = tmp_lease = NULL;
260  if (memcmp(cip.iabuf, "\0\0\0", 4)) {
261 
262  want_associated_ip = 0;
263 
264  snprintf(dbg_info, sizeof(dbg_info), "IP %s", piaddr(cip));
266 
267 
268  } else {
269 
270  want_associated_ip = 1;
271 
272  /*
273  * If the client IP address is all zero, then we will
274  * either look up by the client identifier (if we have
275  * one), or by the MAC address.
276  */
277 
278  memset(&uid, 0, sizeof(uid));
279  i = get_option(&uid,
280  &dhcp_universe,
281  packet,
282  NULL,
283  NULL,
284  packet->options,
285  NULL,
286  packet->options,
287  &global_scope,
289  MDL);
290  if (!i)
291  i = get_option(&uid,
292  &dhcp_universe,
293  packet,
294  NULL,
295  NULL,
296  packet->options,
297  NULL,
298  packet->options,
299  &global_scope,
301  MDL);
302  if (i) {
303  snprintf(dbg_info,
304  sizeof(dbg_info),
305  "client-id %s",
306  print_hex_1(uid.len, uid.data, 60));
307 
308  find_lease_by_uid(&tmp_lease, uid.data, uid.len, MDL);
309  data_string_forget(&uid, MDL);
310  get_newest_lease(&lease, tmp_lease, next_uid);
311  assoc_ip_cnt = get_associated_ips(tmp_lease,
312  next_uid,
313  lease,
314  assoc_ips,
315  nassoc_ips);
316 
317  } else {
318 
319  if (packet->raw->hlen+1 > sizeof(h.hbuf)) {
320  log_info("%s: hardware length too long, "
321  "no reply sent", msgbuf);
322  option_state_dereference(&options, MDL);
323  return;
324  }
325 
326  h.hlen = packet->raw->hlen + 1;
327  h.hbuf[0] = packet->raw->htype;
328  memcpy(&h.hbuf[1],
329  packet->raw->chaddr,
330  packet->raw->hlen);
331 
332  snprintf(dbg_info,
333  sizeof(dbg_info),
334  "MAC address %s",
335  print_hw_addr(h.hbuf[0],
336  h.hlen - 1,
337  &h.hbuf[1]));
338 
339  find_lease_by_hw_addr(&tmp_lease, h.hbuf, h.hlen, MDL);
340  get_newest_lease(&lease, tmp_lease, next_hw);
341  assoc_ip_cnt = get_associated_ips(tmp_lease,
342  next_hw,
343  lease,
344  assoc_ips,
345  nassoc_ips);
346 
347  }
348 
349  lease_dereference(&tmp_lease, MDL);
350 
351  if (lease != NULL) {
352  memcpy(&packet->raw->ciaddr,
354  sizeof(packet->raw->ciaddr));
355  }
356 
357  /*
358  * Log if we have too many IP addresses associated
359  * with this client.
360  */
361  if (want_associated_ip && (assoc_ip_cnt > nassoc_ips)) {
362  log_info("%d IP addresses associated with %s, "
363  "only %d sent in reply.",
364  assoc_ip_cnt, dbg_info, nassoc_ips);
365  }
366  }
367 
368  /*
369  * We now know the query target too, so can report this in
370  * our log message.
371  */
372  snprintf(msgbuf, sizeof(msgbuf),
373  "DHCPLEASEQUERY from %s for %s",
374  inet_ntoa(packet->raw->giaddr), dbg_info);
375 
376  /*
377  * Figure our our return type.
378  */
379  if (lease == NULL) {
380  dhcpMsgType = DHCPLEASEUNKNOWN;
381  dhcp_msg_type_name = "DHCPLEASEUNKNOWN";
382  } else {
383  if (lease->binding_state == FTS_ACTIVE) {
384  dhcpMsgType = DHCPLEASEACTIVE;
385  dhcp_msg_type_name = "DHCPLEASEACTIVE";
386  } else {
387  dhcpMsgType = DHCPLEASEUNASSIGNED;
388  dhcp_msg_type_name = "DHCPLEASEUNASSIGNED";
389  }
390  }
391 
392  /*
393  * Set options that only make sense if we have an active lease.
394  */
395 
396  if (dhcpMsgType == DHCPLEASEACTIVE)
397  {
398  /*
399  * RFC 4388 uses the PRL to request options for the agent to
400  * receive that are "about" the client. It is confusing
401  * because in some cases it wants to know what was sent to
402  * the client (lease times, adjusted), and in others it wants
403  * to know information the client sent. You're supposed to
404  * know this on a case-by-case basis.
405  *
406  * "Name servers", "domain name", and the like from the relay
407  * agent's scope seems less than useful. Our options are to
408  * restart the option cache from the lease's best point of view
409  * (execute statements from the lease pool's group), or to
410  * simply restart the option cache from empty.
411  *
412  * I think restarting the option cache from empty best
413  * approaches RFC 4388's intent; specific options are included.
414  */
415  option_state_dereference(&options, MDL);
416 
417  if (!option_state_allocate(&options, MDL)) {
418  log_error("%s: out of memory, no reply sent", msgbuf);
419  lease_dereference(&lease, MDL);
420  return;
421  }
422 
423  /*
424  * Set the hardware address fields.
425  */
426 
429  memcpy(packet->raw->chaddr,
430  &lease->hardware_addr.hbuf[1],
431  sizeof(packet->raw->chaddr));
432 
433  /*
434  * Set client identifier option.
435  */
436  if (lease->uid_len > 0) {
437  if (!add_option(options,
439  lease->uid,
440  lease->uid_len)) {
441  option_state_dereference(&options, MDL);
442  lease_dereference(&lease, MDL);
443  log_info("%s: out of memory, no reply sent",
444  msgbuf);
445  return;
446  }
447  }
448 
449 
450  /*
451  * Calculate T1 and T2, the times when the client
452  * tries to extend its lease on its networking
453  * address.
454  * These seem to be hard-coded in ISC DHCP, to 0.5 and
455  * 0.875 of the lease time.
456  */
457 
458  lease_duration = lease->ends - lease->starts;
459  time_renewal = lease->starts +
460  (lease_duration / 2);
461  time_rebinding = lease->starts +
462  (lease_duration / 2) +
463  (lease_duration / 4) +
464  (lease_duration / 8);
465 
466  if (time_renewal > cur_time) {
467  time_renewal = htonl(time_renewal - cur_time);
468 
469  if (!add_option(options,
471  &time_renewal,
472  sizeof(time_renewal))) {
473  option_state_dereference(&options, MDL);
474  lease_dereference(&lease, MDL);
475  log_info("%s: out of memory, no reply sent",
476  msgbuf);
477  return;
478  }
479  }
480 
481  if (time_rebinding > cur_time) {
482  time_rebinding = htonl(time_rebinding - cur_time);
483 
484  if (!add_option(options,
486  &time_rebinding,
487  sizeof(time_rebinding))) {
488  option_state_dereference(&options, MDL);
489  lease_dereference(&lease, MDL);
490  log_info("%s: out of memory, no reply sent",
491  msgbuf);
492  return;
493  }
494  }
495 
496  if (lease->ends > cur_time) {
497  time_expiry = htonl(lease->ends - cur_time);
498 
499  if (!add_option(options,
501  &time_expiry,
502  sizeof(time_expiry))) {
503  option_state_dereference(&options, MDL);
504  lease_dereference(&lease, MDL);
505  log_info("%s: out of memory, no reply sent",
506  msgbuf);
507  return;
508  }
509  }
510 
511  /* Supply the Vendor-Class-Identifier. */
512  if (lease->scope != NULL) {
513  struct data_string vendor_class;
514 
515  memset(&vendor_class, 0, sizeof(vendor_class));
516 
517  if (find_bound_string(&vendor_class, lease->scope,
518  "vendor-class-identifier")) {
519  if (!add_option(options,
521  (void *)vendor_class.data,
522  vendor_class.len)) {
523  option_state_dereference(&options,
524  MDL);
525  lease_dereference(&lease, MDL);
526  log_error("%s: error adding vendor "
527  "class identifier, no reply "
528  "sent", msgbuf);
529  data_string_forget(&vendor_class, MDL);
530  return;
531  }
532  data_string_forget(&vendor_class, MDL);
533  }
534  }
535 
536  /*
537  * Set the relay agent info.
538  *
539  * Note that because agent info is appended without regard
540  * to the PRL in cons_options(), this will be sent as the
541  * last option in the packet whether it is listed on PRL or
542  * not.
543  */
544 
545  if (lease->agent_options != NULL) {
546  int idx = agent_universe.index;
547  struct option_chain_head **tmp1 =
548  (struct option_chain_head **)
549  &(options->universes[idx]);
550  struct option_chain_head *tmp2 =
551  (struct option_chain_head *)
553 
554  option_chain_head_reference(tmp1, tmp2, MDL);
555  }
556 
557  /*
558  * Set the client last transaction time.
559  * We check to make sure we have a timestamp. For
560  * lease files that were saved before running a
561  * timestamp-aware version of the server, this may
562  * not be set.
563  */
564 
565  if (lease->cltt != MIN_TIME) {
566  if (cur_time > lease->cltt) {
567  client_last_transaction_time =
568  htonl(cur_time - lease->cltt);
569  } else {
570  client_last_transaction_time = htonl(0);
571  }
572  if (!add_option(options,
574  &client_last_transaction_time,
575  sizeof(client_last_transaction_time))) {
576  option_state_dereference(&options, MDL);
577  lease_dereference(&lease, MDL);
578  log_info("%s: out of memory, no reply sent",
579  msgbuf);
580  return;
581  }
582  }
583 
584  /*
585  * Set associated IPs, if requested and there are some.
586  */
587  if (want_associated_ip && (assoc_ip_cnt > 0)) {
588  if (!add_option(options,
590  assoc_ips,
591  assoc_ip_cnt * sizeof(assoc_ips[0]))) {
592  option_state_dereference(&options, MDL);
593  lease_dereference(&lease, MDL);
594  log_info("%s: out of memory, no reply sent",
595  msgbuf);
596  return;
597  }
598  }
599  }
600 
601  /*
602  * Set the message type.
603  */
604 
605  packet->raw->op = BOOTREPLY;
606 
607  /*
608  * Set DHCP message type.
609  */
610  if (!add_option(options,
612  &dhcpMsgType,
613  sizeof(dhcpMsgType))) {
614  option_state_dereference(&options, MDL);
615  lease_dereference(&lease, MDL);
616  log_info("%s: error adding option, no reply sent", msgbuf);
617  return;
618  }
619 
620  /*
621  * Log the message we've received.
622  */
623  log_info("%s", msgbuf);
624 
625  /*
626  * Figure out which address to use to send from.
627  */
628  get_server_source_address(&siaddr, options, options, packet);
629 
630  /*
631  * Set up the option buffer.
632  */
633 
634  memset(&prl, 0, sizeof(prl));
635  oc = lookup_option(&dhcp_universe, options,
637  if (oc != NULL) {
638  evaluate_option_cache(&prl,
639  packet,
640  NULL,
641  NULL,
642  packet->options,
643  options,
644  &global_scope,
645  oc,
646  MDL);
647  }
648  if (prl.len > 0) {
649  prl_ptr = &prl;
650  } else {
651  prl_ptr = NULL;
652  }
653 
655  packet->raw,
656  lease,
657  NULL,
658  0,
659  packet->options,
660  options,
661  &global_scope,
662  0,
663  0,
664  0,
665  prl_ptr,
666  NULL);
667 
668  data_string_forget(&prl, MDL); /* SK: safe, even if empty */
669  option_state_dereference(&options, MDL);
670  lease_dereference(&lease, MDL);
671 
672  to.sin_family = AF_INET;
673 #ifdef HAVE_SA_LEN
674  to.sin_len = sizeof(to);
675 #endif
676  memset(to.sin_zero, 0, sizeof(to.sin_zero));
677 
678 #if defined(RELAY_PORT)
680 #endif
681 
682  /*
683  * Leasequery packets are be sent to the gateway address.
684  */
685  to.sin_addr = packet->raw->giaddr;
686  if (packet->raw->giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
687 #if defined(RELAY_PORT)
688  to.sin_port = relay_port ? relay_port : local_port;
689 #else
690  to.sin_port = local_port;
691 #endif
692  } else {
693  to.sin_port = remote_port; /* XXXSK: For debugging. */
694  }
695 
696  /*
697  * The fallback_interface lets us send with a real IP
698  * address. The packet interface sends from all-zeros.
699  */
700  if (fallback_interface != NULL) {
701  interface = fallback_interface;
702  } else {
703  interface = packet->interface;
704  }
705 
706  /*
707  * Report what we're sending.
708  */
709  log_info("%s to %s for %s (%d associated IPs)",
710  dhcp_msg_type_name,
711  inet_ntoa(to.sin_addr), dbg_info, assoc_ip_cnt);
712 
714  NULL,
715  packet->raw,
717  siaddr,
718  &to,
719  NULL);
720 }
721 
722 #ifdef DHCPv6
723 
724 /*
725  * TODO: RFC5007 query-by-clientid.
726  *
727  * TODO: RFC5007 look at the pools according to the link-address.
728  *
729  * TODO: get fixed leases too.
730  *
731  * TODO: RFC5007 ORO in query-options.
732  *
733  * TODO: RFC5007 lq-relay-data.
734  *
735  * TODO: RFC5007 lq-client-link.
736  *
737  * Note: the code is still nearly compliant and usable for the target
738  * case with these missing features!
739  */
740 
741 /*
742  * The structure to handle a leasequery.
743  */
744 struct lq6_state {
745  struct packet *packet;
746  struct data_string client_id;
747  struct data_string server_id;
748  struct data_string lq_query;
749  uint8_t query_type;
750  struct in6_addr link_addr;
751  struct option_state *query_opts;
752 
753  struct option_state *reply_opts;
754  unsigned cursor;
755  union reply_buffer {
756  unsigned char data[65536];
757  struct dhcpv6_packet reply;
758  } buf;
759 };
760 
761 /*
762  * Options that we want to send.
763  */
764 static const int required_opts_lq[] = {
765  D6O_CLIENTID,
766  D6O_SERVERID,
771  0
772 };
773 static const int required_opt_CLIENT_DATA[] = {
774  D6O_CLIENTID,
775  D6O_IAADDR,
776  D6O_IAPREFIX,
777  D6O_CLT_TIME,
778  0
779 };
780 
781 /*
782  * Get the lq-query option from the packet.
783  */
784 static isc_result_t
785 get_lq_query(struct lq6_state *lq)
786 {
787  struct data_string *lq_query = &lq->lq_query;
788  struct packet *packet = lq->packet;
789  struct option_cache *oc;
790 
791  /*
792  * Verify our lq_query structure is empty.
793  */
794  if ((lq_query->data != NULL) || (lq_query->len != 0)) {
795  return DHCP_R_INVALIDARG;
796  }
797 
799  if (oc == NULL) {
800  return ISC_R_NOTFOUND;
801  }
802 
803  if (!evaluate_option_cache(lq_query, packet, NULL, NULL,
804  packet->options, NULL,
805  &global_scope, oc, MDL)) {
806  return ISC_R_FAILURE;
807  }
808 
809  return ISC_R_SUCCESS;
810 }
811 
812 /*
813  * Message validation, RFC 5007 section 4.2.1:
814  * dhcpv6.c:valid_client_msg() - unicast + lq-query option.
815  */
816 static int
817 valid_query_msg(struct lq6_state *lq) {
818  struct packet *packet = lq->packet;
819  int ret_val = 0;
820  struct option_cache *oc;
821 
822  /* INSIST((lq != NULL) || (packet != NULL)); */
823 
824  switch (get_client_id(packet, &lq->client_id)) {
825  case ISC_R_SUCCESS:
826  break;
827  case ISC_R_NOTFOUND:
828  log_debug("Discarding %s from %s; "
829  "client identifier missing",
832  goto exit;
833  default:
834  log_error("Error processing %s from %s; "
835  "unable to evaluate Client Identifier",
838  goto exit;
839  }
840 
842  if (oc != NULL) {
843  if (evaluate_option_cache(&lq->server_id, packet, NULL, NULL,
844  packet->options, NULL,
845  &global_scope, oc, MDL)) {
846  log_debug("Discarding %s from %s; "
847  "server identifier found "
848  "(CLIENTID %s, SERVERID %s)",
851  print_hex_1(lq->client_id.len,
852  lq->client_id.data, 60),
853  print_hex_2(lq->server_id.len,
854  lq->server_id.data, 60));
855  } else {
856  log_debug("Discarding %s from %s; "
857  "server identifier found "
858  "(CLIENTID %s)",
860  print_hex_1(lq->client_id.len,
861  lq->client_id.data, 60),
863  }
864  goto exit;
865  }
866 
867  switch (get_lq_query(lq)) {
868  case ISC_R_SUCCESS:
869  break;
870  case ISC_R_NOTFOUND:
871  log_debug("Discarding %s from %s; lq-query missing",
874  goto exit;
875  default:
876  log_error("Error processing %s from %s; "
877  "unable to evaluate LQ-Query",
880  goto exit;
881  }
882 
883  /* looks good */
884  ret_val = 1;
885 
886 exit:
887  if (!ret_val) {
888  data_string_forget(&lq->client_id, MDL);
889  data_string_forget(&lq->server_id, MDL);
890  data_string_forget(&lq->lq_query, MDL);
891  }
892  return ret_val;
893 }
894 
895 /*
896  * Set an error in a status-code option (from set_status_code).
897  */
898 static int
899 set_error(struct lq6_state *lq, u_int16_t code, const char *message) {
900  struct data_string d;
901  int ret_val;
902 
903  memset(&d, 0, sizeof(d));
904  d.len = sizeof(code) + strlen(message);
905  if (!buffer_allocate(&d.buffer, d.len, MDL)) {
906  log_fatal("set_error: no memory for status code.");
907  }
908  d.data = d.buffer->data;
909  putUShort(d.buffer->data, code);
910  memcpy(d.buffer->data + sizeof(code), message, d.len - sizeof(code));
911  if (!save_option_buffer(&dhcpv6_universe, lq->reply_opts,
912  d.buffer, (unsigned char *)d.data, d.len,
913  D6O_STATUS_CODE, 0)) {
914  log_error("set_error: error saving status code.");
915  ret_val = 0;
916  } else {
917  ret_val = 1;
918  }
919  data_string_forget(&d, MDL);
920  return ret_val;
921 }
922 
923 /*
924  * Process a by-address lease query.
925  */
926 static int
927 process_lq_by_address(struct lq6_state *lq) {
928  struct packet *packet = lq->packet;
929  struct option_cache *oc;
930  struct ipv6_pool *pool = NULL;
931  struct data_string data;
932  struct in6_addr addr;
933  struct iasubopt *iaaddr = NULL;
934  struct option_state *opt_state = NULL;
935  u_int32_t lifetime;
936  unsigned opt_cursor;
937  int ret_val = 0;
938 
939  /*
940  * Get the IAADDR.
941  */
942  oc = lookup_option(&dhcpv6_universe, lq->query_opts, D6O_IAADDR);
943  if (oc == NULL) {
944  if (!set_error(lq, STATUS_MalformedQuery,
945  "No OPTION_IAADDR.")) {
946  log_error("process_lq_by_address: unable "
947  "to set MalformedQuery status code.");
948  return 0;
949  }
950  return 1;
951  }
952  memset(&data, 0, sizeof(data));
953  if (!evaluate_option_cache(&data, packet,
954  NULL, NULL,
955  lq->query_opts, NULL,
956  &global_scope, oc, MDL) ||
957  (data.len < IAADDR_OFFSET)) {
958  log_error("process_lq_by_address: error evaluating IAADDR.");
959  goto exit;
960  }
961  memcpy(&addr, data.data, sizeof(addr));
962  data_string_forget(&data, MDL);
963 
964  /*
965  * Find the lease.
966  * Note the RFC 5007 says to use the link-address to find the link
967  * or the ia-aadr when it is :: but in any case the ia-addr has
968  * to be on the link, so we ignore the link-address here.
969  */
970  if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_SUCCESS) {
971  if (!set_error(lq, STATUS_NotConfigured,
972  "Address not in a pool.")) {
973  log_error("process_lq_by_address: unable "
974  "to set NotConfigured status code.");
975  goto exit;
976  }
977  ret_val = 1;
978  goto exit;
979  }
980  if (iasubopt_hash_lookup(&iaaddr, pool->leases, &addr,
981  sizeof(addr), MDL) == 0) {
982  ret_val = 1;
983  goto exit;
984  }
985  if ((iaaddr == NULL) || (iaaddr->state != FTS_ACTIVE) ||
986  (iaaddr->ia == NULL) || (iaaddr->ia->iaid_duid.len <= 4)) {
987  ret_val = 1;
988  goto exit;
989  }
990 
991  /*
992  * Build the client-data option (with client-id, ia-addr and clt-time).
993  */
994  if (!option_state_allocate(&opt_state, MDL)) {
995  log_error("process_lq_by_address: "
996  "no memory for option state.");
997  goto exit;
998  }
999 
1000  data_string_copy(&data, &iaaddr->ia->iaid_duid, MDL);
1001  data.data += 4;
1002  data.len -= 4;
1003  if (!save_option_buffer(&dhcpv6_universe, opt_state,
1004  NULL, (unsigned char *)data.data, data.len,
1005  D6O_CLIENTID, 0)) {
1006  log_error("process_lq_by_address: error saving client ID.");
1007  goto exit;
1008  }
1009  data_string_forget(&data, MDL);
1010 
1011  data.len = IAADDR_OFFSET;
1012  if (!buffer_allocate(&data.buffer, data.len, MDL)) {
1013  log_error("process_lq_by_address: no memory for ia-addr.");
1014  goto exit;
1015  }
1016  data.data = data.buffer->data;
1017  memcpy(data.buffer->data, &iaaddr->addr, 16);
1018  lifetime = iaaddr->prefer;
1019  putULong(data.buffer->data + 16, lifetime);
1020  lifetime = iaaddr->valid;
1021  putULong(data.buffer->data + 20, lifetime);
1022  if (!save_option_buffer(&dhcpv6_universe, opt_state,
1023  NULL, (unsigned char *)data.data, data.len,
1024  D6O_IAADDR, 0)) {
1025  log_error("process_lq_by_address: error saving ia-addr.");
1026  goto exit;
1027  }
1028  data_string_forget(&data, MDL);
1029 
1030  lifetime = htonl(iaaddr->ia->cltt);
1031  if (!save_option_buffer(&dhcpv6_universe, opt_state,
1032  NULL, (unsigned char *)&lifetime, 4,
1033  D6O_CLT_TIME, 0)) {
1034  log_error("process_lq_by_address: error saving clt time.");
1035  goto exit;
1036  }
1037 
1038  /*
1039  * Store the client-data option.
1040  */
1041  opt_cursor = lq->cursor;
1042  putUShort(lq->buf.data + lq->cursor, (unsigned)D6O_CLIENT_DATA);
1043  lq->cursor += 2;
1044  /* Skip option length. */
1045  lq->cursor += 2;
1046 
1047  lq->cursor += store_options6((char *)lq->buf.data + lq->cursor,
1048  sizeof(lq->buf) - lq->cursor,
1049  opt_state, lq->packet,
1050  required_opt_CLIENT_DATA, NULL);
1051  /* Reset the length. */
1052  putUShort(lq->buf.data + opt_cursor + 2,
1053  lq->cursor - (opt_cursor + 4));
1054 
1055  /* Done. */
1056  ret_val = 1;
1057 
1058  exit:
1059  if (data.data != NULL)
1060  data_string_forget(&data, MDL);
1061  if (pool != NULL)
1063  if (iaaddr != NULL)
1064  iasubopt_dereference(&iaaddr, MDL);
1065  if (opt_state != NULL)
1066  option_state_dereference(&opt_state, MDL);
1067  return ret_val;
1068 }
1069 
1070 
1071 /*
1072  * Process a lease query.
1073  */
1074 void
1075 dhcpv6_leasequery(struct data_string *reply_ret, struct packet *packet) {
1076  static struct lq6_state lq;
1077  struct option_cache *oc;
1078  int allow_lq;
1079 
1080  /*
1081  * Initialize the lease query state.
1082  */
1083  lq.packet = NULL;
1084  memset(&lq.client_id, 0, sizeof(lq.client_id));
1085  memset(&lq.server_id, 0, sizeof(lq.server_id));
1086  memset(&lq.lq_query, 0, sizeof(lq.lq_query));
1087  lq.query_opts = NULL;
1088  lq.reply_opts = NULL;
1089  packet_reference(&lq.packet, packet, MDL);
1090 
1091  /*
1092  * Validate our input.
1093  */
1094  if (!valid_query_msg(&lq)) {
1095  goto exit;
1096  }
1097 
1098  /*
1099  * Prepare our reply.
1100  */
1101  if (!option_state_allocate(&lq.reply_opts, MDL)) {
1102  log_error("dhcpv6_leasequery: no memory for option state.");
1103  goto exit;
1104  }
1105  execute_statements_in_scope(NULL, lq.packet, NULL, NULL,
1106  lq.packet->options, lq.reply_opts,
1107  &global_scope, root_group, NULL, NULL);
1108 
1109  lq.buf.reply.msg_type = DHCPV6_LEASEQUERY_REPLY;
1110 
1111  memcpy(lq.buf.reply.transaction_id,
1112  lq.packet->dhcpv6_transaction_id,
1113  sizeof(lq.buf.reply.transaction_id));
1114 
1115  /*
1116  * Because LEASEQUERY has some privacy concerns, default to deny.
1117  */
1118  allow_lq = 0;
1119 
1120  /*
1121  * See if we are authorized to do LEASEQUERY.
1122  */
1123  oc = lookup_option(&server_universe, lq.reply_opts, SV_LEASEQUERY);
1124  if (oc != NULL) {
1125  allow_lq = evaluate_boolean_option_cache(NULL,
1126  lq.packet,
1127  NULL, NULL,
1128  lq.packet->options,
1129  lq.reply_opts,
1130  &global_scope,
1131  oc, MDL);
1132  }
1133 
1134  if (!allow_lq) {
1135  log_info("dhcpv6_leasequery: not allowed, query ignored.");
1136  goto exit;
1137  }
1138 
1139  /*
1140  * Same than transmission of REPLY message in RFC 3315:
1141  * server-id
1142  * client-id
1143  */
1144 
1145  oc = lookup_option(&dhcpv6_universe, lq.reply_opts, D6O_SERVERID);
1146  if (oc == NULL) {
1147  /* If not already in options, get from query then global. */
1148  if (lq.server_id.data == NULL)
1149  copy_server_duid(&lq.server_id, MDL);
1151  lq.reply_opts,
1152  NULL,
1153  (unsigned char *)lq.server_id.data,
1154  lq.server_id.len,
1155  D6O_SERVERID,
1156  0)) {
1157  log_error("dhcpv6_leasequery: "
1158  "error saving server identifier.");
1159  goto exit;
1160  }
1161  }
1162 
1164  lq.reply_opts,
1165  lq.client_id.buffer,
1166  (unsigned char *)lq.client_id.data,
1167  lq.client_id.len,
1168  D6O_CLIENTID,
1169  0)) {
1170  log_error("dhcpv6_leasequery: "
1171  "error saving client identifier.");
1172  goto exit;
1173  }
1174 
1175  lq.cursor = 4;
1176 
1177  /*
1178  * Decode the lq-query option.
1179  */
1180 
1181  if (lq.lq_query.len <= LQ_QUERY_OFFSET) {
1182  if (!set_error(&lq, STATUS_MalformedQuery,
1183  "OPTION_LQ_QUERY too short.")) {
1184  log_error("dhcpv6_leasequery: unable "
1185  "to set MalformedQuery status code.");
1186  goto exit;
1187  }
1188  goto done;
1189  }
1190 
1191  lq.query_type = lq.lq_query.data [0];
1192  memcpy(&lq.link_addr, lq.lq_query.data + 1, sizeof(lq.link_addr));
1193  switch (lq.query_type) {
1194  case LQ6QT_BY_ADDRESS:
1195  break;
1196  case LQ6QT_BY_CLIENTID:
1197  if (!set_error(&lq, STATUS_UnknownQueryType,
1198  "QUERY_BY_CLIENTID not supported.")) {
1199  log_error("dhcpv6_leasequery: unable to "
1200  "set UnknownQueryType status code.");
1201  goto exit;
1202  }
1203  goto done;
1204  default:
1205  if (!set_error(&lq, STATUS_UnknownQueryType,
1206  "Unknown query-type.")) {
1207  log_error("dhcpv6_leasequery: unable to "
1208  "set UnknownQueryType status code.");
1209  goto exit;
1210  }
1211  goto done;
1212  }
1213 
1214  if (!option_state_allocate(&lq.query_opts, MDL)) {
1215  log_error("dhcpv6_leasequery: no memory for option state.");
1216  goto exit;
1217  }
1218  if (!parse_option_buffer(lq.query_opts,
1219  lq.lq_query.data + LQ_QUERY_OFFSET,
1220  lq.lq_query.len - LQ_QUERY_OFFSET,
1221  &dhcpv6_universe)) {
1222  log_error("dhcpv6_leasequery: error parsing query-options.");
1223  if (!set_error(&lq, STATUS_MalformedQuery,
1224  "Bad query-options.")) {
1225  log_error("dhcpv6_leasequery: unable "
1226  "to set MalformedQuery status code.");
1227  goto exit;
1228  }
1229  goto done;
1230  }
1231 
1232  /* Do it. */
1233  if (!process_lq_by_address(&lq))
1234  goto exit;
1235 
1236  done:
1237  /* Store the options. */
1238  lq.cursor += store_options6((char *)lq.buf.data + lq.cursor,
1239  sizeof(lq.buf) - lq.cursor,
1240  lq.reply_opts,
1241  lq.packet,
1242  required_opts_lq,
1243  NULL);
1244 
1245  /* Return our reply to the caller. */
1246  reply_ret->len = lq.cursor;
1247  reply_ret->buffer = NULL;
1248  if (!buffer_allocate(&reply_ret->buffer, lq.cursor, MDL)) {
1249  log_fatal("dhcpv6_leasequery: no memory to store Reply.");
1250  }
1251  memcpy(reply_ret->buffer->data, lq.buf.data, lq.cursor);
1252  reply_ret->data = reply_ret->buffer->data;
1253 
1254  exit:
1255  /* Cleanup. */
1256  if (lq.packet != NULL)
1257  packet_dereference(&lq.packet, MDL);
1258  if (lq.client_id.data != NULL)
1259  data_string_forget(&lq.client_id, MDL);
1260  if (lq.server_id.data != NULL)
1261  data_string_forget(&lq.server_id, MDL);
1262  if (lq.lq_query.data != NULL)
1263  data_string_forget(&lq.lq_query, MDL);
1264  if (lq.query_opts != NULL)
1265  option_state_dereference(&lq.query_opts, MDL);
1266  if (lq.reply_opts != NULL)
1267  option_state_dereference(&lq.reply_opts, MDL);
1268 }
1269 
1270 #endif /* DHCPv6 */
universe::index
int index
Definition: tree.h:339
iaddr::iabuf
unsigned char iabuf[16]
Definition: inet.h:33
evaluate_boolean_option_cache
int evaluate_boolean_option_cache(int *ignorep, 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:2733
lease::starts
TIME starts
Definition: dhcpd.h:570
option_state
Definition: dhcpd.h:396
send_packet
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
DHO_DHCP_RENEWAL_TIME
#define DHO_DHCP_RENEWAL_TIME
Definition: dhcp.h:147
lease
Definition: dhcpd.h:560
putUShort
void putUShort(unsigned char *, u_int32_t)
Definition: convert.c:86
server_universe
struct universe server_universe
Definition: stables.c:176
dhcp_packet::ciaddr
struct in_addr ciaddr
Definition: dhcp.h:55
lease::n_uid
struct lease * n_uid
Definition: dhcpd.h:567
log_fatal
void log_fatal(const char *,...) __attribute__((__format__(__printf__
lease::next
struct lease * next
Definition: dhcpd.h:562
find_lease_by_ip_addr
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
Definition: mdb.c:2052
cur_time
#define cur_time
Definition: dhcpd.h:2121
hardware
Definition: dhcpd.h:491
lease::uid_len
unsigned short uid_len
Definition: dhcpd.h:586
iasubopt::ia
struct ia_xx * ia
Definition: dhcpd.h:1651
get_client_id
isc_result_t get_client_id(struct packet *, struct data_string *)
lease::ends
TIME ends
Definition: dhcpd.h:570
D6O_IAPREFIX
#define D6O_IAPREFIX
Definition: dhcp6.h:55
SV_LEASEQUERY
#define SV_LEASEQUERY
Definition: dhcpd.h:759
packet
Definition: dhcpd.h:405
get_newest_lease
void get_newest_lease(struct lease **retval, struct lease *lease, struct lease *(*next)(const struct lease *))
Definition: dhcpleasequery.c:62
add_option
int add_option(struct option_state *options, unsigned int option_num, void *data, unsigned int data_len)
Definition: options.c:4480
dhcpd.h
find_ipv6_pool
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *addr)
Definition: mdb6.c:2291
DHCPLEASEACTIVE
#define DHCPLEASEACTIVE
Definition: dhcp.h:180
BOOTREPLY
#define BOOTREPLY
Definition: dhcp.h:69
agent_universe
struct universe agent_universe
Definition: stables.c:165
dhcpleasequery
void dhcpleasequery(struct packet *packet, int ms_nulltp)
Definition: dhcpleasequery.c:128
data_string_forget
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1339
LQ6QT_BY_ADDRESS
#define LQ6QT_BY_ADDRESS
Definition: dhcp6.h:264
iasubopt::addr
struct in6_addr addr
Definition: dhcpd.h:1643
ia_xx::cltt
time_t cltt
Definition: dhcpd.h:1682
option_chain_head
Definition: tree.h:35
buffer::data
unsigned char data[1]
Definition: tree.h:62
get_server_source_address
void get_server_source_address(struct in_addr *from, struct option_state *options, struct option_state *out_options, struct packet *packet)
Definition: dhcp.c:5487
IAADDR_OFFSET
#define IAADDR_OFFSET
Definition: dhcp6.h:178
data_string::data
const unsigned char * data
Definition: tree.h:78
DHO_DHCP_PARAMETER_REQUEST_LIST
#define DHO_DHCP_PARAMETER_REQUEST_LIST
Definition: dhcp.h:144
find_subnet
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
Definition: dhclient.c:1552
option_cache
Definition: dhcpd.h:385
iasubopt::prefer
u_int32_t prefer
Definition: dhcpd.h:1649
FTS_ACTIVE
#define FTS_ACTIVE
Definition: dhcpd.h:538
DHCPLEASEUNASSIGNED
#define DHCPLEASEUNASSIGNED
Definition: dhcp.h:178
STATUS_MalformedQuery
#define STATUS_MalformedQuery
Definition: dhcp6.h:132
dhcpv6_universe
struct universe dhcpv6_universe
Definition: tables.c:348
D6O_CLIENTID
#define D6O_CLIENTID
Definition: dhcp6.h:30
lookup_option
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition: options.c:2503
DHO_DHCP_MESSAGE_TYPE
#define DHO_DHCP_MESSAGE_TYPE
Definition: dhcp.h:142
DHO_VENDOR_CLASS_IDENTIFIER
#define DHO_VENDOR_CLASS_IDENTIFIER
Definition: dhcp.h:149
dhcp_check_relayport
u_int16_t dhcp_check_relayport(struct packet *packet)
dhcp_packet::htype
u_int8_t htype
Definition: dhcp.h:49
data_string
Definition: tree.h:76
lease::ip_addr
struct iaddr ip_addr
Definition: dhcpd.h:569
execute_statements_in_scope
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
Definition: execute.c:570
option_state_allocate
int option_state_allocate(struct option_state **ptr, const char *file, int line)
Definition: alloc.c:846
root_group
struct group * root_group
Definition: memory.c:31
DHO_DHCP_CLIENT_IDENTIFIER
#define DHO_DHCP_CLIENT_IDENTIFIER
Definition: dhcp.h:150
packet::class_count
int class_count
Definition: dhcpd.h:454
D6O_STATUS_CODE
#define D6O_STATUS_CODE
Definition: dhcp6.h:42
ia_xx::iaid_duid
struct data_string iaid_duid
Definition: dhcpd.h:1678
data_string::len
unsigned len
Definition: tree.h:79
lease::scope
struct binding_scope * scope
Definition: dhcpd.h:575
print_hex_2
#define print_hex_2(len, data, limit)
Definition: dhcpd.h:2634
print_hex_1
#define print_hex_1(len, data, limit)
Definition: dhcpd.h:2633
get_option
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:2323
dhcpv6_packet
Definition: dhcp6.h:227
lease::uid
unsigned char * uid
Definition: dhcpd.h:585
D6O_IA_NA
#define D6O_IA_NA
Definition: dhcp6.h:32
group
Definition: dhcpd.h:958
log_info
int int log_info(const char *,...) __attribute__((__format__(__printf__
find_lease_by_hw_addr
int find_lease_by_hw_addr(struct lease **, const unsigned char *, unsigned, const char *, int)
Definition: mdb.c:2067
relay_port
u_int16_t relay_port
Definition: discover.c:47
dhcpv6_leasequery
void dhcpv6_leasequery(struct data_string *, struct packet *)
DHO_DHCP_REBINDING_TIME
#define DHO_DHCP_REBINDING_TIME
Definition: dhcp.h:148
ipv6_pool_dereference
isc_result_t ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line)
de-reference an IPv6 pool structure.
Definition: mdb6.c:777
remote_port
u_int16_t remote_port
Definition: dhclient.c:97
DHO_PXE_CLIENT_ID
#define DHO_PXE_CLIENT_ID
Definition: dhcp.h:159
D6O_SERVERID
#define D6O_SERVERID
Definition: dhcp6.h:31
packet_reference
int packet_reference(struct packet **ptr, struct packet *bp, const char *file, int line)
Definition: alloc.c:1053
store_options6
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:1048
LQ_QUERY_OFFSET
#define LQ_QUERY_OFFSET
Definition: dhcp6.h:184
option_chain_head_reference
int option_chain_head_reference(struct option_chain_head **ptr, struct option_chain_head *bp, const char *file, int line)
Definition: alloc.c:67
MDL
#define MDL
Definition: omapip.h:567
cons_options
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:538
lease::cltt
TIME cltt
Definition: dhcpd.h:640
buffer_allocate
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition: alloc.c:679
iaddr
Definition: inet.h:31
hardware::hlen
u_int8_t hlen
Definition: dhcpd.h:492
find_lease_by_uid
int find_lease_by_uid(struct lease **, const unsigned char *, unsigned, const char *, int)
Definition: mdb.c:2059
log_error
int log_error(const char *,...) __attribute__((__format__(__printf__
D6O_LQ_CLIENT_LINK
#define D6O_LQ_CLIENT_LINK
Definition: dhcp6.h:77
option_state::universes
void * universes[1]
Definition: dhcpd.h:401
lease::n_hw
struct lease * n_hw
Definition: dhcpd.h:567
STATUS_NotConfigured
#define STATUS_NotConfigured
Definition: dhcp6.h:133
iasubopt
Definition: dhcpd.h:1641
packet::dhcpv6_msg_type
unsigned char dhcpv6_msg_type
Definition: dhcpd.h:411
DHCPLEASEUNKNOWN
#define DHCPLEASEUNKNOWN
Definition: dhcp.h:179
find_bound_string
int find_bound_string(struct data_string *value, struct binding_scope *scope, const char *name)
Definition: tree.c:4103
dhcp_packet::chaddr
unsigned char chaddr[16]
Definition: dhcp.h:59
copy_server_duid
void copy_server_duid(struct data_string *ds, const char *file, int line)
class::group
struct group * group
Definition: dhcpd.h:1125
subnet::group
struct group * group
Definition: dhcpd.h:1081
iasubopt_dereference
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
Definition: mdb6.c:261
putULong
void putULong(unsigned char *, u_int32_t)
Definition: convert.c:70
option_state_dereference
int option_state_dereference(struct option_state **ptr, const char *file, int line)
Definition: alloc.c:911
packet_dereference
int packet_dereference(struct packet **ptr, const char *file, int line)
Definition: alloc.c:1081
parse_option_buffer
int parse_option_buffer(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *universe)
Definition: options.c:119
hardware::hbuf
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition: dhcpd.h:493
packet::classes
struct class * classes[PACKET_MAX_CLASSES]
Definition: dhcpd.h:455
D6O_IAADDR
#define D6O_IAADDR
Definition: dhcp6.h:34
dhcpv6_type_names
const char * dhcpv6_type_names[]
Definition: tables.c:665
dhcp_packet::op
u_int8_t op
Definition: dhcp.h:48
dhcp_packet::hlen
u_int8_t hlen
Definition: dhcp.h:50
packet::options
struct option_state * options
Definition: dhcpd.h:449
subnet
Definition: dhcpd.h:1071
DHCPV6_LEASEQUERY_REPLY
#define DHCPV6_LEASEQUERY_REPLY
Definition: dhcp6.h:154
iaddr::len
unsigned len
Definition: inet.h:32
global_scope
struct binding_scope * global_scope
Definition: tree.c:38
evaluate_option_cache
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition: tree.c:2699
DHO_DHCP_LEASE_TIME
#define DHO_DHCP_LEASE_TIME
Definition: dhcp.h:140
log_debug
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
save_option_buffer
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:2545
lease::agent_options
struct option_chain_head * agent_options
Definition: dhcpd.h:580
DHO_ASSOCIATED_IP
#define DHO_ASSOCIATED_IP
Definition: dhcp.h:158
piaddr
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
pool
Definition: dhcpd.h:1025
DHO_CLIENT_LAST_TRANSACTION_TIME
#define DHO_CLIENT_LAST_TRANSACTION_TIME
Definition: dhcp.h:157
interface_info
Definition: dhcpd.h:1376
data_string::buffer
struct buffer * buffer
Definition: tree.h:77
local_port
u_int16_t local_port
Definition: dhclient.c:96
D6O_LQ_QUERY
#define D6O_LQ_QUERY
Definition: dhcp6.h:73
subnet::subnet
struct element * subnet
Definition: confparse.c:57
print_hw_addr
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
Definition: print.c:171
packet::raw
struct dhcp_packet * raw
Definition: dhcpd.h:406
lease::hardware_addr
struct hardware hardware_addr
Definition: dhcpd.h:589
DHCP_R_INVALIDARG
#define DHCP_R_INVALIDARG
Definition: result.h:49
D6O_CLT_TIME
#define D6O_CLT_TIME
Definition: dhcp6.h:75
iasubopt::state
binding_state_t state
Definition: dhcpd.h:1645
D6O_CLIENT_DATA
#define D6O_CLIENT_DATA
Definition: dhcp6.h:74
dhcp_packet::giaddr
struct in_addr giaddr
Definition: dhcp.h:58
packet::interface
struct interface_info * interface
Definition: dhcpd.h:433
lease::binding_state
binding_state_t binding_state
Definition: dhcpd.h:623
MIN_TIME
#define MIN_TIME
Definition: dhcpd.h:1627
packet::packet_length
unsigned packet_length
Definition: dhcpd.h:408
D6O_LQ_RELAY_DATA
#define D6O_LQ_RELAY_DATA
Definition: dhcp6.h:76
dhcp_universe
struct universe dhcp_universe
ISC_R_SUCCESS
#define ISC_R_SUCCESS
STATUS_UnknownQueryType
#define STATUS_UnknownQueryType
Definition: dhcp6.h:131
data_string_copy
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition: alloc.c:1323
iasubopt::valid
u_int32_t valid
Definition: dhcpd.h:1650
fallback_interface
struct interface_info * fallback_interface
Definition: discover.c:42
ipv6_pool
ipv6_pool structure
Definition: dhcpd.h:1710
LQ6QT_BY_CLIENTID
#define LQ6QT_BY_CLIENTID
Definition: dhcp6.h:265
packet::client_addr
struct iaddr client_addr
Definition: dhcpd.h:432