ISC DHCP  4.3.0
A reference DHCPv4 and DHCPv6 implementation
discover.c
Go to the documentation of this file.
1 /* discover.c
2 
3  Find and identify the network interfaces. */
4 
5 /*
6  * Copyright (c) 2013-2014 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 2004-2009,2011 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1995-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Internet Systems Consortium, Inc.
23  * 950 Charter Street
24  * Redwood City, CA 94063
25  * <info@isc.org>
26  * https://www.isc.org/
27  *
28  */
29 
30 #include "dhcpd.h"
31 
32 #define BSD_COMP /* needed on Solaris for SIOCGLIFNUM */
33 #include <sys/ioctl.h>
34 #include <errno.h>
35 
36 #ifdef HAVE_NET_IF6_H
37 # include <net/if6.h>
38 #endif
39 
43 u_int16_t local_port;
44 u_int16_t remote_port;
47 isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *);
49 
50 struct in_addr limited_broadcast;
51 
52 int local_family = AF_INET;
53 struct in_addr local_address;
54 
56  struct dhcp_packet *, unsigned,
57  unsigned int,
58  struct iaddr, struct hardware *);
59 
60 #ifdef DHCPv6
61 void (*dhcpv6_packet_handler)(struct interface_info *,
62  const char *, int,
63  int, const struct iaddr *,
64  isc_boolean_t);
65 #endif /* DHCPv6 */
66 
67 
69 #if defined (TRACING)
73 #endif
77 
78 OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface)
79 
80 isc_result_t interface_setup ()
81 {
82  isc_result_t status;
83  status = omapi_object_type_register (&dhcp_type_interface,
84  "interface",
93  0, 0, 0,
94  sizeof (struct interface_info),
96  if (status != ISC_R_SUCCESS)
97  log_fatal ("Can't register interface object type: %s",
98  isc_result_totext (status));
99 
100  return status;
101 }
102 
103 #if defined (TRACING)
104 void interface_trace_setup ()
105 {
106  interface_trace = trace_type_register ("interface", (void *)0,
109  inpacket_trace = trace_type_register ("inpacket", (void *)0,
112  outpacket_trace = trace_type_register ("outpacket", (void *)0,
115 }
116 #endif
117 
119  const char *file, int line)
120 {
121  struct interface_info *ip = (struct interface_info *)ipo;
122  ip -> rfdesc = ip -> wfdesc = -1;
123  return ISC_R_SUCCESS;
124 }
125 
126 
127 /*
128  * Scanning for Interfaces
129  * -----------------------
130  *
131  * To find interfaces, we create an iterator that abstracts out most
132  * of the platform specifics. Use is fairly straightforward:
133  *
134  * - begin_iface_scan() starts the process.
135  * - Use next_iface() until it returns 0.
136  * - end_iface_scan() performs any necessary cleanup.
137  *
138  * We check for errors on each call to next_iface(), which returns a
139  * description of the error as a string if any occurs.
140  *
141  * We currently have code for Solaris and Linux. Other systems need
142  * to have code written.
143  *
144  * NOTE: the long-term goal is to use the interface code from BIND 9.
145  */
146 
147 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && defined(SIOCGLIFFLAGS)
148 
149 /* HP/UX doesn't define struct lifconf, instead they define struct
150  * if_laddrconf. Similarly, 'struct lifreq' and 'struct lifaddrreq'.
151  */
152 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
153 # define lifc_len iflc_len
154 # define lifc_buf iflc_buf
155 # define lifc_req iflc_req
156 # define LIFCONF if_laddrconf
157 #else
158 # define ISC_HAVE_LIFC_FAMILY 1
159 # define ISC_HAVE_LIFC_FLAGS 1
160 # define LIFCONF lifconf
161 #endif
162 
163 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
164 # define lifr_addr iflr_addr
165 # define lifr_name iflr_name
166 # define lifr_dstaddr iflr_dstaddr
167 # define lifr_flags iflr_flags
168 # define sockaddr_storage sockaddr_ext
169 # define ss_family sa_family
170 # define LIFREQ if_laddrreq
171 #else
172 # define LIFREQ lifreq
173 #endif
174 
175 #ifndef IF_NAMESIZE
176 # if defined(LIFNAMSIZ)
177 # define IF_NAMESIZE LIFNAMSIZ
178 # elif defined(IFNAMSIZ)
179 # define IF_NAMESIZE IFNAMSIZ
180 # else
181 # define IF_NAMESIZE 16
182 # endif
183 #endif
184 #elif !defined(__linux) && !defined(HAVE_IFADDRS_H)
185 # define SIOCGLIFCONF SIOCGIFCONF
186 # define SIOCGLIFFLAGS SIOCGIFFLAGS
187 # define LIFREQ ifreq
188 # define LIFCONF ifconf
189 # define lifr_name ifr_name
190 # define lifr_addr ifr_addr
191 # define lifr_flags ifr_flags
192 # define lifc_len ifc_len
193 # define lifc_buf ifc_buf
194 # define lifc_req ifc_req
195 #ifdef _AIX
196 # define ss_family __ss_family
197 #endif
198 #endif
199 
200 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
201 /*
202  * Solaris support
203  * ---------------
204  *
205  * The SIOCGLIFCONF ioctl() are the extension that you need to use
206  * on Solaris to get information about IPv6 addresses.
207  *
208  * Solaris' extended interface is documented in the if_tcp man page.
209  */
210 
211 /*
212  * Structure holding state about the scan.
213  */
215  int sock; /* file descriptor used to get information */
216  int num; /* total number of interfaces */
217  struct LIFCONF conf; /* structure used to get information */
218  int next; /* next interface to retrieve when iterating */
219 };
220 
221 /*
222  * Structure used to return information about a specific interface.
223  */
224 struct iface_info {
225  char name[IF_NAMESIZE+1]; /* name of the interface, e.g. "bge0" */
226  struct sockaddr_storage addr; /* address information */
227  isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */
228 };
229 
230 /*
231  * Start a scan of interfaces.
232  *
233  * The iface_conf_list structure maintains state for this process.
234  */
235 int
237 #ifdef ISC_PLATFORM_HAVELIFNUM
238  struct lifnum lifnum;
239 #else
240  int lifnum;
241 #endif
242 
243  ifaces->sock = socket(local_family, SOCK_DGRAM, IPPROTO_UDP);
244  if (ifaces->sock < 0) {
245  log_error("Error creating socket to list interfaces; %m");
246  return 0;
247  }
248 
249  memset(&lifnum, 0, sizeof(lifnum));
250 #ifdef ISC_PLATFORM_HAVELIFNUM
251  lifnum.lifn_family = AF_UNSPEC;
252 #endif
253 #ifdef SIOCGLIFNUM
254  if (ioctl(ifaces->sock, SIOCGLIFNUM, &lifnum) < 0) {
255  log_error("Error finding total number of interfaces; %m");
256  close(ifaces->sock);
257  ifaces->sock = -1;
258  return 0;
259  }
260 
261 #ifdef ISC_PLATFORM_HAVELIFNUM
262  ifaces->num = lifnum.lifn_count;
263 #else
264  ifaces->num = lifnum;
265 #endif
266 #else
267  ifaces->num = 64;
268 #endif /* SIOCGLIFNUM */
269 
270  memset(&ifaces->conf, 0, sizeof(ifaces->conf));
271 #ifdef ISC_HAVE_LIFC_FAMILY
272  ifaces->conf.lifc_family = AF_UNSPEC;
273 #endif
274  ifaces->conf.lifc_len = ifaces->num * sizeof(struct LIFREQ);
275  ifaces->conf.lifc_buf = dmalloc(ifaces->conf.lifc_len, MDL);
276  if (ifaces->conf.lifc_buf == NULL) {
277  log_fatal("Out of memory getting interface list.");
278  }
279 
280  if (ioctl(ifaces->sock, SIOCGLIFCONF, &ifaces->conf) < 0) {
281  log_error("Error getting interfaces configuration list; %m");
282  dfree(ifaces->conf.lifc_buf, MDL);
283  close(ifaces->sock);
284  ifaces->sock = -1;
285  return 0;
286  }
287 
288  ifaces->next = 0;
289 
290  return 1;
291 }
292 
293 /*
294  * Retrieve the next interface.
295  *
296  * Returns information in the info structure.
297  * Sets err to 1 if there is an error, otherwise 0.
298  */
299 int
300 next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
301  struct LIFREQ *p;
302  struct LIFREQ tmp;
303  isc_boolean_t foundif;
304 #if defined(sun) || defined(__linux)
305  /* Pointer used to remove interface aliases. */
306  char *s;
307 #endif
308 
309  do {
310  foundif = ISC_FALSE;
311 
312  if (ifaces->next >= ifaces->num) {
313  *err = 0;
314  return 0;
315  }
316 
317  p = ifaces->conf.lifc_req;
318  p += ifaces->next;
319 
320  if (strlen(p->lifr_name) >= sizeof(info->name)) {
321  *err = 1;
322  log_error("Interface name '%s' too long", p->lifr_name);
323  return 0;
324  }
325 
326  /* Reject if interface address family does not match */
327  if (p->lifr_addr.ss_family != local_family) {
328  ifaces->next++;
329  continue;
330  }
331 
332  strcpy(info->name, p->lifr_name);
333  memset(&info->addr, 0, sizeof(info->addr));
334  memcpy(&info->addr, &p->lifr_addr, sizeof(p->lifr_addr));
335 
336 #if defined(sun) || defined(__linux)
337  /* interface aliases look like "eth0:1" or "wlan1:3" */
338  s = strchr(info->name, ':');
339  if (s != NULL) {
340  *s = '\0';
341  }
342 #endif /* defined(sun) || defined(__linux) */
343 
344  foundif = ISC_TRUE;
345  } while ((foundif == ISC_FALSE) ||
346  (strncmp(info->name, "dummy", 5) == 0));
347 
348  memset(&tmp, 0, sizeof(tmp));
349  strcpy(tmp.lifr_name, info->name);
350  if (ioctl(ifaces->sock, SIOCGLIFFLAGS, &tmp) < 0) {
351  log_error("Error getting interface flags for '%s'; %m",
352  p->lifr_name);
353  *err = 1;
354  return 0;
355  }
356  info->flags = tmp.lifr_flags;
357 
358  ifaces->next++;
359  *err = 0;
360  return 1;
361 }
362 
363 /*
364  * End scan of interfaces.
365  */
366 void
368  dfree(ifaces->conf.lifc_buf, MDL);
369  close(ifaces->sock);
370  ifaces->sock = -1;
371 }
372 
373 #else
374 
375 /*
376  * BSD support
377  * -----------
378  *
379  * FreeBSD, NetBSD, OpenBSD, OS X and Linux all have the getifaddrs()
380  * function.
381  *
382  * The getifaddrs() man page describes the use.
383  */
384 
385 #include <ifaddrs.h>
386 
387 /*
388  * Structure holding state about the scan.
389  */
390 struct iface_conf_list {
391  struct ifaddrs *head; /* beginning of the list */
392  struct ifaddrs *next; /* current position in the list */
393 };
394 
395 /*
396  * Structure used to return information about a specific interface.
397  */
398 struct iface_info {
399  char name[IFNAMSIZ]; /* name of the interface, e.g. "bge0" */
400  struct sockaddr_storage addr; /* address information */
401  isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */
402 };
403 
404 /*
405  * Start a scan of interfaces.
406  *
407  * The iface_conf_list structure maintains state for this process.
408  */
409 int
410 begin_iface_scan(struct iface_conf_list *ifaces) {
411  if (getifaddrs(&ifaces->head) != 0) {
412  log_error("Error getting interfaces; %m");
413  return 0;
414  }
415  ifaces->next = ifaces->head;
416  return 1;
417 }
418 
419 /*
420  * Retrieve the next interface.
421  *
422  * Returns information in the info structure.
423  * Sets err to 1 if there is an error, otherwise 0.
424  */
425 int
426 next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
427  size_t sa_len = 0;
428 
429  if (ifaces->next == NULL) {
430  *err = 0;
431  return 0;
432  }
433  if (strlen(ifaces->next->ifa_name) >= sizeof(info->name)) {
434  log_error("Interface name '%s' too long",
435  ifaces->next->ifa_name);
436  *err = 1;
437  return 0;
438  }
439  strcpy(info->name, ifaces->next->ifa_name);
440 
441  memset(&info->addr, 0 , sizeof(info->addr));
442 
443  if (ifaces->next->ifa_addr != NULL) {
444 #ifdef HAVE_SA_LEN
445  sa_len = ifaces->next->ifa_addr->sa_len;
446 #else
447  if (ifaces->next->ifa_addr->sa_family == AF_INET)
448  sa_len = sizeof(struct sockaddr_in);
449  else if (ifaces->next->ifa_addr->sa_family == AF_INET6)
450  sa_len = sizeof(struct sockaddr_in6);
451 #endif
452  memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
453  }
454  info->flags = ifaces->next->ifa_flags;
455  ifaces->next = ifaces->next->ifa_next;
456  *err = 0;
457  return 1;
458 }
459 
460 /*
461  * End scan of interfaces.
462  */
463 void
464 end_iface_scan(struct iface_conf_list *ifaces) {
465  freeifaddrs(ifaces->head);
466  ifaces->head = NULL;
467  ifaces->next = NULL;
468 }
469 #endif
470 
471 /* XXX: perhaps create drealloc() rather than do it manually */
472 void
474  const struct in_addr *addr) {
475  /*
476  * We don't expect a lot of addresses per IPv4 interface, so
477  * we use 4, as our "chunk size" for collecting addresses.
478  */
479  if (iface->addresses == NULL) {
480  iface->addresses = dmalloc(4 * sizeof(struct in_addr), MDL);
481  if (iface->addresses == NULL) {
482  log_fatal("Out of memory saving IPv4 address "
483  "on interface.");
484  }
485  iface->address_count = 0;
486  iface->address_max = 4;
487  } else if (iface->address_count >= iface->address_max) {
488  struct in_addr *tmp;
489  int new_max;
490 
491  new_max = iface->address_max + 4;
492  tmp = dmalloc(new_max * sizeof(struct in_addr), MDL);
493  if (tmp == NULL) {
494  log_fatal("Out of memory saving IPv4 address "
495  "on interface.");
496  }
497  memcpy(tmp,
498  iface->addresses,
499  iface->address_max * sizeof(struct in_addr));
500  dfree(iface->addresses, MDL);
501  iface->addresses = tmp;
502  iface->address_max = new_max;
503  }
504  iface->addresses[iface->address_count++] = *addr;
505 }
506 
507 #ifdef DHCPv6
508 /* XXX: perhaps create drealloc() rather than do it manually */
509 void
510 add_ipv6_addr_to_interface(struct interface_info *iface,
511  const struct in6_addr *addr) {
512  /*
513  * Each IPv6 interface will have at least two IPv6 addresses,
514  * and likely quite a few more. So we use 8, as our "chunk size" for
515  * collecting addresses.
516  */
517  if (iface->v6addresses == NULL) {
518  iface->v6addresses = dmalloc(8 * sizeof(struct in6_addr), MDL);
519  if (iface->v6addresses == NULL) {
520  log_fatal("Out of memory saving IPv6 address "
521  "on interface.");
522  }
523  iface->v6address_count = 0;
524  iface->v6address_max = 8;
525  } else if (iface->v6address_count >= iface->v6address_max) {
526  struct in6_addr *tmp;
527  int new_max;
528 
529  new_max = iface->v6address_max + 8;
530  tmp = dmalloc(new_max * sizeof(struct in6_addr), MDL);
531  if (tmp == NULL) {
532  log_fatal("Out of memory saving IPv6 address "
533  "on interface.");
534  }
535  memcpy(tmp,
536  iface->v6addresses,
537  iface->v6address_max * sizeof(struct in6_addr));
538  dfree(iface->v6addresses, MDL);
539  iface->v6addresses = tmp;
540  iface->v6address_max = new_max;
541  }
542  iface->v6addresses[iface->v6address_count++] = *addr;
543 }
544 #endif /* DHCPv6 */
545 
546 /* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
547  For each interface that's of type INET and not the loopback interface,
548  register that interface with the network I/O software, figure out what
549  subnet it's on, and add it to the list of interfaces. */
550 
551 void
553  struct iface_conf_list ifaces;
554  struct iface_info info;
555  int err;
556 
557  struct interface_info *tmp;
558  struct interface_info *last, *next;
559 
560 #ifdef DHCPv6
561  char abuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
562 #endif /* DHCPv6 */
563 
564 
565  struct subnet *subnet;
566  int ir;
567  isc_result_t status;
568  int wifcount = 0;
569 
570  static int setup_fallback = 0;
571 
572  if (!begin_iface_scan(&ifaces)) {
573  log_fatal("Can't get list of interfaces.");
574  }
575 
576  /* If we already have a list of interfaces, and we're running as
577  a DHCP server, the interfaces were requested. */
578  if (interfaces && (state == DISCOVER_SERVER ||
579  state == DISCOVER_RELAY ||
580  state == DISCOVER_REQUESTED))
581  ir = 0;
582  else if (state == DISCOVER_UNCONFIGURED)
584  else
585  ir = INTERFACE_REQUESTED;
586 
587  /* Cycle through the list of interfaces looking for IP addresses. */
588  while (next_iface(&info, &err, &ifaces)) {
589 
590  /* See if we've seen an interface that matches this one. */
591  for (tmp = interfaces; tmp; tmp = tmp->next) {
592  if (!strcmp(tmp->name, info.name))
593  break;
594  }
595 
596  /* Skip non broadcast interfaces (plus loopback and
597  point-to-point in case an OS incorrectly marks them
598  as broadcast). Also skip down interfaces unless we're
599  trying to get a list of configurable interfaces. */
600  if ((((local_family == AF_INET &&
601  !(info.flags & IFF_BROADCAST)) ||
602 #ifdef DHCPv6
603  (local_family == AF_INET6 &&
604  !(info.flags & IFF_MULTICAST)) ||
605 #endif
606  info.flags & IFF_LOOPBACK ||
607  info.flags & IFF_POINTOPOINT) && !tmp) ||
608  (!(info.flags & IFF_UP) &&
609  state != DISCOVER_UNCONFIGURED))
610  continue;
611 
612  /* If there isn't already an interface by this name,
613  allocate one. */
614  if (tmp == NULL) {
615  status = interface_allocate(&tmp, MDL);
616  if (status != ISC_R_SUCCESS) {
617  log_fatal("Error allocating interface %s: %s",
618  info.name, isc_result_totext(status));
619  }
620  strcpy(tmp->name, info.name);
621  interface_snorf(tmp, ir);
622  interface_dereference(&tmp, MDL);
623  tmp = interfaces; /* XXX */
624  }
625 
627  (*dhcp_interface_discovery_hook)(tmp);
628  }
629 
630  if ((info.addr.ss_family == AF_INET) &&
631  (local_family == AF_INET)) {
632  struct sockaddr_in *a = (struct sockaddr_in*)&info.addr;
633  struct iaddr addr;
634 
635  /* We don't want the loopback interface. */
636  if (a->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
637  ((tmp->flags & INTERFACE_AUTOMATIC) &&
638  state == DISCOVER_SERVER))
639  continue;
640 
641  /* If the only address we have is 0.0.0.0, we
642  shouldn't consider the interface configured. */
643  if (a->sin_addr.s_addr != htonl(INADDR_ANY))
644  tmp->configured = 1;
645 
646  add_ipv4_addr_to_interface(tmp, &a->sin_addr);
647 
648  /* invoke the setup hook */
649  addr.len = 4;
650  memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len);
652  (*dhcp_interface_setup_hook)(tmp, &addr);
653  }
654  }
655 #ifdef DHCPv6
656  else if ((info.addr.ss_family == AF_INET6) &&
657  (local_family == AF_INET6)) {
658  struct sockaddr_in6 *a =
659  (struct sockaddr_in6*)&info.addr;
660  struct iaddr addr;
661 
662  /* We don't want the loopback interface. */
663  if (IN6_IS_ADDR_LOOPBACK(&a->sin6_addr) &&
664  ((tmp->flags & INTERFACE_AUTOMATIC) &&
665  state == DISCOVER_SERVER))
666  continue;
667 
668  /* If the only address we have is 0.0.0.0, we
669  shouldn't consider the interface configured. */
670  if (IN6_IS_ADDR_UNSPECIFIED(&a->sin6_addr))
671  tmp->configured = 1;
672 
673  add_ipv6_addr_to_interface(tmp, &a->sin6_addr);
674 
675  /* invoke the setup hook */
676  addr.len = 16;
677  memcpy(addr.iabuf, &a->sin6_addr, addr.len);
679  (*dhcp_interface_setup_hook)(tmp, &addr);
680  }
681  }
682 #endif /* DHCPv6 */
683  }
684 
685  if (err) {
686  log_fatal("Error getting interface information.");
687  }
688 
689  end_iface_scan(&ifaces);
690 
691 
692  /* Mock-up an 'ifp' structure which is no longer used in the
693  * new interface-sensing code, but is used in higher layers
694  * (for example to sense fallback interfaces).
695  */
696  for (tmp = interfaces ; tmp != NULL ; tmp = tmp->next) {
697  if (tmp->ifp == NULL) {
698  struct ifreq *tif;
699 
700  tif = (struct ifreq *)dmalloc(sizeof(struct ifreq),
701  MDL);
702  if (tif == NULL)
703  log_fatal("no space for ifp mockup.");
704  strcpy(tif->ifr_name, tmp->name);
705  tmp->ifp = tif;
706  }
707  }
708 
709 
710  /* If we're just trying to get a list of interfaces that we might
711  be able to configure, we can quit now. */
712  if (state == DISCOVER_UNCONFIGURED) {
713  return;
714  }
715 
716  /* Weed out the interfaces that did not have IP addresses. */
717  tmp = last = next = NULL;
718  if (interfaces)
719  interface_reference (&tmp, interfaces, MDL);
720  while (tmp) {
721  if (next)
722  interface_dereference (&next, MDL);
723  if (tmp -> next)
724  interface_reference (&next, tmp -> next, MDL);
725  /* skip interfaces that are running already */
726  if (tmp -> flags & INTERFACE_RUNNING) {
727  interface_dereference(&tmp, MDL);
728  if(next)
729  interface_reference(&tmp, next, MDL);
730  continue;
731  }
732  if ((tmp -> flags & INTERFACE_AUTOMATIC) &&
733  state == DISCOVER_REQUESTED)
734  tmp -> flags &= ~(INTERFACE_AUTOMATIC |
736 
737 #ifdef DHCPv6
738  if (!(tmp->flags & INTERFACE_REQUESTED)) {
739 #else
740  if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
741 #endif /* DHCPv6 */
742  if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
743  log_fatal ("%s: not found", tmp -> name);
744  if (!last) {
745  if (interfaces)
746  interface_dereference (&interfaces,
747  MDL);
748  if (next)
749  interface_reference (&interfaces, next, MDL);
750  } else {
751  interface_dereference (&last -> next, MDL);
752  if (next)
753  interface_reference (&last -> next,
754  next, MDL);
755  }
756  if (tmp -> next)
757  interface_dereference (&tmp -> next, MDL);
758 
759  /* Remember the interface in case we need to know
760  about it later. */
761  if (dummy_interfaces) {
762  interface_reference (&tmp -> next,
763  dummy_interfaces, MDL);
764  interface_dereference (&dummy_interfaces, MDL);
765  }
766  interface_reference (&dummy_interfaces, tmp, MDL);
767  interface_dereference (&tmp, MDL);
768  if (next)
769  interface_reference (&tmp, next, MDL);
770  continue;
771  }
772  last = tmp;
773 
774  /* We must have a subnet declaration for each interface. */
775  if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
776  log_info("%s", "");
777  if (local_family == AF_INET) {
778  log_info("No subnet declaration for %s (%s).",
779  tmp->name,
780  (tmp->addresses == NULL) ?
781  "no IPv4 addresses" :
782  inet_ntoa(tmp->addresses[0]));
783 #ifdef DHCPv6
784  } else {
785  if (tmp->v6addresses != NULL) {
786  inet_ntop(AF_INET6,
787  &tmp->v6addresses[0],
788  abuf,
789  sizeof(abuf));
790  } else {
791  strcpy(abuf, "no IPv6 addresses");
792  }
793  log_info("No subnet6 declaration for %s (%s).",
794  tmp->name,
795  abuf);
796 #endif /* DHCPv6 */
797  }
798  if (supports_multiple_interfaces(tmp)) {
799  log_info ("** Ignoring requests on %s. %s",
800  tmp -> name, "If this is not what");
801  log_info (" you want, please write %s",
802 #ifdef DHCPv6
803  (local_family != AF_INET) ?
804  "a subnet6 declaration" :
805 #endif
806  "a subnet declaration");
807  log_info (" in your dhcpd.conf file %s",
808  "for the network segment");
809  log_info (" to %s %s %s",
810  "which interface",
811  tmp -> name, "is attached. **");
812  log_info ("%s", "");
813  goto next;
814  } else {
815  log_error ("You must write a %s",
816 #ifdef DHCPv6
817  (local_family != AF_INET) ?
818  "subnet6 declaration for this" :
819 #endif
820  "subnet declaration for this");
821  log_error ("subnet. You cannot prevent %s",
822  "the DHCP server");
823  log_error ("from listening on this subnet %s",
824  "because your");
825  log_fatal ("operating system does not %s.",
826  "support this capability");
827  }
828  }
829 
830  /* Find subnets that don't have valid interface
831  addresses... */
832  for (subnet = (tmp -> shared_network
833  ? tmp -> shared_network -> subnets
834  : (struct subnet *)0);
835  subnet; subnet = subnet -> next_sibling) {
836  /* Set the interface address for this subnet
837  to the first address we found. */
838  if (subnet->interface_address.len == 0) {
839  if (tmp->address_count > 0) {
840  subnet->interface_address.len = 4;
841  memcpy(subnet->interface_address.iabuf,
842  &tmp->addresses[0].s_addr, 4);
843  } else if (tmp->v6address_count > 0) {
844  subnet->interface_address.len = 16;
845  memcpy(subnet->interface_address.iabuf,
846  &tmp->v6addresses[0].s6_addr,
847  16);
848  } else {
849  /* XXX: should be one */
850  log_error("%s missing an interface "
851  "address", tmp->name);
852  continue;
853  }
854  }
855  }
856 
857  /* Flag the index as not having been set, so that the
858  interface registerer can set it or not as it chooses. */
859  tmp -> index = -1;
860 
861  /* Register the interface... */
862  if (local_family == AF_INET) {
863  if_register_receive(tmp);
864  if_register_send(tmp);
865 #ifdef DHCPv6
866  } else {
867  if ((state == DISCOVER_SERVER) ||
868  (state == DISCOVER_RELAY)) {
869  if_register6(tmp, 1);
870  } else {
872  }
873 #endif /* DHCPv6 */
874  }
875 
876  interface_stash (tmp);
877  wifcount++;
878 #if defined (F_SETFD)
879  if (fcntl (tmp -> rfdesc, F_SETFD, 1) < 0)
880  log_error ("Can't set close-on-exec on %s: %m",
881  tmp -> name);
882  if (tmp -> rfdesc != tmp -> wfdesc) {
883  if (fcntl (tmp -> wfdesc, F_SETFD, 1) < 0)
884  log_error ("Can't set close-on-exec on %s: %m",
885  tmp -> name);
886  }
887 #endif
888  next:
889  interface_dereference (&tmp, MDL);
890  if (next)
891  interface_reference (&tmp, next, MDL);
892  }
893 
894  /*
895  * Now register all the remaining interfaces as protocols.
896  * We register with omapi to allow for control of the interface,
897  * we've already registered the fd or socket with the socket
898  * manager as part of if_register_receive().
899  */
900  for (tmp = interfaces; tmp; tmp = tmp -> next) {
901  /* not if it's been registered before */
902  if (tmp -> flags & INTERFACE_RUNNING)
903  continue;
904  if (tmp -> rfdesc == -1)
905  continue;
906  switch (local_family) {
907 #ifdef DHCPv6
908  case AF_INET6:
910  if_readsocket,
911  0, got_one_v6, 0, 0);
912  break;
913 #endif /* DHCPv6 */
914  case AF_INET:
915  default:
917  if_readsocket,
918  0, got_one, 0, 0);
919  break;
920  }
921 
922  if (status != ISC_R_SUCCESS)
923  log_fatal ("Can't register I/O handle for %s: %s",
924  tmp -> name, isc_result_totext (status));
925 
926 #if defined(DHCPv6)
927  /* Only register the first interface for V6, since
928  * servers and relays all use the same socket.
929  * XXX: This has some messy side effects if we start
930  * dynamically adding and removing interfaces, but
931  * we're well beyond that point in terms of mess.
932  */
933  if (((state == DISCOVER_SERVER) || (state == DISCOVER_RELAY)) &&
934  (local_family == AF_INET6))
935  break;
936 #endif
937  } /* for (tmp = interfaces; ... */
938 
939  if (state == DISCOVER_SERVER && wifcount == 0) {
940  log_info ("%s", "");
941  log_fatal ("Not configured to listen on any interfaces!");
942  }
943 
944  if ((local_family == AF_INET) && !setup_fallback) {
945  setup_fallback = 1;
947  }
948 
949 #if defined (F_SETFD)
950  if (fallback_interface) {
951  if (fcntl (fallback_interface -> rfdesc, F_SETFD, 1) < 0)
952  log_error ("Can't set close-on-exec on fallback: %m");
953  if (fallback_interface -> rfdesc != fallback_interface -> wfdesc) {
954  if (fcntl (fallback_interface -> wfdesc, F_SETFD, 1) < 0)
955  log_error ("Can't set close-on-exec on fallback: %m");
956  }
957  }
958 #endif /* F_SETFD */
959 }
960 
962  omapi_object_t *h;
963 {
964  struct interface_info *ip;
965 
966  if (h -> type != dhcp_type_interface)
967  return -1;
968  ip = (struct interface_info *)h;
969  return ip -> rfdesc;
970 }
971 
972 int setup_fallback (struct interface_info **fp, const char *file, int line)
973 {
974  isc_result_t status;
975 
976  status = interface_allocate (&fallback_interface, file, line);
977  if (status != ISC_R_SUCCESS)
978  log_fatal ("Error allocating fallback interface: %s",
979  isc_result_totext (status));
980  strcpy (fallback_interface -> name, "fallback");
982  (*dhcp_interface_setup_hook) (fallback_interface,
983  (struct iaddr *)0);
984  status = interface_reference (fp, fallback_interface, file, line);
985 
986  fallback_interface -> index = -1;
987  interface_stash (fallback_interface);
988  return status == ISC_R_SUCCESS;
989 }
990 
992 {
993  struct interface_info *ip;
994 
995  for (ip = interfaces; ip; ip = ip -> next) {
998  }
999 
1000  if (fallback_interface)
1001  if_reinitialize_send (fallback_interface);
1002 
1004 }
1005 
1006 isc_result_t got_one (h)
1007  omapi_object_t *h;
1008 {
1009  struct sockaddr_in from;
1010  struct hardware hfrom;
1011  struct iaddr ifrom;
1012  int result;
1013  union {
1014  unsigned char packbuf [4095]; /* Packet input buffer.
1015  Must be as large as largest
1016  possible MTU. */
1017  struct dhcp_packet packet;
1018  } u;
1019  struct interface_info *ip;
1020 
1021  if (h -> type != dhcp_type_interface)
1022  return DHCP_R_INVALIDARG;
1023  ip = (struct interface_info *)h;
1024 
1025  again:
1026  if ((result =
1027  receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) {
1028  log_error ("receive_packet failed on %s: %m", ip -> name);
1029  return ISC_R_UNEXPECTED;
1030  }
1031  if (result == 0)
1032  return ISC_R_UNEXPECTED;
1033 
1034  /*
1035  * If we didn't at least get the fixed portion of the BOOTP
1036  * packet, drop the packet.
1037  * Previously we allowed packets with no sname or filename
1038  * as we were aware of at least one client that did. But
1039  * a bug caused short packets to not work and nobody has
1040  * complained, it seems rational to tighten up that
1041  * restriction.
1042  */
1043  if (result < DHCP_FIXED_NON_UDP)
1044  return ISC_R_UNEXPECTED;
1045 
1046 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
1047  {
1048  /* We retrieve the ifindex from the unused hfrom variable */
1049  unsigned int ifindex;
1050 
1051  memcpy(&ifindex, hfrom.hbuf, sizeof (ifindex));
1052 
1053  /*
1054  * Seek forward from the first interface to find the matching
1055  * source interface by interface index.
1056  */
1057  ip = interfaces;
1058  while ((ip != NULL) && (if_nametoindex(ip->name) != ifindex))
1059  ip = ip->next;
1060  if (ip == NULL)
1061  return ISC_R_NOTFOUND;
1062  }
1063 #endif
1064 
1065  if (bootp_packet_handler) {
1066  ifrom.len = 4;
1067  memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
1068 
1069  (*bootp_packet_handler) (ip, &u.packet, (unsigned)result,
1070  from.sin_port, ifrom, &hfrom);
1071  }
1072 
1073  /* If there is buffered data, read again. This is for, e.g.,
1074  bpf, which may return two packets at once. */
1075  if (ip -> rbuf_offset != ip -> rbuf_len)
1076  goto again;
1077  return ISC_R_SUCCESS;
1078 }
1079 
1080 #ifdef DHCPv6
1081 isc_result_t
1083  struct sockaddr_in6 from;
1084  struct in6_addr to;
1085  struct iaddr ifrom;
1086  int result;
1087  char buf[65536]; /* maximum size for a UDP packet is 65536 */
1088  struct interface_info *ip;
1089  int is_unicast;
1090  unsigned int if_idx = 0;
1091 
1092  if (h->type != dhcp_type_interface) {
1093  return DHCP_R_INVALIDARG;
1094  }
1095  ip = (struct interface_info *)h;
1096 
1097  result = receive_packet6(ip, (unsigned char *)buf, sizeof(buf),
1098  &from, &to, &if_idx);
1099  if (result < 0) {
1100  log_error("receive_packet6() failed on %s: %m", ip->name);
1101  return ISC_R_UNEXPECTED;
1102  }
1103 
1104  /* 0 is 'any' interface. */
1105  if (if_idx == 0)
1106  return ISC_R_NOTFOUND;
1107 
1108  if (dhcpv6_packet_handler != NULL) {
1109  /*
1110  * If a packet is not multicast, we assume it is unicast.
1111  */
1112  if (IN6_IS_ADDR_MULTICAST(&to)) {
1113  is_unicast = ISC_FALSE;
1114  } else {
1115  is_unicast = ISC_TRUE;
1116  }
1117 
1118  ifrom.len = 16;
1119  memcpy(ifrom.iabuf, &from.sin6_addr, ifrom.len);
1120 
1121  /* Seek forward to find the matching source interface. */
1122  ip = interfaces;
1123  while ((ip != NULL) && (if_nametoindex(ip->name) != if_idx))
1124  ip = ip->next;
1125 
1126  if (ip == NULL)
1127  return ISC_R_NOTFOUND;
1128 
1129  (*dhcpv6_packet_handler)(ip, buf,
1130  result, from.sin6_port,
1131  &ifrom, is_unicast);
1132  }
1133 
1134  return ISC_R_SUCCESS;
1135 }
1136 #endif /* DHCPv6 */
1137 
1139  omapi_object_t *id,
1141  omapi_typed_data_t *value)
1142 {
1143  struct interface_info *interface;
1144  isc_result_t status;
1145 
1146  if (h -> type != dhcp_type_interface)
1147  return DHCP_R_INVALIDARG;
1148  interface = (struct interface_info *)h;
1149 
1150  if (!omapi_ds_strcmp (name, "name")) {
1151  if ((value -> type == omapi_datatype_data ||
1152  value -> type == omapi_datatype_string) &&
1153  value -> u.buffer.len < sizeof interface -> name) {
1154  memcpy (interface -> name,
1155  value -> u.buffer.value,
1156  value -> u.buffer.len);
1157  interface -> name [value -> u.buffer.len] = 0;
1158  } else
1159  return DHCP_R_INVALIDARG;
1160  return ISC_R_SUCCESS;
1161  }
1162 
1163  /* Try to find some inner object that can take the value. */
1164  if (h -> inner && h -> inner -> type -> set_value) {
1165  status = ((*(h -> inner -> type -> set_value))
1166  (h -> inner, id, name, value));
1167  if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
1168  return status;
1169  }
1170 
1171  return ISC_R_NOTFOUND;
1172 }
1173 
1174 
1176  omapi_object_t *id,
1177  omapi_data_string_t *name,
1178  omapi_value_t **value)
1179 {
1180  return ISC_R_NOTIMPLEMENTED;
1181 }
1182 
1184  const char *file, int line)
1185 {
1186  struct interface_info *interface;
1187 
1188  if (h -> type != dhcp_type_interface)
1189  return DHCP_R_INVALIDARG;
1190  interface = (struct interface_info *)h;
1191 
1192  if (interface -> ifp) {
1193  dfree (interface -> ifp, file, line);
1194  interface -> ifp = 0;
1195  }
1196  if (interface -> next)
1197  interface_dereference (&interface -> next, file, line);
1198  if (interface -> rbuf) {
1199  dfree (interface -> rbuf, file, line);
1200  interface -> rbuf = (unsigned char *)0;
1201  }
1202  if (interface -> client)
1203  interface -> client = (struct client_state *)0;
1204 
1205  if (interface -> shared_network)
1207  &interface -> shared_network, MDL);
1208 
1209  return ISC_R_SUCCESS;
1210 }
1211 
1213  const char *name, va_list ap)
1214 {
1215  struct interface_info *ip, *interface;
1216  isc_result_t status;
1217 
1218  if (h -> type != dhcp_type_interface)
1219  return DHCP_R_INVALIDARG;
1220  interface = (struct interface_info *)h;
1221 
1222  /* If it's an update signal, see if the interface is dead right
1223  now, or isn't known at all, and if that's the case, revive it. */
1224  if (!strcmp (name, "update")) {
1225  for (ip = dummy_interfaces; ip; ip = ip -> next)
1226  if (ip == interface)
1227  break;
1228  if (ip && dhcp_interface_startup_hook)
1229  return (*dhcp_interface_startup_hook) (ip);
1230 
1231  for (ip = interfaces; ip; ip = ip -> next)
1232  if (ip == interface)
1233  break;
1234  if (!ip && dhcp_interface_startup_hook)
1235  return (*dhcp_interface_startup_hook) (ip);
1236  }
1237 
1238  /* Try to find some inner object that can take the value. */
1239  if (h -> inner && h -> inner -> type -> signal_handler) {
1240  status = ((*(h -> inner -> type -> signal_handler))
1241  (h -> inner, name, ap));
1242  if (status == ISC_R_SUCCESS)
1243  return status;
1244  }
1245  return ISC_R_NOTFOUND;
1246 }
1247 
1249  omapi_object_t *id,
1250  omapi_object_t *h)
1251 {
1252  struct interface_info *interface;
1253  isc_result_t status;
1254 
1255  if (h -> type != dhcp_type_interface)
1256  return DHCP_R_INVALIDARG;
1257  interface = (struct interface_info *)h;
1258 
1259  /* Write out all the values. */
1260 
1261  status = omapi_connection_put_name (c, "state");
1262  if (status != ISC_R_SUCCESS)
1263  return status;
1264  if ((interface->flags & INTERFACE_REQUESTED) != 0)
1265  status = omapi_connection_put_string (c, "up");
1266  else
1267  status = omapi_connection_put_string (c, "down");
1268  if (status != ISC_R_SUCCESS)
1269  return status;
1270 
1271  /* Write out the inner object, if any. */
1272  if (h -> inner && h -> inner -> type -> stuff_values) {
1273  status = ((*(h -> inner -> type -> stuff_values))
1274  (c, id, h -> inner));
1275  if (status == ISC_R_SUCCESS)
1276  return status;
1277  }
1278 
1279  return ISC_R_SUCCESS;
1280 }
1281 
1283  omapi_object_t *id,
1284  omapi_object_t *ref)
1285 {
1286  omapi_value_t *tv = (omapi_value_t *)0;
1287  isc_result_t status;
1288  struct interface_info *interface;
1289 
1290  if (!ref)
1291  return DHCP_R_NOKEYS;
1292 
1293  /* First see if we were sent a handle. */
1294  status = omapi_get_value_str (ref, id, "handle", &tv);
1295  if (status == ISC_R_SUCCESS) {
1296  status = omapi_handle_td_lookup (ip, tv -> value);
1297 
1299  if (status != ISC_R_SUCCESS)
1300  return status;
1301 
1302  /* Don't return the object if the type is wrong. */
1303  if ((*ip) -> type != dhcp_type_interface) {
1305  return DHCP_R_INVALIDARG;
1306  }
1307  }
1308 
1309  /* Now look for an interface name. */
1310  status = omapi_get_value_str (ref, id, "name", &tv);
1311  if (status == ISC_R_SUCCESS) {
1312  char *s;
1313  unsigned len;
1314  for (interface = interfaces; interface;
1315  interface = interface -> next) {
1316  s = memchr (interface -> name, 0, IFNAMSIZ);
1317  if (s)
1318  len = s - &interface -> name [0];
1319  else
1320  len = IFNAMSIZ;
1321  if ((tv -> value -> u.buffer.len == len &&
1322  !memcmp (interface -> name,
1323  (char *)tv -> value -> u.buffer.value,
1324  len)))
1325  break;
1326  }
1327  if (!interface) {
1328  for (interface = dummy_interfaces;
1329  interface; interface = interface -> next) {
1330  s = memchr (interface -> name, 0, IFNAMSIZ);
1331  if (s)
1332  len = s - &interface -> name [0];
1333  else
1334  len = IFNAMSIZ;
1335  if ((tv -> value -> u.buffer.len == len &&
1336  !memcmp (interface -> name,
1337  (char *)
1338  tv -> value -> u.buffer.value,
1339  len)))
1340  break;
1341  }
1342  }
1343 
1345  if (*ip && *ip != (omapi_object_t *)interface) {
1347  return DHCP_R_KEYCONFLICT;
1348  } else if (!interface) {
1349  if (*ip)
1351  return ISC_R_NOTFOUND;
1352  } else if (!*ip)
1354  (omapi_object_t *)interface,
1355  MDL);
1356  }
1357 
1358  /* If we get to here without finding an interface, no valid key was
1359  specified. */
1360  if (!*ip)
1361  return DHCP_R_NOKEYS;
1362  return ISC_R_SUCCESS;
1363 }
1364 
1365 /* actually just go discover the interface */
1367  omapi_object_t *id)
1368 {
1369  struct interface_info *hp;
1370  isc_result_t status;
1371 
1372  hp = (struct interface_info *)0;
1373  status = interface_allocate (&hp, MDL);
1374  if (status != ISC_R_SUCCESS)
1375  return status;
1376  hp -> flags = INTERFACE_REQUESTED;
1377  status = interface_reference ((struct interface_info **)lp, hp, MDL);
1378  interface_dereference (&hp, MDL);
1379  return status;
1380 }
1381 
1383  omapi_object_t *id)
1384 {
1385  struct interface_info *interface, *ip, *last;
1386 
1387  interface = (struct interface_info *)lp;
1388 
1389  /* remove from interfaces */
1390  last = 0;
1391  for (ip = interfaces; ip; ip = ip -> next) {
1392  if (ip == interface) {
1393  if (last) {
1394  interface_dereference (&last -> next, MDL);
1395  if (ip -> next)
1396  interface_reference (&last -> next,
1397  ip -> next, MDL);
1398  } else {
1399  interface_dereference (&interfaces, MDL);
1400  if (ip -> next)
1401  interface_reference (&interfaces,
1402  ip -> next, MDL);
1403  }
1404  if (ip -> next)
1405  interface_dereference (&ip -> next, MDL);
1406  break;
1407  }
1408  last = ip;
1409  }
1410  if (!ip)
1411  return ISC_R_NOTFOUND;
1412 
1413  /* add the interface to the dummy_interface list */
1414  if (dummy_interfaces) {
1415  interface_reference (&interface -> next,
1416  dummy_interfaces, MDL);
1417  interface_dereference (&dummy_interfaces, MDL);
1418  }
1419  interface_reference (&dummy_interfaces, interface, MDL);
1420 
1421  /* do a DHCPRELEASE */
1423  (*dhcp_interface_shutdown_hook) (interface);
1424 
1425  /* remove the io object */
1427 
1428  switch(local_family) {
1429 #ifdef DHCPv6
1430  case AF_INET6:
1431  if_deregister6(interface);
1432  break;
1433 #endif /* DHCPv6 */
1434  case AF_INET:
1435  default:
1436  if_deregister_send(interface);
1437  if_deregister_receive(interface);
1438  break;
1439  }
1440 
1441  return ISC_R_SUCCESS;
1442 }
1443 
1444 void interface_stash (struct interface_info *tptr)
1445 {
1446  struct interface_info **vec;
1447  int delta;
1448 
1449  /* If the registerer didn't assign an index, assign one now. */
1450  if (tptr -> index == -1) {
1451  tptr -> index = interface_count++;
1452  while (tptr -> index < interface_max &&
1453  interface_vector [tptr -> index])
1454  tptr -> index = interface_count++;
1455  }
1456 
1457  if (interface_max <= tptr -> index) {
1458  delta = tptr -> index - interface_max + 10;
1459  vec = dmalloc ((interface_max + delta) *
1460  sizeof (struct interface_info *), MDL);
1461  if (!vec)
1462  return;
1463  memset (&vec [interface_max], 0,
1464  (sizeof (struct interface_info *)) * delta);
1465  interface_max += delta;
1466  if (interface_vector) {
1467  memcpy (vec, interface_vector,
1468  (interface_count *
1469  sizeof (struct interface_info *)));
1470  dfree (interface_vector, MDL);
1471  }
1472  interface_vector = vec;
1473  }
1474  interface_reference (&interface_vector [tptr -> index], tptr, MDL);
1475  if (tptr -> index >= interface_count)
1476  interface_count = tptr -> index + 1;
1477 #if defined (TRACING)
1478  trace_interface_register (interface_trace, tptr);
1479 #endif
1480 }
1481 
1482 void interface_snorf (struct interface_info *tmp, int ir)
1483 {
1484  tmp -> circuit_id = (u_int8_t *)tmp -> name;
1485  tmp -> circuit_id_len = strlen (tmp -> name);
1486  tmp -> remote_id = 0;
1487  tmp -> remote_id_len = 0;
1488  tmp -> flags = ir;
1489  if (interfaces) {
1490  interface_reference (&tmp -> next,
1491  interfaces, MDL);
1492  interface_dereference (&interfaces, MDL);
1493  }
1494  interface_reference (&interfaces, tmp, MDL);
1495 }
#define LIFCONF
Definition: discover.c:188
void if_register_send(struct interface_info *)
#define DHCP_FIXED_NON_UDP
Definition: dhcp.h:37
void(* dhcpv6_packet_handler)(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
u_int16_t local_port
Definition: discover.c:43
const char int line
Definition: dhcpd.h:3535
char name[IF_NAMESIZE+1]
Definition: discover.c:225
isc_result_t omapi_register_io_object(omapi_object_t *, int(*)(omapi_object_t *), int(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *))
Definition: dispatch.c:199
#define SIOCGLIFFLAGS
Definition: discover.c:186
void end_iface_scan(struct iface_conf_list *ifaces)
Definition: discover.c:367
isc_result_t omapi_object_reference(omapi_object_t **, omapi_object_t *, const char *, int)
Definition: alloc.c:557
struct shared_network * shared_network
Definition: dhcpd.h:1243
isc_result_t dhcp_interface_destroy(omapi_object_t *h, const char *file, int line)
Definition: discover.c:1183
int if_readsocket(omapi_object_t *h)
Definition: discover.c:961
char name[IFNAMSIZ]
Definition: dhcpd.h:1267
void if_reinitialize_send(struct interface_info *)
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
Definition: discover.c:55
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
Definition: dhcpd.h:948
u_int16_t remote_port
Definition: discover.c:44
void trace_interface_register(trace_type_t *, struct interface_info *)
trace_type_t * interface_trace
#define MDL
Definition: omapip.h:568
isc_result_t dhcp_interface_stuff_values(omapi_object_t *c, omapi_object_t *id, omapi_object_t *h)
Definition: discover.c:1248
unsigned char iabuf[16]
Definition: inet.h:33
#define DHCP_R_INVALIDARG
Definition: result.h:48
omapi_typed_data_t * value
Definition: omapip.h:91
#define DISCOVER_REQUESTED
Definition: dhcpd.h:637
void reinitialize_interfaces()
Definition: discover.c:991
void trace_outpacket_input(trace_type_t *, unsigned, char *)
isc_result_t dhcp_interface_remove(omapi_object_t *lp, omapi_object_t *id)
Definition: discover.c:1382
struct in_addr * addresses
Definition: dhcpd.h:1247
int setup_fallback(struct interface_info **fp, const char *file, int line)
Definition: discover.c:972
#define INTERFACE_RUNNING
Definition: dhcpd.h:1284
int log_error(const char *,...) __attribute__((__format__(__printf__
trace_type_t * trace_type_register(const char *, void *, void(*)(trace_type_t *, unsigned, char *), void(*)(trace_type_t *), const char *, int)
void add_ipv4_addr_to_interface(struct interface_info *iface, const struct in_addr *addr)
Definition: discover.c:473
struct subnet * subnets
Definition: mdb.c:33
unsigned len
Definition: inet.h:32
#define OMAPI_OBJECT_ALLOC(name, stype, type)
Definition: omapip.h:161
int interface_max
Definition: discover.c:76
void if_deregister_receive(struct interface_info *)
#define DHCP_R_KEYCONFLICT
Definition: result.h:52
void maybe_setup_fallback(void)
void if_deregister_send(struct interface_info *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
size_t rbuf_len
Definition: dhcpd.h:1275
isc_result_t dhcp_interface_get_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value)
Definition: discover.c:1175
#define DISCOVER_RELAY
Definition: dhcpd.h:636
#define INTERFACE_AUTOMATIC
Definition: dhcpd.h:1283
void interface_trace_setup(void)
struct omapi_typed_data_t::@3::@4 buffer
size_t rbuf_offset
Definition: dhcpd.h:1274
int interface_count
Definition: discover.c:75
struct LIFCONF conf
Definition: discover.c:217
#define SIOCGLIFCONF
Definition: discover.c:185
void if_deregister6(struct interface_info *info)
char * name
Definition: dhcpd.h:1161
struct interface_info * fallback_interface
Definition: discover.c:40
void trace_outpacket_stop(trace_type_t *)
void trace_inpacket_stop(trace_type_t *)
void if_register_linklocal6(struct interface_info *info)
#define DISCOVER_SERVER
Definition: dhcpd.h:634
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
Definition: support.c:483
struct iaddr interface_address
Definition: dhcpd.h:954
isc_result_t dhcp_interface_create(omapi_object_t **lp, omapi_object_t *id)
Definition: discover.c:1366
void trace_inpacket_input(trace_type_t *, unsigned, char *)
unsigned circuit_id_len
Definition: dhcpd.h:1261
trace_type_t * inpacket_trace
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
Definition: alloc.c:579
Definition: ip.h:47
isc_result_t got_one_v6(omapi_object_t *)
void dfree(void *, const char *, int)
Definition: alloc.c:131
omapi_object_type_t * dhcp_type_interface
Definition: discover.c:68
isc_result_t omapi_handle_td_lookup(omapi_object_t **, omapi_typed_data_t *)
Definition: handle.c:283
int begin_iface_scan(struct iface_conf_list *ifaces)
Definition: discover.c:236
struct in_addr limited_broadcast
Definition: discover.c:50
int int log_info(const char *,...) __attribute__((__format__(__printf__
isc_result_t dhcp_interface_set_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value)
Definition: discover.c:1138
struct interface_info * interfaces
Definition: discover.c:40
u_int32_t flags
Definition: dhcpd.h:1281
isc_result_t omapi_connection_put_string(omapi_object_t *, const char *)
Definition: buffer.c:681
int interfaces_invalidated
Definition: discover.c:41
void interface_snorf(struct interface_info *tmp, int ir)
Definition: discover.c:1482
int v6address_count
Definition: dhcpd.h:1254
int address_max
Definition: dhcpd.h:1251
int(* dhcp_interface_setup_hook)(struct interface_info *, struct iaddr *)
Definition: discover.c:45
Definition: inet.h:31
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
Definition: alloc.c:1046
u_int8_t * circuit_id
Definition: dhcpd.h:1259
void if_register6(struct interface_info *info, int do_multicast)
int local_family
Definition: discover.c:52
int quiet_interface_discovery
Definition: discover.c:42
isc_result_t omapi_object_type_register(omapi_object_type_t **, const char *, isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *), isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **), isc_result_t(*)(omapi_object_t *, const char *, int), isc_result_t(*)(omapi_object_t *, const char *, va_list), isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t **, omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t **, omapi_object_t *), isc_result_t(*)(omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t *, const char *, int), isc_result_t(*)(omapi_object_t **, const char *, int), isc_result_t(*)(size_t), size_t, isc_result_t(*)(omapi_object_t *, const char *, int), int)
Definition: support.c:194
isc_result_t(* dhcp_interface_startup_hook)(struct interface_info *)
Definition: discover.c:47
#define DISCOVER_UNCONFIGURED
Definition: dhcpd.h:635
struct sockaddr_storage addr
Definition: discover.c:226
#define DHCP_R_NOKEYS
Definition: result.h:54
#define DHCP_R_UNCHANGED
Definition: result.h:50
isc_result_t dhcp_interface_signal_handler(omapi_object_t *h, const char *name, va_list ap)
Definition: discover.c:1212
struct interface_info * next
Definition: dhcpd.h:1242
isc_uint64_t flags
Definition: discover.c:227
const char int
Definition: omapip.h:443
struct interface_info * dummy_interfaces
Definition: discover.c:40
int omapi_ds_strcmp(omapi_data_string_t *, const char *)
Definition: support.c:582
isc_result_t got_one(omapi_object_t *h)
Definition: discover.c:1006
isc_result_t omapi_unregister_io_object(omapi_object_t *)
Definition: dispatch.c:356
isc_result_t interface_initialize(omapi_object_t *ipo, const char *file, int line)
Definition: discover.c:118
int supports_multiple_interfaces(struct interface_info *)
u_int8_t * remote_id
Definition: dhcpd.h:1263
isc_result_t interface_setup()
Definition: discover.c:80
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition: dhcpd.h:441
int address_count
Definition: dhcpd.h:1250
unsigned remote_id_len
Definition: dhcpd.h:1265
struct in_addr local_address
Definition: discover.c:53
int(* dhcp_interface_discovery_hook)(struct interface_info *)
Definition: discover.c:46
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
void trace_interface_input(trace_type_t *, unsigned, char *)
const char * file
Definition: dhcpd.h:3535
isc_result_t omapi_connection_put_name(omapi_object_t *, const char *)
Definition: buffer.c:670
int configured
Definition: dhcpd.h:1278
void if_reinitialize_receive(struct interface_info *)
void if_register_receive(struct interface_info *)
struct interface_info ** interface_vector
Definition: discover.c:74
void interface_stash(struct interface_info *tptr)
Definition: discover.c:1444
trace_type_t * outpacket_trace
#define DHCPv6
Definition: config.h:18
#define LIFREQ
Definition: discover.c:187
int v6address_max
Definition: dhcpd.h:1256
struct ifreq * ifp
Definition: dhcpd.h:1277
void trace_interface_stop(trace_type_t *)
#define RC_MISC
Definition: alloc.h:56
int(* dhcp_interface_shutdown_hook)(struct interface_info *)
Definition: discover.c:48
void discover_interfaces(int state)
Definition: discover.c:552
int next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces)
Definition: discover.c:300
isc_result_t dhcp_interface_lookup(omapi_object_t **ip, omapi_object_t *id, omapi_object_t *ref)
Definition: discover.c:1282
#define INTERFACE_REQUESTED
Definition: dhcpd.h:1282
ssize_t receive_packet6(struct interface_info *interface, unsigned char *buf, size_t len, struct sockaddr_in6 *from, struct in6_addr *to_addr, unsigned int *if_index)
struct in6_addr * v6addresses
Definition: dhcpd.h:1252