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