ISC DHCP  4.4.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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));
265  find_lease_by_ip_addr(&lease, cip, MDL);
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  if (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 
291  snprintf(dbg_info,
292  sizeof(dbg_info),
293  "client-id %s",
294  print_hex_1(uid.len, uid.data, 60));
295 
296  find_lease_by_uid(&tmp_lease, uid.data, uid.len, MDL);
297  data_string_forget(&uid, MDL);
298  get_newest_lease(&lease, tmp_lease, next_uid);
299  assoc_ip_cnt = get_associated_ips(tmp_lease,
300  next_uid,
301  lease,
302  assoc_ips,
303  nassoc_ips);
304 
305  } else {
306 
307  if (packet->raw->hlen+1 > sizeof(h.hbuf)) {
308  log_info("%s: hardware length too long, "
309  "no reply sent", msgbuf);
310  option_state_dereference(&options, MDL);
311  return;
312  }
313 
314  h.hlen = packet->raw->hlen + 1;
315  h.hbuf[0] = packet->raw->htype;
316  memcpy(&h.hbuf[1],
317  packet->raw->chaddr,
318  packet->raw->hlen);
319 
320  snprintf(dbg_info,
321  sizeof(dbg_info),
322  "MAC address %s",
323  print_hw_addr(h.hbuf[0],
324  h.hlen - 1,
325  &h.hbuf[1]));
326 
327  find_lease_by_hw_addr(&tmp_lease, h.hbuf, h.hlen, MDL);
328  get_newest_lease(&lease, tmp_lease, next_hw);
329  assoc_ip_cnt = get_associated_ips(tmp_lease,
330  next_hw,
331  lease,
332  assoc_ips,
333  nassoc_ips);
334 
335  }
336 
337  lease_dereference(&tmp_lease, MDL);
338 
339  if (lease != NULL) {
340  memcpy(&packet->raw->ciaddr,
341  lease->ip_addr.iabuf,
342  sizeof(packet->raw->ciaddr));
343  }
344 
345  /*
346  * Log if we have too many IP addresses associated
347  * with this client.
348  */
349  if (want_associated_ip && (assoc_ip_cnt > nassoc_ips)) {
350  log_info("%d IP addresses associated with %s, "
351  "only %d sent in reply.",
352  assoc_ip_cnt, dbg_info, nassoc_ips);
353  }
354  }
355 
356  /*
357  * We now know the query target too, so can report this in
358  * our log message.
359  */
360  snprintf(msgbuf, sizeof(msgbuf),
361  "DHCPLEASEQUERY from %s for %s",
362  inet_ntoa(packet->raw->giaddr), dbg_info);
363 
364  /*
365  * Figure our our return type.
366  */
367  if (lease == NULL) {
368  dhcpMsgType = DHCPLEASEUNKNOWN;
369  dhcp_msg_type_name = "DHCPLEASEUNKNOWN";
370  } else {
371  if (lease->binding_state == FTS_ACTIVE) {
372  dhcpMsgType = DHCPLEASEACTIVE;
373  dhcp_msg_type_name = "DHCPLEASEACTIVE";
374  } else {
375  dhcpMsgType = DHCPLEASEUNASSIGNED;
376  dhcp_msg_type_name = "DHCPLEASEUNASSIGNED";
377  }
378  }
379 
380  /*
381  * Set options that only make sense if we have an active lease.
382  */
383 
384  if (dhcpMsgType == DHCPLEASEACTIVE)
385  {
386  /*
387  * RFC 4388 uses the PRL to request options for the agent to
388  * receive that are "about" the client. It is confusing
389  * because in some cases it wants to know what was sent to
390  * the client (lease times, adjusted), and in others it wants
391  * to know information the client sent. You're supposed to
392  * know this on a case-by-case basis.
393  *
394  * "Name servers", "domain name", and the like from the relay
395  * agent's scope seems less than useful. Our options are to
396  * restart the option cache from the lease's best point of view
397  * (execute statements from the lease pool's group), or to
398  * simply restart the option cache from empty.
399  *
400  * I think restarting the option cache from empty best
401  * approaches RFC 4388's intent; specific options are included.
402  */
403  option_state_dereference(&options, MDL);
404 
405  if (!option_state_allocate(&options, MDL)) {
406  log_error("%s: out of memory, no reply sent", msgbuf);
407  lease_dereference(&lease, MDL);
408  return;
409  }
410 
411  /*
412  * Set the hardware address fields.
413  */
414 
415  packet->raw->hlen = lease->hardware_addr.hlen - 1;
416  packet->raw->htype = lease->hardware_addr.hbuf[0];
417  memcpy(packet->raw->chaddr,
418  &lease->hardware_addr.hbuf[1],
419  sizeof(packet->raw->chaddr));
420 
421  /*
422  * Set client identifier option.
423  */
424  if (lease->uid_len > 0) {
425  if (!add_option(options,
427  lease->uid,
428  lease->uid_len)) {
429  option_state_dereference(&options, MDL);
430  lease_dereference(&lease, MDL);
431  log_info("%s: out of memory, no reply sent",
432  msgbuf);
433  return;
434  }
435  }
436 
437 
438  /*
439  * Calculate T1 and T2, the times when the client
440  * tries to extend its lease on its networking
441  * address.
442  * These seem to be hard-coded in ISC DHCP, to 0.5 and
443  * 0.875 of the lease time.
444  */
445 
446  lease_duration = lease->ends - lease->starts;
447  time_renewal = lease->starts +
448  (lease_duration / 2);
449  time_rebinding = lease->starts +
450  (lease_duration / 2) +
451  (lease_duration / 4) +
452  (lease_duration / 8);
453 
454  if (time_renewal > cur_time) {
455  time_renewal = htonl(time_renewal - cur_time);
456 
457  if (!add_option(options,
459  &time_renewal,
460  sizeof(time_renewal))) {
461  option_state_dereference(&options, MDL);
462  lease_dereference(&lease, MDL);
463  log_info("%s: out of memory, no reply sent",
464  msgbuf);
465  return;
466  }
467  }
468 
469  if (time_rebinding > cur_time) {
470  time_rebinding = htonl(time_rebinding - cur_time);
471 
472  if (!add_option(options,
474  &time_rebinding,
475  sizeof(time_rebinding))) {
476  option_state_dereference(&options, MDL);
477  lease_dereference(&lease, MDL);
478  log_info("%s: out of memory, no reply sent",
479  msgbuf);
480  return;
481  }
482  }
483 
484  if (lease->ends > cur_time) {
485  time_expiry = htonl(lease->ends - cur_time);
486 
487  if (!add_option(options,
489  &time_expiry,
490  sizeof(time_expiry))) {
491  option_state_dereference(&options, MDL);
492  lease_dereference(&lease, MDL);
493  log_info("%s: out of memory, no reply sent",
494  msgbuf);
495  return;
496  }
497  }
498 
499  /* Supply the Vendor-Class-Identifier. */
500  if (lease->scope != NULL) {
501  struct data_string vendor_class;
502 
503  memset(&vendor_class, 0, sizeof(vendor_class));
504 
505  if (find_bound_string(&vendor_class, lease->scope,
506  "vendor-class-identifier")) {
507  if (!add_option(options,
509  (void *)vendor_class.data,
510  vendor_class.len)) {
511  option_state_dereference(&options,
512  MDL);
513  lease_dereference(&lease, MDL);
514  log_error("%s: error adding vendor "
515  "class identifier, no reply "
516  "sent", msgbuf);
517  data_string_forget(&vendor_class, MDL);
518  return;
519  }
520  data_string_forget(&vendor_class, MDL);
521  }
522  }
523 
524  /*
525  * Set the relay agent info.
526  *
527  * Note that because agent info is appended without regard
528  * to the PRL in cons_options(), this will be sent as the
529  * last option in the packet whether it is listed on PRL or
530  * not.
531  */
532 
533  if (lease->agent_options != NULL) {
534  int idx = agent_universe.index;
535  struct option_chain_head **tmp1 =
536  (struct option_chain_head **)
537  &(options->universes[idx]);
538  struct option_chain_head *tmp2 =
539  (struct option_chain_head *)
540  lease->agent_options;
541 
542  option_chain_head_reference(tmp1, tmp2, MDL);
543  }
544 
545  /*
546  * Set the client last transaction time.
547  * We check to make sure we have a timestamp. For
548  * lease files that were saved before running a
549  * timestamp-aware version of the server, this may
550  * not be set.
551  */
552 
553  if (lease->cltt != MIN_TIME) {
554  if (cur_time > lease->cltt) {
555  client_last_transaction_time =
556  htonl(cur_time - lease->cltt);
557  } else {
558  client_last_transaction_time = htonl(0);
559  }
560  if (!add_option(options,
562  &client_last_transaction_time,
563  sizeof(client_last_transaction_time))) {
564  option_state_dereference(&options, MDL);
565  lease_dereference(&lease, MDL);
566  log_info("%s: out of memory, no reply sent",
567  msgbuf);
568  return;
569  }
570  }
571 
572  /*
573  * Set associated IPs, if requested and there are some.
574  */
575  if (want_associated_ip && (assoc_ip_cnt > 0)) {
576  if (!add_option(options,
578  assoc_ips,
579  assoc_ip_cnt * sizeof(assoc_ips[0]))) {
580  option_state_dereference(&options, MDL);
581  lease_dereference(&lease, MDL);
582  log_info("%s: out of memory, no reply sent",
583  msgbuf);
584  return;
585  }
586  }
587  }
588 
589  /*
590  * Set the message type.
591  */
592 
593  packet->raw->op = BOOTREPLY;
594 
595  /*
596  * Set DHCP message type.
597  */
598  if (!add_option(options,
600  &dhcpMsgType,
601  sizeof(dhcpMsgType))) {
602  option_state_dereference(&options, MDL);
603  lease_dereference(&lease, MDL);
604  log_info("%s: error adding option, no reply sent", msgbuf);
605  return;
606  }
607 
608  /*
609  * Log the message we've received.
610  */
611  log_info("%s", msgbuf);
612 
613  /*
614  * Figure out which address to use to send from.
615  */
616  get_server_source_address(&siaddr, options, options, packet);
617 
618  /*
619  * Set up the option buffer.
620  */
621 
622  memset(&prl, 0, sizeof(prl));
623  oc = lookup_option(&dhcp_universe, options,
625  if (oc != NULL) {
626  evaluate_option_cache(&prl,
627  packet,
628  NULL,
629  NULL,
630  packet->options,
631  options,
632  &global_scope,
633  oc,
634  MDL);
635  }
636  if (prl.len > 0) {
637  prl_ptr = &prl;
638  } else {
639  prl_ptr = NULL;
640  }
641 
642  packet->packet_length = cons_options(packet,
643  packet->raw,
644  lease,
645  NULL,
646  0,
647  packet->options,
648  options,
649  &global_scope,
650  0,
651  0,
652  0,
653  prl_ptr,
654  NULL);
655 
656  data_string_forget(&prl, MDL); /* SK: safe, even if empty */
657  option_state_dereference(&options, MDL);
658  lease_dereference(&lease, MDL);
659 
660  to.sin_family = AF_INET;
661 #ifdef HAVE_SA_LEN
662  to.sin_len = sizeof(to);
663 #endif
664  memset(to.sin_zero, 0, sizeof(to.sin_zero));
665 
666 #if defined(RELAY_PORT)
667  relay_port = dhcp_check_relayport(packet);
668 #endif
669 
670  /*
671  * Leasequery packets are be sent to the gateway address.
672  */
673  to.sin_addr = packet->raw->giaddr;
674  if (packet->raw->giaddr.s_addr != htonl(INADDR_LOOPBACK)) {
675 #if defined(RELAY_PORT)
676  to.sin_port = relay_port ? relay_port : local_port;
677 #else
678  to.sin_port = local_port;
679 #endif
680  } else {
681  to.sin_port = remote_port; /* XXXSK: For debugging. */
682  }
683 
684  /*
685  * The fallback_interface lets us send with a real IP
686  * address. The packet interface sends from all-zeros.
687  */
688  if (fallback_interface != NULL) {
689  interface = fallback_interface;
690  } else {
691  interface = packet->interface;
692  }
693 
694  /*
695  * Report what we're sending.
696  */
697  log_info("%s to %s for %s (%d associated IPs)",
698  dhcp_msg_type_name,
699  inet_ntoa(to.sin_addr), dbg_info, assoc_ip_cnt);
700 
701  send_packet(interface,
702  NULL,
703  packet->raw,
704  packet->packet_length,
705  siaddr,
706  &to,
707  NULL);
708 }
709 
710 #ifdef DHCPv6
711 
712 /*
713  * TODO: RFC5007 query-by-clientid.
714  *
715  * TODO: RFC5007 look at the pools according to the link-address.
716  *
717  * TODO: get fixed leases too.
718  *
719  * TODO: RFC5007 ORO in query-options.
720  *
721  * TODO: RFC5007 lq-relay-data.
722  *
723  * TODO: RFC5007 lq-client-link.
724  *
725  * Note: the code is still nearly compliant and usable for the target
726  * case with these missing features!
727  */
728 
729 /*
730  * The structure to handle a leasequery.
731  */
732 struct lq6_state {
733  struct packet *packet;
734  struct data_string client_id;
735  struct data_string server_id;
736  struct data_string lq_query;
737  uint8_t query_type;
738  struct in6_addr link_addr;
739  struct option_state *query_opts;
740 
741  struct option_state *reply_opts;
742  unsigned cursor;
743  union reply_buffer {
744  unsigned char data[65536];
745  struct dhcpv6_packet reply;
746  } buf;
747 };
748 
749 /*
750  * Options that we want to send.
751  */
752 static const int required_opts_lq[] = {
753  D6O_CLIENTID,
754  D6O_SERVERID,
759  0
760 };
761 static const int required_opt_CLIENT_DATA[] = {
762  D6O_CLIENTID,
763  D6O_IAADDR,
764  D6O_IAPREFIX,
765  D6O_CLT_TIME,
766  0
767 };
768 
769 /*
770  * Get the lq-query option from the packet.
771  */
772 static isc_result_t
773 get_lq_query(struct lq6_state *lq)
774 {
775  struct data_string *lq_query = &lq->lq_query;
776  struct packet *packet = lq->packet;
777  struct option_cache *oc;
778 
779  /*
780  * Verify our lq_query structure is empty.
781  */
782  if ((lq_query->data != NULL) || (lq_query->len != 0)) {
783  return DHCP_R_INVALIDARG;
784  }
785 
787  if (oc == NULL) {
788  return ISC_R_NOTFOUND;
789  }
790 
791  if (!evaluate_option_cache(lq_query, packet, NULL, NULL,
792  packet->options, NULL,
793  &global_scope, oc, MDL)) {
794  return ISC_R_FAILURE;
795  }
796 
797  return ISC_R_SUCCESS;
798 }
799 
800 /*
801  * Message validation, RFC 5007 section 4.2.1:
802  * dhcpv6.c:valid_client_msg() - unicast + lq-query option.
803  */
804 static int
805 valid_query_msg(struct lq6_state *lq) {
806  struct packet *packet = lq->packet;
807  int ret_val = 0;
808  struct option_cache *oc;
809 
810  /* INSIST((lq != NULL) || (packet != NULL)); */
811 
812  switch (get_client_id(packet, &lq->client_id)) {
813  case ISC_R_SUCCESS:
814  break;
815  case ISC_R_NOTFOUND:
816  log_debug("Discarding %s from %s; "
817  "client identifier missing",
819  piaddr(packet->client_addr));
820  goto exit;
821  default:
822  log_error("Error processing %s from %s; "
823  "unable to evaluate Client Identifier",
825  piaddr(packet->client_addr));
826  goto exit;
827  }
828 
830  if (oc != NULL) {
831  if (evaluate_option_cache(&lq->server_id, packet, NULL, NULL,
832  packet->options, NULL,
833  &global_scope, oc, MDL)) {
834  log_debug("Discarding %s from %s; "
835  "server identifier found "
836  "(CLIENTID %s, SERVERID %s)",
838  piaddr(packet->client_addr),
839  print_hex_1(lq->client_id.len,
840  lq->client_id.data, 60),
841  print_hex_2(lq->server_id.len,
842  lq->server_id.data, 60));
843  } else {
844  log_debug("Discarding %s from %s; "
845  "server identifier found "
846  "(CLIENTID %s)",
848  print_hex_1(lq->client_id.len,
849  lq->client_id.data, 60),
850  piaddr(packet->client_addr));
851  }
852  goto exit;
853  }
854 
855  switch (get_lq_query(lq)) {
856  case ISC_R_SUCCESS:
857  break;
858  case ISC_R_NOTFOUND:
859  log_debug("Discarding %s from %s; lq-query missing",
861  piaddr(packet->client_addr));
862  goto exit;
863  default:
864  log_error("Error processing %s from %s; "
865  "unable to evaluate LQ-Query",
867  piaddr(packet->client_addr));
868  goto exit;
869  }
870 
871  /* looks good */
872  ret_val = 1;
873 
874 exit:
875  if (!ret_val) {
876  if (lq->client_id.len > 0) {
877  data_string_forget(&lq->client_id, MDL);
878  }
879  if (lq->server_id.len > 0) {
880  data_string_forget(&lq->server_id, MDL);
881  }
882  if (lq->lq_query.len > 0) {
883  data_string_forget(&lq->lq_query, MDL);
884  }
885  }
886  return ret_val;
887 }
888 
889 /*
890  * Set an error in a status-code option (from set_status_code).
891  */
892 static int
893 set_error(struct lq6_state *lq, u_int16_t code, const char *message) {
894  struct data_string d;
895  int ret_val;
896 
897  memset(&d, 0, sizeof(d));
898  d.len = sizeof(code) + strlen(message);
899  if (!buffer_allocate(&d.buffer, d.len, MDL)) {
900  log_fatal("set_error: no memory for status code.");
901  }
902  d.data = d.buffer->data;
903  putUShort(d.buffer->data, code);
904  memcpy(d.buffer->data + sizeof(code), message, d.len - sizeof(code));
905  if (!save_option_buffer(&dhcpv6_universe, lq->reply_opts,
906  d.buffer, (unsigned char *)d.data, d.len,
907  D6O_STATUS_CODE, 0)) {
908  log_error("set_error: error saving status code.");
909  ret_val = 0;
910  } else {
911  ret_val = 1;
912  }
913  data_string_forget(&d, MDL);
914  return ret_val;
915 }
916 
917 /*
918  * Process a by-address lease query.
919  */
920 static int
921 process_lq_by_address(struct lq6_state *lq) {
922  struct packet *packet = lq->packet;
923  struct option_cache *oc;
924  struct ipv6_pool *pool = NULL;
925  struct data_string data;
926  struct in6_addr addr;
927  struct iasubopt *iaaddr = NULL;
928  struct option_state *opt_state = NULL;
929  u_int32_t lifetime;
930  unsigned opt_cursor;
931  int ret_val = 0;
932 
933  /*
934  * Get the IAADDR.
935  */
936  oc = lookup_option(&dhcpv6_universe, lq->query_opts, D6O_IAADDR);
937  if (oc == NULL) {
938  if (!set_error(lq, STATUS_MalformedQuery,
939  "No OPTION_IAADDR.")) {
940  log_error("process_lq_by_address: unable "
941  "to set MalformedQuery status code.");
942  return 0;
943  }
944  return 1;
945  }
946  memset(&data, 0, sizeof(data));
947  if (!evaluate_option_cache(&data, packet,
948  NULL, NULL,
949  lq->query_opts, NULL,
950  &global_scope, oc, MDL) ||
951  (data.len < IAADDR_OFFSET)) {
952  log_error("process_lq_by_address: error evaluating IAADDR.");
953  goto exit;
954  }
955  memcpy(&addr, data.data, sizeof(addr));
956  data_string_forget(&data, MDL);
957 
958  /*
959  * Find the lease.
960  * Note the RFC 5007 says to use the link-address to find the link
961  * or the ia-aadr when it is :: but in any case the ia-addr has
962  * to be on the link, so we ignore the link-address here.
963  */
964  if (find_ipv6_pool(&pool, D6O_IA_NA, &addr) != ISC_R_SUCCESS) {
965  if (!set_error(lq, STATUS_NotConfigured,
966  "Address not in a pool.")) {
967  log_error("process_lq_by_address: unable "
968  "to set NotConfigured status code.");
969  goto exit;
970  }
971  ret_val = 1;
972  goto exit;
973  }
974  if (iasubopt_hash_lookup(&iaaddr, pool->leases, &addr,
975  sizeof(addr), MDL) == 0) {
976  ret_val = 1;
977  goto exit;
978  }
979  if ((iaaddr == NULL) || (iaaddr->state != FTS_ACTIVE) ||
980  (iaaddr->ia == NULL) || (iaaddr->ia->iaid_duid.len <= 4)) {
981  ret_val = 1;
982  goto exit;
983  }
984 
985  /*
986  * Build the client-data option (with client-id, ia-addr and clt-time).
987  */
988  if (!option_state_allocate(&opt_state, MDL)) {
989  log_error("process_lq_by_address: "
990  "no memory for option state.");
991  goto exit;
992  }
993 
994  data_string_copy(&data, &iaaddr->ia->iaid_duid, MDL);
995  data.data += 4;
996  data.len -= 4;
997  if (!save_option_buffer(&dhcpv6_universe, opt_state,
998  NULL, (unsigned char *)data.data, data.len,
999  D6O_CLIENTID, 0)) {
1000  log_error("process_lq_by_address: error saving client ID.");
1001  goto exit;
1002  }
1003  data_string_forget(&data, MDL);
1004 
1005  data.len = IAADDR_OFFSET;
1006  if (!buffer_allocate(&data.buffer, data.len, MDL)) {
1007  log_error("process_lq_by_address: no memory for ia-addr.");
1008  goto exit;
1009  }
1010  data.data = data.buffer->data;
1011  memcpy(data.buffer->data, &iaaddr->addr, 16);
1012  lifetime = iaaddr->prefer;
1013  putULong(data.buffer->data + 16, lifetime);
1014  lifetime = iaaddr->valid;
1015  putULong(data.buffer->data + 20, lifetime);
1016  if (!save_option_buffer(&dhcpv6_universe, opt_state,
1017  NULL, (unsigned char *)data.data, data.len,
1018  D6O_IAADDR, 0)) {
1019  log_error("process_lq_by_address: error saving ia-addr.");
1020  goto exit;
1021  }
1022  data_string_forget(&data, MDL);
1023 
1024  lifetime = htonl(iaaddr->ia->cltt);
1025  if (!save_option_buffer(&dhcpv6_universe, opt_state,
1026  NULL, (unsigned char *)&lifetime, 4,
1027  D6O_CLT_TIME, 0)) {
1028  log_error("process_lq_by_address: error saving clt time.");
1029  goto exit;
1030  }
1031 
1032  /*
1033  * Store the client-data option.
1034  */
1035  opt_cursor = lq->cursor;
1036  putUShort(lq->buf.data + lq->cursor, (unsigned)D6O_CLIENT_DATA);
1037  lq->cursor += 2;
1038  /* Skip option length. */
1039  lq->cursor += 2;
1040 
1041  lq->cursor += store_options6((char *)lq->buf.data + lq->cursor,
1042  sizeof(lq->buf) - lq->cursor,
1043  opt_state, lq->packet,
1044  required_opt_CLIENT_DATA, NULL);
1045  /* Reset the length. */
1046  putUShort(lq->buf.data + opt_cursor + 2,
1047  lq->cursor - (opt_cursor + 4));
1048 
1049  /* Done. */
1050  ret_val = 1;
1051 
1052  exit:
1053  if (data.data != NULL)
1054  data_string_forget(&data, MDL);
1055  if (pool != NULL)
1056  ipv6_pool_dereference(&pool, MDL);
1057  if (iaaddr != NULL)
1058  iasubopt_dereference(&iaaddr, MDL);
1059  if (opt_state != NULL)
1060  option_state_dereference(&opt_state, MDL);
1061  return ret_val;
1062 }
1063 
1064 
1065 /*
1066  * Process a lease query.
1067  */
1068 void
1069 dhcpv6_leasequery(struct data_string *reply_ret, struct packet *packet) {
1070  static struct lq6_state lq;
1071  struct option_cache *oc;
1072  int allow_lq;
1073 
1074  /*
1075  * Initialize the lease query state.
1076  */
1077  lq.packet = NULL;
1078  memset(&lq.client_id, 0, sizeof(lq.client_id));
1079  memset(&lq.server_id, 0, sizeof(lq.server_id));
1080  memset(&lq.lq_query, 0, sizeof(lq.lq_query));
1081  lq.query_opts = NULL;
1082  lq.reply_opts = NULL;
1083  packet_reference(&lq.packet, packet, MDL);
1084 
1085  /*
1086  * Validate our input.
1087  */
1088  if (!valid_query_msg(&lq)) {
1089  goto exit;
1090  }
1091 
1092  /*
1093  * Prepare our reply.
1094  */
1095  if (!option_state_allocate(&lq.reply_opts, MDL)) {
1096  log_error("dhcpv6_leasequery: no memory for option state.");
1097  goto exit;
1098  }
1099  execute_statements_in_scope(NULL, lq.packet, NULL, NULL,
1100  lq.packet->options, lq.reply_opts,
1101  &global_scope, root_group, NULL, NULL);
1102 
1103  lq.buf.reply.msg_type = DHCPV6_LEASEQUERY_REPLY;
1104 
1105  memcpy(lq.buf.reply.transaction_id,
1106  lq.packet->dhcpv6_transaction_id,
1107  sizeof(lq.buf.reply.transaction_id));
1108 
1109  /*
1110  * Because LEASEQUERY has some privacy concerns, default to deny.
1111  */
1112  allow_lq = 0;
1113 
1114  /*
1115  * See if we are authorized to do LEASEQUERY.
1116  */
1117  oc = lookup_option(&server_universe, lq.reply_opts, SV_LEASEQUERY);
1118  if (oc != NULL) {
1119  allow_lq = evaluate_boolean_option_cache(NULL,
1120  lq.packet,
1121  NULL, NULL,
1122  lq.packet->options,
1123  lq.reply_opts,
1124  &global_scope,
1125  oc, MDL);
1126  }
1127 
1128  if (!allow_lq) {
1129  log_info("dhcpv6_leasequery: not allowed, query ignored.");
1130  goto exit;
1131  }
1132 
1133  /*
1134  * Same than transmission of REPLY message in RFC 3315:
1135  * server-id
1136  * client-id
1137  */
1138 
1139  oc = lookup_option(&dhcpv6_universe, lq.reply_opts, D6O_SERVERID);
1140  if (oc == NULL) {
1141  /* If not already in options, get from query then global. */
1142  if (lq.server_id.data == NULL)
1143  copy_server_duid(&lq.server_id, MDL);
1145  lq.reply_opts,
1146  NULL,
1147  (unsigned char *)lq.server_id.data,
1148  lq.server_id.len,
1149  D6O_SERVERID,
1150  0)) {
1151  log_error("dhcpv6_leasequery: "
1152  "error saving server identifier.");
1153  goto exit;
1154  }
1155  }
1156 
1158  lq.reply_opts,
1159  lq.client_id.buffer,
1160  (unsigned char *)lq.client_id.data,
1161  lq.client_id.len,
1162  D6O_CLIENTID,
1163  0)) {
1164  log_error("dhcpv6_leasequery: "
1165  "error saving client identifier.");
1166  goto exit;
1167  }
1168 
1169  lq.cursor = 4;
1170 
1171  /*
1172  * Decode the lq-query option.
1173  */
1174 
1175  if (lq.lq_query.len <= LQ_QUERY_OFFSET) {
1176  if (!set_error(&lq, STATUS_MalformedQuery,
1177  "OPTION_LQ_QUERY too short.")) {
1178  log_error("dhcpv6_leasequery: unable "
1179  "to set MalformedQuery status code.");
1180  goto exit;
1181  }
1182  goto done;
1183  }
1184 
1185  lq.query_type = lq.lq_query.data [0];
1186  memcpy(&lq.link_addr, lq.lq_query.data + 1, sizeof(lq.link_addr));
1187  switch (lq.query_type) {
1188  case LQ6QT_BY_ADDRESS:
1189  break;
1190  case LQ6QT_BY_CLIENTID:
1191  if (!set_error(&lq, STATUS_UnknownQueryType,
1192  "QUERY_BY_CLIENTID not supported.")) {
1193  log_error("dhcpv6_leasequery: unable to "
1194  "set UnknownQueryType status code.");
1195  goto exit;
1196  }
1197  goto done;
1198  default:
1199  if (!set_error(&lq, STATUS_UnknownQueryType,
1200  "Unknown query-type.")) {
1201  log_error("dhcpv6_leasequery: unable to "
1202  "set UnknownQueryType status code.");
1203  goto exit;
1204  }
1205  goto done;
1206  }
1207 
1208  if (!option_state_allocate(&lq.query_opts, MDL)) {
1209  log_error("dhcpv6_leasequery: no memory for option state.");
1210  goto exit;
1211  }
1212  if (!parse_option_buffer(lq.query_opts,
1213  lq.lq_query.data + LQ_QUERY_OFFSET,
1214  lq.lq_query.len - LQ_QUERY_OFFSET,
1215  &dhcpv6_universe)) {
1216  log_error("dhcpv6_leasequery: error parsing query-options.");
1217  if (!set_error(&lq, STATUS_MalformedQuery,
1218  "Bad query-options.")) {
1219  log_error("dhcpv6_leasequery: unable "
1220  "to set MalformedQuery status code.");
1221  goto exit;
1222  }
1223  goto done;
1224  }
1225 
1226  /* Do it. */
1227  if (!process_lq_by_address(&lq))
1228  goto exit;
1229 
1230  done:
1231  /* Store the options. */
1232  lq.cursor += store_options6((char *)lq.buf.data + lq.cursor,
1233  sizeof(lq.buf) - lq.cursor,
1234  lq.reply_opts,
1235  lq.packet,
1236  required_opts_lq,
1237  NULL);
1238 
1239  /* Return our reply to the caller. */
1240  reply_ret->len = lq.cursor;
1241  reply_ret->buffer = NULL;
1242  if (!buffer_allocate(&reply_ret->buffer, lq.cursor, MDL)) {
1243  log_fatal("dhcpv6_leasequery: no memory to store Reply.");
1244  }
1245  memcpy(reply_ret->buffer->data, lq.buf.data, lq.cursor);
1246  reply_ret->data = reply_ret->buffer->data;
1247 
1248  exit:
1249  /* Cleanup. */
1250  if (lq.packet != NULL)
1251  packet_dereference(&lq.packet, MDL);
1252  if (lq.client_id.data != NULL)
1253  data_string_forget(&lq.client_id, MDL);
1254  if (lq.server_id.data != NULL)
1255  data_string_forget(&lq.server_id, MDL);
1256  if (lq.lq_query.data != NULL)
1257  data_string_forget(&lq.lq_query, MDL);
1258  if (lq.query_opts != NULL)
1259  option_state_dereference(&lq.query_opts, MDL);
1260  if (lq.reply_opts != NULL)
1261  option_state_dereference(&lq.reply_opts, MDL);
1262 }
1263 
1264 #endif /* DHCPv6 */
#define BOOTREPLY
Definition: dhcp.h:69
return DHCP_R_INVALIDARG
Definition: parse.c:1222
#define D6O_CLT_TIME
Definition: dhcp6.h:75
#define D6O_LQ_CLIENT_LINK
Definition: dhcp6.h:77
#define D6O_IAADDR
Definition: dhcp6.h:34
struct binding_scope * global_scope
Definition: tree.c:38
void dhcpleasequery(struct packet *, int)
Definition: dhcpd.h:560
unsigned len
Definition: tree.h:79
const char * piaddr(const struct iaddr addr)
Definition: inet.c:579
u_int8_t hlen
Definition: dhcpd.h:492
#define D6O_STATUS_CODE
Definition: dhcp6.h:42
unsigned char * uid
Definition: dhcpd.h:585
void dhcpv6_leasequery(struct data_string *, struct packet *)
Definition: dhcpd.h:1061
struct universe server_universe
Definition: stables.c:176
#define MDL
Definition: omapip.h:567
unsigned char iabuf[16]
Definition: inet.h:33
#define print_hex_1(len, data, limit)
Definition: dhcpd.h:2622
#define DHO_DHCP_PARAMETER_REQUEST_LIST
Definition: dhcp.h:146
u_int8_t hlen
Definition: dhcp.h:50
const char * dhcpv6_type_names[]
Definition: tables.c:660
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
#define IAADDR_OFFSET
Definition: dhcp6.h:178
#define DHO_DHCP_LEASE_TIME
Definition: dhcp.h:142
int find_bound_string(struct data_string *value, struct binding_scope *scope, const char *name)
Definition: tree.c:4103
struct universe dhcp_universe
#define D6O_SERVERID
Definition: dhcp6.h:31
return ISC_R_SUCCESS
Definition: parse.c:1341
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1339
struct group * root_group
Definition: memory.c:31
p
Definition: options.c:1628
u_int32_t valid
Definition: dhcpd.h:1639
int log_error(const char *,...) __attribute__((__format__(__printf__
time_t cltt
Definition: dhcpd.h:1671
void copy_server_duid(struct data_string *ds, const char *file, int line)
#define DHO_DHCP_REBINDING_TIME
Definition: dhcp.h:150
unsigned len
Definition: inet.h:32
log_fatal("no memory for uname information.")
#define D6O_CLIENTID
Definition: dhcp6.h:30
#define DHO_ASSOCIATED_IP
Definition: dhcp.h:160
struct option_state * options
Definition: dhcpd.h:449
unsigned char dhcpv6_msg_type
Definition: dhcpd.h:411
int parse_option_buffer(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *universe)
Definition: options.c:117
void get_server_source_address(struct in_addr *from, struct option_state *options, struct option_state *out_options, struct packet *packet)
Definition: dhcp.c:5361
#define DHO_CLIENT_LAST_TRANSACTION_TIME
Definition: dhcp.h:159
#define LQ_QUERY_OFFSET
Definition: dhcp6.h:184
struct dhcp_packet * raw
Definition: dhcpd.h:406
struct hardware hardware_addr
Definition: dhcpd.h:589
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
Definition: dhclient.c:1537
#define D6O_IAPREFIX
Definition: dhcp6.h:55
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:563
u_int8_t htype
Definition: dhcp.h:49
struct interface_info * fallback_interface
Definition: discover.c:42
#define DHCPLEASEACTIVE
Definition: dhcp.h:181
#define STATUS_NotConfigured
Definition: dhcp6.h:133
int option_state_allocate(struct option_state **ptr, const char *file, int line)
Definition: alloc.c:846
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
unsigned char chaddr[16]
Definition: dhcp.h:59
#define MIN_TIME
Definition: dhcpd.h:1616
int packet_reference(struct packet **ptr, struct packet *bp, const char *file, int line)
Definition: alloc.c:1053
Definition: dhcpd.h:1015
binding_state_t binding_state
Definition: dhcpd.h:623
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition: alloc.c:679
#define LQ6QT_BY_ADDRESS
Definition: dhcp6.h:264
struct class * classes[PACKET_MAX_CLASSES]
Definition: dhcpd.h:455
void putULong(unsigned char *, u_int32_t)
Definition: convert.c:70
u_int16_t local_port
Definition: dhclient.c:94
Definition: dhcpd.h:405
int find_lease_by_hw_addr(struct lease **, const unsigned char *, unsigned, const char *, int)
Definition: mdb.c:2044
struct data_string iaid_duid
Definition: dhcpd.h:1667
#define cur_time
Definition: dhcpd.h:2110
struct lease * n_hw
Definition: dhcpd.h:567
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
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:533
struct lease * n_uid
Definition: dhcpd.h:567
int index
Definition: tree.h:339
TIME starts
Definition: dhcpd.h:570
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:2507
int add_option(struct option_state *options, unsigned int option_num, void *data, unsigned int data_len)
Definition: options.c:4394
u_int32_t prefer
Definition: dhcpd.h:1638
int option_chain_head_reference(struct option_chain_head **ptr, struct option_chain_head *bp, const char *file, int line)
Definition: alloc.c:67
#define D6O_LQ_QUERY
Definition: dhcp6.h:73
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition: options.c:2465
iasubopt_hash_t * leases
Definition: dhcpd.h:1705
int int log_info(const char *,...) __attribute__((__format__(__printf__
binding_state_t state
Definition: dhcpd.h:1634
u_int16_t dhcp_check_relayport(struct packet *packet)
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
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *addr)
Definition: mdb6.c:2289
void get_newest_lease(struct lease **retval, struct lease *lease, struct lease *(*next)(const struct lease *))
struct group * group
Definition: dhcpd.h:1071
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:2285
#define DHCPV6_LEASEQUERY_REPLY
Definition: dhcp6.h:154
int struct iaddr * addr
Definition: inet.c:185
TIME cltt
Definition: dhcpd.h:640
isc_result_t get_client_id(struct packet *, struct data_string *)
Definition: inet.h:31
ipv6_pool structure
Definition: dhcpd.h:1699
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:1043
unsigned short uid_len
Definition: dhcpd.h:586
struct iaddr ip_addr
Definition: dhcpd.h:569
struct in_addr giaddr
Definition: dhcp.h:58
int option_state_dereference(struct option_state **ptr, const char *file, int line)
Definition: alloc.c:911
Definition: dhcpd.h:948
#define STATUS_UnknownQueryType
Definition: dhcp6.h:131
struct universe dhcpv6_universe
Definition: tables.c:343
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
#define D6O_IA_NA
Definition: dhcp6.h:32
#define print_hex_2(len, data, limit)
Definition: dhcpd.h:2623
#define LQ6QT_BY_CLIENTID
Definition: dhcp6.h:265
int packet_dereference(struct packet **ptr, const char *file, int line)
Definition: alloc.c:1081
#define STATUS_MalformedQuery
Definition: dhcp6.h:132
#define DHCPLEASEUNASSIGNED
Definition: dhcp.h:179
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
Definition: mdb6.c:261
unsigned char data[1]
Definition: tree.h:62
unsigned code
Definition: parse.c:1219
#define D6O_CLIENT_DATA
Definition: dhcp6.h:74
int find_lease_by_uid(struct lease **, const unsigned char *, unsigned, const char *, int)
Definition: mdb.c:2036
struct option_cache * oc
Definition: options.c:1687
return ISC_R_NOTFOUND
Definition: parse.c:1336
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition: dhcpd.h:493
int class_count
Definition: dhcpd.h:454
struct lease * next
Definition: dhcpd.h:562
#define DHO_VENDOR_CLASS_IDENTIFIER
Definition: dhcp.h:151
struct iaddr client_addr
Definition: dhcpd.h:432
struct universe agent_universe
Definition: stables.c:165
struct ia_xx * ia
Definition: dhcpd.h:1640
u_int16_t remote_port
Definition: dhclient.c:95
#define DHO_DHCP_RENEWAL_TIME
Definition: dhcp.h:149
u_int16_t relay_port
Definition: discover.c:47
#define DHO_DHCP_CLIENT_IDENTIFIER
Definition: dhcp.h:152
void putUShort(unsigned char *, u_int32_t)
Definition: convert.c:86
#define DHCPLEASEUNKNOWN
Definition: dhcp.h:180
struct in6_addr addr
Definition: dhcpd.h:1632
void * universes[1]
Definition: dhcpd.h:401
const unsigned char * data
Definition: tree.h:78
struct in_addr ciaddr
Definition: dhcp.h:55
#define DHO_DHCP_MESSAGE_TYPE
Definition: dhcp.h:144
TIME ends
Definition: dhcpd.h:570
struct binding_scope * scope
Definition: dhcpd.h:575
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition: alloc.c:1323
unsigned packet_length
Definition: dhcpd.h:408
#define D6O_LQ_RELAY_DATA
Definition: dhcp6.h:76
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
Definition: mdb.c:2029
u_int8_t op
Definition: dhcp.h:48
#define SV_LEASEQUERY
Definition: dhcpd.h:759
struct buffer * buffer
Definition: tree.h:77
struct group * group
Definition: dhcpd.h:1115
struct option_chain_head * agent_options
Definition: dhcpd.h:580
#define FTS_ACTIVE
Definition: dhcpd.h:538