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