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