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