00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031
00032 #define BSD_COMP
00033 #include <sys/ioctl.h>
00034 #include <errno.h>
00035
00036 #ifdef HAVE_NET_IF6_H
00037 # include <net/if6.h>
00038 #endif
00039
00040 struct interface_info *interfaces, *dummy_interfaces, *fallback_interface;
00041 int interfaces_invalidated;
00042 int quiet_interface_discovery;
00043 u_int16_t local_port;
00044 u_int16_t remote_port;
00045 int (*dhcp_interface_setup_hook) (struct interface_info *, struct iaddr *);
00046 int (*dhcp_interface_discovery_hook) (struct interface_info *);
00047 isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *);
00048 int (*dhcp_interface_shutdown_hook) (struct interface_info *);
00049
00050 struct in_addr limited_broadcast;
00051
00052 int local_family = AF_INET;
00053 struct in_addr local_address;
00054
00055 void (*bootp_packet_handler) (struct interface_info *,
00056 struct dhcp_packet *, unsigned,
00057 unsigned int,
00058 struct iaddr, struct hardware *);
00059
00060 #ifdef DHCPv6
00061 void (*dhcpv6_packet_handler)(struct interface_info *,
00062 const char *, int,
00063 int, const struct iaddr *,
00064 isc_boolean_t);
00065 #endif
00066
00067
00068 omapi_object_type_t *dhcp_type_interface;
00069 #if defined (TRACING)
00070 trace_type_t *interface_trace;
00071 trace_type_t *inpacket_trace;
00072 trace_type_t *outpacket_trace;
00073 #endif
00074 struct interface_info **interface_vector;
00075 int interface_count;
00076 int interface_max;
00077
00078 OMAPI_OBJECT_ALLOC (interface, struct interface_info, dhcp_type_interface)
00079
00080 isc_result_t interface_setup ()
00081 {
00082 isc_result_t status;
00083 status = omapi_object_type_register (&dhcp_type_interface,
00084 "interface",
00085 dhcp_interface_set_value,
00086 dhcp_interface_get_value,
00087 dhcp_interface_destroy,
00088 dhcp_interface_signal_handler,
00089 dhcp_interface_stuff_values,
00090 dhcp_interface_lookup,
00091 dhcp_interface_create,
00092 dhcp_interface_remove,
00093 0, 0, 0,
00094 sizeof (struct interface_info),
00095 interface_initialize, RC_MISC);
00096 if (status != ISC_R_SUCCESS)
00097 log_fatal ("Can't register interface object type: %s",
00098 isc_result_totext (status));
00099
00100 return status;
00101 }
00102
00103 #if defined (TRACING)
00104 void interface_trace_setup ()
00105 {
00106 interface_trace = trace_type_register ("interface", (void *)0,
00107 trace_interface_input,
00108 trace_interface_stop, MDL);
00109 inpacket_trace = trace_type_register ("inpacket", (void *)0,
00110 trace_inpacket_input,
00111 trace_inpacket_stop, MDL);
00112 outpacket_trace = trace_type_register ("outpacket", (void *)0,
00113 trace_outpacket_input,
00114 trace_outpacket_stop, MDL);
00115 }
00116 #endif
00117
00118 isc_result_t interface_initialize (omapi_object_t *ipo,
00119 const char *file, int line)
00120 {
00121 struct interface_info *ip = (struct interface_info *)ipo;
00122 ip -> rfdesc = ip -> wfdesc = -1;
00123 return ISC_R_SUCCESS;
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && defined(SIOCGLIFFLAGS)
00148
00149
00150
00151
00152 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
00153 # define lifc_len iflc_len
00154 # define lifc_buf iflc_buf
00155 # define lifc_req iflc_req
00156 # define LIFCONF if_laddrconf
00157 #else
00158 # define ISC_HAVE_LIFC_FAMILY 1
00159 # define ISC_HAVE_LIFC_FLAGS 1
00160 # define LIFCONF lifconf
00161 #endif
00162
00163 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
00164 # define lifr_addr iflr_addr
00165 # define lifr_name iflr_name
00166 # define lifr_dstaddr iflr_dstaddr
00167 # define lifr_flags iflr_flags
00168 # define sockaddr_storage sockaddr_ext
00169 # define ss_family sa_family
00170 # define LIFREQ if_laddrreq
00171 #else
00172 # define LIFREQ lifreq
00173 #endif
00174
00175 #ifndef IF_NAMESIZE
00176 # if defined(LIFNAMSIZ)
00177 # define IF_NAMESIZE LIFNAMSIZ
00178 # elif defined(IFNAMSIZ)
00179 # define IF_NAMESIZE IFNAMSIZ
00180 # else
00181 # define IF_NAMESIZE 16
00182 # endif
00183 #endif
00184 #elif !defined(__linux) && !defined(HAVE_IFADDRS_H)
00185 # define SIOCGLIFCONF SIOCGIFCONF
00186 # define SIOCGLIFFLAGS SIOCGIFFLAGS
00187 # define LIFREQ ifreq
00188 # define LIFCONF ifconf
00189 # define lifr_name ifr_name
00190 # define lifr_addr ifr_addr
00191 # define lifr_flags ifr_flags
00192 # define lifc_len ifc_len
00193 # define lifc_buf ifc_buf
00194 # define lifc_req ifc_req
00195 #ifdef _AIX
00196 # define ss_family __ss_family
00197 #endif
00198 #endif
00199
00200 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 struct iface_conf_list {
00215 int sock;
00216 int num;
00217 struct LIFCONF conf;
00218 int next;
00219 };
00220
00221
00222
00223
00224 struct iface_info {
00225 char name[IF_NAMESIZE+1];
00226 struct sockaddr_storage addr;
00227 isc_uint64_t flags;
00228 };
00229
00230
00231
00232
00233
00234
00235 int
00236 begin_iface_scan(struct iface_conf_list *ifaces) {
00237 #ifdef ISC_PLATFORM_HAVELIFNUM
00238 struct lifnum lifnum;
00239 #else
00240 int lifnum;
00241 #endif
00242
00243 ifaces->sock = socket(local_family, SOCK_DGRAM, IPPROTO_UDP);
00244 if (ifaces->sock < 0) {
00245 log_error("Error creating socket to list interfaces; %m");
00246 return 0;
00247 }
00248
00249 memset(&lifnum, 0, sizeof(lifnum));
00250 #ifdef ISC_PLATFORM_HAVELIFNUM
00251 lifnum.lifn_family = AF_UNSPEC;
00252 #endif
00253 #ifdef SIOCGLIFNUM
00254 if (ioctl(ifaces->sock, SIOCGLIFNUM, &lifnum) < 0) {
00255 log_error("Error finding total number of interfaces; %m");
00256 close(ifaces->sock);
00257 ifaces->sock = -1;
00258 return 0;
00259 }
00260
00261 #ifdef ISC_PLATFORM_HAVELIFNUM
00262 ifaces->num = lifnum.lifn_count;
00263 #else
00264 ifaces->num = lifnum;
00265 #endif
00266 #else
00267 ifaces->num = 64;
00268 #endif
00269
00270 memset(&ifaces->conf, 0, sizeof(ifaces->conf));
00271 #ifdef ISC_HAVE_LIFC_FAMILY
00272 ifaces->conf.lifc_family = AF_UNSPEC;
00273 #endif
00274 ifaces->conf.lifc_len = ifaces->num * sizeof(struct LIFREQ);
00275 ifaces->conf.lifc_buf = dmalloc(ifaces->conf.lifc_len, MDL);
00276 if (ifaces->conf.lifc_buf == NULL) {
00277 log_fatal("Out of memory getting interface list.");
00278 }
00279
00280 if (ioctl(ifaces->sock, SIOCGLIFCONF, &ifaces->conf) < 0) {
00281 log_error("Error getting interfaces configuration list; %m");
00282 dfree(ifaces->conf.lifc_buf, MDL);
00283 close(ifaces->sock);
00284 ifaces->sock = -1;
00285 return 0;
00286 }
00287
00288 ifaces->next = 0;
00289
00290 return 1;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299 int
00300 next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
00301 struct LIFREQ *p;
00302 struct LIFREQ tmp;
00303 isc_boolean_t foundif;
00304 #if defined(sun) || defined(__linux)
00305
00306 char *s;
00307 #endif
00308
00309 do {
00310 foundif = ISC_FALSE;
00311
00312 if (ifaces->next >= ifaces->num) {
00313 *err = 0;
00314 return 0;
00315 }
00316
00317 p = ifaces->conf.lifc_req;
00318 p += ifaces->next;
00319
00320 if (strlen(p->lifr_name) >= sizeof(info->name)) {
00321 *err = 1;
00322 log_error("Interface name '%s' too long", p->lifr_name);
00323 return 0;
00324 }
00325
00326
00327 if (p->lifr_addr.ss_family != local_family) {
00328 ifaces->next++;
00329 continue;
00330 }
00331
00332 strcpy(info->name, p->lifr_name);
00333 memset(&info->addr, 0, sizeof(info->addr));
00334 memcpy(&info->addr, &p->lifr_addr, sizeof(p->lifr_addr));
00335
00336 #if defined(sun) || defined(__linux)
00337
00338 s = strchr(info->name, ':');
00339 if (s != NULL) {
00340 *s = '\0';
00341 }
00342 #endif
00343
00344 foundif = ISC_TRUE;
00345 } while ((foundif == ISC_FALSE) ||
00346 (strncmp(info->name, "dummy", 5) == 0));
00347
00348 memset(&tmp, 0, sizeof(tmp));
00349 strcpy(tmp.lifr_name, info->name);
00350 if (ioctl(ifaces->sock, SIOCGLIFFLAGS, &tmp) < 0) {
00351 log_error("Error getting interface flags for '%s'; %m",
00352 p->lifr_name);
00353 *err = 1;
00354 return 0;
00355 }
00356 info->flags = tmp.lifr_flags;
00357
00358 ifaces->next++;
00359 *err = 0;
00360 return 1;
00361 }
00362
00363
00364
00365
00366 void
00367 end_iface_scan(struct iface_conf_list *ifaces) {
00368 dfree(ifaces->conf.lifc_buf, MDL);
00369 close(ifaces->sock);
00370 ifaces->sock = -1;
00371 }
00372
00373 #else
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 #include <ifaddrs.h>
00386
00387
00388
00389
00390 struct iface_conf_list {
00391 struct ifaddrs *head;
00392 struct ifaddrs *next;
00393 };
00394
00395
00396
00397
00398 struct iface_info {
00399 char name[IFNAMSIZ];
00400 struct sockaddr_storage addr;
00401 isc_uint64_t flags;
00402 };
00403
00404
00405
00406
00407
00408
00409 int
00410 begin_iface_scan(struct iface_conf_list *ifaces) {
00411 if (getifaddrs(&ifaces->head) != 0) {
00412 log_error("Error getting interfaces; %m");
00413 return 0;
00414 }
00415 ifaces->next = ifaces->head;
00416 return 1;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 int
00426 next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
00427 size_t sa_len = 0;
00428
00429 if (ifaces->next == NULL) {
00430 *err = 0;
00431 return 0;
00432 }
00433 if (strlen(ifaces->next->ifa_name) >= sizeof(info->name)) {
00434 log_error("Interface name '%s' too long",
00435 ifaces->next->ifa_name);
00436 *err = 1;
00437 return 0;
00438 }
00439 strcpy(info->name, ifaces->next->ifa_name);
00440
00441 memset(&info->addr, 0 , sizeof(info->addr));
00442
00443 if (ifaces->next->ifa_addr != NULL) {
00444 #ifdef HAVE_SA_LEN
00445 sa_len = ifaces->next->ifa_addr->sa_len;
00446 #else
00447 if (ifaces->next->ifa_addr->sa_family == AF_INET)
00448 sa_len = sizeof(struct sockaddr_in);
00449 else if (ifaces->next->ifa_addr->sa_family == AF_INET6)
00450 sa_len = sizeof(struct sockaddr_in6);
00451 #endif
00452 memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
00453 }
00454 info->flags = ifaces->next->ifa_flags;
00455 ifaces->next = ifaces->next->ifa_next;
00456 *err = 0;
00457 return 1;
00458 }
00459
00460
00461
00462
00463 void
00464 end_iface_scan(struct iface_conf_list *ifaces) {
00465 freeifaddrs(ifaces->head);
00466 ifaces->head = NULL;
00467 ifaces->next = NULL;
00468 }
00469 #endif
00470
00471
00472 void
00473 add_ipv4_addr_to_interface(struct interface_info *iface,
00474 const struct in_addr *addr) {
00475
00476
00477
00478
00479 if (iface->addresses == NULL) {
00480 iface->addresses = dmalloc(4 * sizeof(struct in_addr), MDL);
00481 if (iface->addresses == NULL) {
00482 log_fatal("Out of memory saving IPv4 address "
00483 "on interface.");
00484 }
00485 iface->address_count = 0;
00486 iface->address_max = 4;
00487 } else if (iface->address_count >= iface->address_max) {
00488 struct in_addr *tmp;
00489 int new_max;
00490
00491 new_max = iface->address_max + 4;
00492 tmp = dmalloc(new_max * sizeof(struct in_addr), MDL);
00493 if (tmp == NULL) {
00494 log_fatal("Out of memory saving IPv4 address "
00495 "on interface.");
00496 }
00497 memcpy(tmp,
00498 iface->addresses,
00499 iface->address_max * sizeof(struct in_addr));
00500 dfree(iface->addresses, MDL);
00501 iface->addresses = tmp;
00502 iface->address_max = new_max;
00503 }
00504 iface->addresses[iface->address_count++] = *addr;
00505 }
00506
00507 #ifdef DHCPv6
00508
00509 void
00510 add_ipv6_addr_to_interface(struct interface_info *iface,
00511 const struct in6_addr *addr) {
00512
00513
00514
00515
00516
00517 if (iface->v6addresses == NULL) {
00518 iface->v6addresses = dmalloc(8 * sizeof(struct in6_addr), MDL);
00519 if (iface->v6addresses == NULL) {
00520 log_fatal("Out of memory saving IPv6 address "
00521 "on interface.");
00522 }
00523 iface->v6address_count = 0;
00524 iface->v6address_max = 8;
00525 } else if (iface->v6address_count >= iface->v6address_max) {
00526 struct in6_addr *tmp;
00527 int new_max;
00528
00529 new_max = iface->v6address_max + 8;
00530 tmp = dmalloc(new_max * sizeof(struct in6_addr), MDL);
00531 if (tmp == NULL) {
00532 log_fatal("Out of memory saving IPv6 address "
00533 "on interface.");
00534 }
00535 memcpy(tmp,
00536 iface->v6addresses,
00537 iface->v6address_max * sizeof(struct in6_addr));
00538 dfree(iface->v6addresses, MDL);
00539 iface->v6addresses = tmp;
00540 iface->v6address_max = new_max;
00541 }
00542 iface->v6addresses[iface->v6address_count++] = *addr;
00543 }
00544 #endif
00545
00546
00547
00548
00549
00550
00551 void
00552 discover_interfaces(int state) {
00553 struct iface_conf_list ifaces;
00554 struct iface_info info;
00555 int err;
00556
00557 struct interface_info *tmp;
00558 struct interface_info *last, *next;
00559
00560 #ifdef DHCPv6
00561 char abuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
00562 #endif
00563
00564
00565 struct subnet *subnet;
00566 int ir;
00567 isc_result_t status;
00568 int wifcount = 0;
00569
00570 static int setup_fallback = 0;
00571
00572 if (!begin_iface_scan(&ifaces)) {
00573 log_fatal("Can't get list of interfaces.");
00574 }
00575
00576
00577
00578 if (interfaces && (state == DISCOVER_SERVER ||
00579 state == DISCOVER_RELAY ||
00580 state == DISCOVER_REQUESTED))
00581 ir = 0;
00582 else if (state == DISCOVER_UNCONFIGURED)
00583 ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC;
00584 else
00585 ir = INTERFACE_REQUESTED;
00586
00587
00588 while (next_iface(&info, &err, &ifaces)) {
00589
00590
00591 for (tmp = interfaces; tmp; tmp = tmp->next) {
00592 if (!strcmp(tmp->name, info.name))
00593 break;
00594 }
00595
00596
00597
00598
00599
00600 if ((((local_family == AF_INET &&
00601 !(info.flags & IFF_BROADCAST)) ||
00602 #ifdef DHCPv6
00603 (local_family == AF_INET6 &&
00604 !(info.flags & IFF_MULTICAST)) ||
00605 #endif
00606 info.flags & IFF_LOOPBACK ||
00607 info.flags & IFF_POINTOPOINT) && !tmp) ||
00608 (!(info.flags & IFF_UP) &&
00609 state != DISCOVER_UNCONFIGURED))
00610 continue;
00611
00612
00613
00614 if (tmp == NULL) {
00615 status = interface_allocate(&tmp, MDL);
00616 if (status != ISC_R_SUCCESS) {
00617 log_fatal("Error allocating interface %s: %s",
00618 info.name, isc_result_totext(status));
00619 }
00620 strcpy(tmp->name, info.name);
00621 interface_snorf(tmp, ir);
00622 interface_dereference(&tmp, MDL);
00623 tmp = interfaces;
00624 }
00625
00626 if (dhcp_interface_discovery_hook) {
00627 (*dhcp_interface_discovery_hook)(tmp);
00628 }
00629
00630 if ((info.addr.ss_family == AF_INET) &&
00631 (local_family == AF_INET)) {
00632 struct sockaddr_in *a = (struct sockaddr_in*)&info.addr;
00633 struct iaddr addr;
00634
00635
00636 if (a->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
00637 ((tmp->flags & INTERFACE_AUTOMATIC) &&
00638 state == DISCOVER_SERVER))
00639 continue;
00640
00641
00642
00643 if (a->sin_addr.s_addr != htonl(INADDR_ANY))
00644 tmp->configured = 1;
00645
00646 add_ipv4_addr_to_interface(tmp, &a->sin_addr);
00647
00648
00649 addr.len = 4;
00650 memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len);
00651 if (dhcp_interface_setup_hook) {
00652 (*dhcp_interface_setup_hook)(tmp, &addr);
00653 }
00654 }
00655 #ifdef DHCPv6
00656 else if ((info.addr.ss_family == AF_INET6) &&
00657 (local_family == AF_INET6)) {
00658 struct sockaddr_in6 *a =
00659 (struct sockaddr_in6*)&info.addr;
00660 struct iaddr addr;
00661
00662
00663 if (IN6_IS_ADDR_LOOPBACK(&a->sin6_addr) &&
00664 ((tmp->flags & INTERFACE_AUTOMATIC) &&
00665 state == DISCOVER_SERVER))
00666 continue;
00667
00668
00669
00670 if (IN6_IS_ADDR_UNSPECIFIED(&a->sin6_addr))
00671 tmp->configured = 1;
00672
00673 add_ipv6_addr_to_interface(tmp, &a->sin6_addr);
00674
00675
00676 addr.len = 16;
00677 memcpy(addr.iabuf, &a->sin6_addr, addr.len);
00678 if (dhcp_interface_setup_hook) {
00679 (*dhcp_interface_setup_hook)(tmp, &addr);
00680 }
00681 }
00682 #endif
00683 }
00684
00685 if (err) {
00686 log_fatal("Error getting interface information.");
00687 }
00688
00689 end_iface_scan(&ifaces);
00690
00691
00692
00693
00694
00695
00696 for (tmp = interfaces ; tmp != NULL ; tmp = tmp->next) {
00697 if (tmp->ifp == NULL) {
00698 struct ifreq *tif;
00699
00700 tif = (struct ifreq *)dmalloc(sizeof(struct ifreq),
00701 MDL);
00702 if (tif == NULL)
00703 log_fatal("no space for ifp mockup.");
00704 strcpy(tif->ifr_name, tmp->name);
00705 tmp->ifp = tif;
00706 }
00707 }
00708
00709
00710
00711
00712 if (state == DISCOVER_UNCONFIGURED) {
00713 return;
00714 }
00715
00716
00717 tmp = last = next = NULL;
00718 if (interfaces)
00719 interface_reference (&tmp, interfaces, MDL);
00720 while (tmp) {
00721 if (next)
00722 interface_dereference (&next, MDL);
00723 if (tmp -> next)
00724 interface_reference (&next, tmp -> next, MDL);
00725
00726 if (tmp -> flags & INTERFACE_RUNNING) {
00727 interface_dereference(&tmp, MDL);
00728 if(next)
00729 interface_reference(&tmp, next, MDL);
00730 continue;
00731 }
00732 if ((tmp -> flags & INTERFACE_AUTOMATIC) &&
00733 state == DISCOVER_REQUESTED)
00734 tmp -> flags &= ~(INTERFACE_AUTOMATIC |
00735 INTERFACE_REQUESTED);
00736
00737 #ifdef DHCPv6
00738 if (!(tmp->flags & INTERFACE_REQUESTED)) {
00739 #else
00740 if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {
00741 #endif
00742 if ((tmp -> flags & INTERFACE_REQUESTED) != ir)
00743 log_fatal ("%s: not found", tmp -> name);
00744 if (!last) {
00745 if (interfaces)
00746 interface_dereference (&interfaces,
00747 MDL);
00748 if (next)
00749 interface_reference (&interfaces, next, MDL);
00750 } else {
00751 interface_dereference (&last -> next, MDL);
00752 if (next)
00753 interface_reference (&last -> next,
00754 next, MDL);
00755 }
00756 if (tmp -> next)
00757 interface_dereference (&tmp -> next, MDL);
00758
00759
00760
00761 if (dummy_interfaces) {
00762 interface_reference (&tmp -> next,
00763 dummy_interfaces, MDL);
00764 interface_dereference (&dummy_interfaces, MDL);
00765 }
00766 interface_reference (&dummy_interfaces, tmp, MDL);
00767 interface_dereference (&tmp, MDL);
00768 if (next)
00769 interface_reference (&tmp, next, MDL);
00770 continue;
00771 }
00772 last = tmp;
00773
00774
00775 if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
00776 log_info("%s", "");
00777 if (local_family == AF_INET) {
00778 log_info("No subnet declaration for %s (%s).",
00779 tmp->name,
00780 (tmp->addresses == NULL) ?
00781 "no IPv4 addresses" :
00782 inet_ntoa(tmp->addresses[0]));
00783 #ifdef DHCPv6
00784 } else {
00785 if (tmp->v6addresses != NULL) {
00786 inet_ntop(AF_INET6,
00787 &tmp->v6addresses[0],
00788 abuf,
00789 sizeof(abuf));
00790 } else {
00791 strcpy(abuf, "no IPv6 addresses");
00792 }
00793 log_info("No subnet6 declaration for %s (%s).",
00794 tmp->name,
00795 abuf);
00796 #endif
00797 }
00798 if (supports_multiple_interfaces(tmp)) {
00799 log_info ("** Ignoring requests on %s. %s",
00800 tmp -> name, "If this is not what");
00801 log_info (" you want, please write %s",
00802 #ifdef DHCPv6
00803 (local_family != AF_INET) ?
00804 "a subnet6 declaration" :
00805 #endif
00806 "a subnet declaration");
00807 log_info (" in your dhcpd.conf file %s",
00808 "for the network segment");
00809 log_info (" to %s %s %s",
00810 "which interface",
00811 tmp -> name, "is attached. **");
00812 log_info ("%s", "");
00813 goto next;
00814 } else {
00815 log_error ("You must write a %s",
00816 #ifdef DHCPv6
00817 (local_family != AF_INET) ?
00818 "subnet6 declaration for this" :
00819 #endif
00820 "subnet declaration for this");
00821 log_error ("subnet. You cannot prevent %s",
00822 "the DHCP server");
00823 log_error ("from listening on this subnet %s",
00824 "because your");
00825 log_fatal ("operating system does not %s.",
00826 "support this capability");
00827 }
00828 }
00829
00830
00831
00832 for (subnet = (tmp -> shared_network
00833 ? tmp -> shared_network -> subnets
00834 : (struct subnet *)0);
00835 subnet; subnet = subnet -> next_sibling) {
00836
00837
00838 if (subnet->interface_address.len == 0) {
00839 if (tmp->address_count > 0) {
00840 subnet->interface_address.len = 4;
00841 memcpy(subnet->interface_address.iabuf,
00842 &tmp->addresses[0].s_addr, 4);
00843 } else if (tmp->v6address_count > 0) {
00844 subnet->interface_address.len = 16;
00845 memcpy(subnet->interface_address.iabuf,
00846 &tmp->v6addresses[0].s6_addr,
00847 16);
00848 } else {
00849
00850 log_error("%s missing an interface "
00851 "address", tmp->name);
00852 continue;
00853 }
00854 }
00855 }
00856
00857
00858
00859 tmp -> index = -1;
00860
00861
00862 if (local_family == AF_INET) {
00863 if_register_receive(tmp);
00864 if_register_send(tmp);
00865 #ifdef DHCPv6
00866 } else {
00867 if ((state == DISCOVER_SERVER) ||
00868 (state == DISCOVER_RELAY)) {
00869 if_register6(tmp, 1);
00870 } else {
00871 if_register_linklocal6(tmp);
00872 }
00873 #endif
00874 }
00875
00876 interface_stash (tmp);
00877 wifcount++;
00878 #if defined (F_SETFD)
00879 if (fcntl (tmp -> rfdesc, F_SETFD, 1) < 0)
00880 log_error ("Can't set close-on-exec on %s: %m",
00881 tmp -> name);
00882 if (tmp -> rfdesc != tmp -> wfdesc) {
00883 if (fcntl (tmp -> wfdesc, F_SETFD, 1) < 0)
00884 log_error ("Can't set close-on-exec on %s: %m",
00885 tmp -> name);
00886 }
00887 #endif
00888 next:
00889 interface_dereference (&tmp, MDL);
00890 if (next)
00891 interface_reference (&tmp, next, MDL);
00892 }
00893
00894
00895
00896
00897
00898
00899
00900 for (tmp = interfaces; tmp; tmp = tmp -> next) {
00901
00902 if (tmp -> flags & INTERFACE_RUNNING)
00903 continue;
00904 if (tmp -> rfdesc == -1)
00905 continue;
00906 switch (local_family) {
00907 #ifdef DHCPv6
00908 case AF_INET6:
00909 status = omapi_register_io_object((omapi_object_t *)tmp,
00910 if_readsocket,
00911 0, got_one_v6, 0, 0);
00912 break;
00913 #endif
00914 case AF_INET:
00915 default:
00916 status = omapi_register_io_object((omapi_object_t *)tmp,
00917 if_readsocket,
00918 0, got_one, 0, 0);
00919 break;
00920 }
00921
00922 if (status != ISC_R_SUCCESS)
00923 log_fatal ("Can't register I/O handle for %s: %s",
00924 tmp -> name, isc_result_totext (status));
00925
00926 #if defined(DHCPv6)
00927
00928
00929
00930
00931
00932
00933 if (((state == DISCOVER_SERVER) || (state == DISCOVER_RELAY)) &&
00934 (local_family == AF_INET6))
00935 break;
00936 #endif
00937 }
00938
00939 if (state == DISCOVER_SERVER && wifcount == 0) {
00940 log_info ("%s", "");
00941 log_fatal ("Not configured to listen on any interfaces!");
00942 }
00943
00944 if ((local_family == AF_INET) && !setup_fallback) {
00945 setup_fallback = 1;
00946 maybe_setup_fallback();
00947 }
00948
00949 #if defined (F_SETFD)
00950 if (fallback_interface) {
00951 if (fcntl (fallback_interface -> rfdesc, F_SETFD, 1) < 0)
00952 log_error ("Can't set close-on-exec on fallback: %m");
00953 if (fallback_interface -> rfdesc != fallback_interface -> wfdesc) {
00954 if (fcntl (fallback_interface -> wfdesc, F_SETFD, 1) < 0)
00955 log_error ("Can't set close-on-exec on fallback: %m");
00956 }
00957 }
00958 #endif
00959 }
00960
00961 int if_readsocket (h)
00962 omapi_object_t *h;
00963 {
00964 struct interface_info *ip;
00965
00966 if (h -> type != dhcp_type_interface)
00967 return -1;
00968 ip = (struct interface_info *)h;
00969 return ip -> rfdesc;
00970 }
00971
00972 int setup_fallback (struct interface_info **fp, const char *file, int line)
00973 {
00974 isc_result_t status;
00975
00976 status = interface_allocate (&fallback_interface, file, line);
00977 if (status != ISC_R_SUCCESS)
00978 log_fatal ("Error allocating fallback interface: %s",
00979 isc_result_totext (status));
00980 strcpy (fallback_interface -> name, "fallback");
00981 if (dhcp_interface_setup_hook)
00982 (*dhcp_interface_setup_hook) (fallback_interface,
00983 (struct iaddr *)0);
00984 status = interface_reference (fp, fallback_interface, file, line);
00985
00986 fallback_interface -> index = -1;
00987 interface_stash (fallback_interface);
00988 return status == ISC_R_SUCCESS;
00989 }
00990
00991 void reinitialize_interfaces ()
00992 {
00993 struct interface_info *ip;
00994
00995 for (ip = interfaces; ip; ip = ip -> next) {
00996 if_reinitialize_receive (ip);
00997 if_reinitialize_send (ip);
00998 }
00999
01000 if (fallback_interface)
01001 if_reinitialize_send (fallback_interface);
01002
01003 interfaces_invalidated = 1;
01004 }
01005
01006 isc_result_t got_one (h)
01007 omapi_object_t *h;
01008 {
01009 struct sockaddr_in from;
01010 struct hardware hfrom;
01011 struct iaddr ifrom;
01012 int result;
01013 union {
01014 unsigned char packbuf [4095];
01015
01016
01017 struct dhcp_packet packet;
01018 } u;
01019 struct interface_info *ip;
01020
01021 if (h -> type != dhcp_type_interface)
01022 return DHCP_R_INVALIDARG;
01023 ip = (struct interface_info *)h;
01024
01025 again:
01026 if ((result =
01027 receive_packet (ip, u.packbuf, sizeof u, &from, &hfrom)) < 0) {
01028 log_error ("receive_packet failed on %s: %m", ip -> name);
01029 return ISC_R_UNEXPECTED;
01030 }
01031 if (result == 0)
01032 return ISC_R_UNEXPECTED;
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 if (result < DHCP_FIXED_NON_UDP)
01044 return ISC_R_UNEXPECTED;
01045
01046 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
01047 {
01048
01049 unsigned int ifindex;
01050
01051 memcpy(&ifindex, hfrom.hbuf, sizeof (ifindex));
01052
01053
01054
01055
01056
01057 ip = interfaces;
01058 while ((ip != NULL) && (if_nametoindex(ip->name) != ifindex))
01059 ip = ip->next;
01060 if (ip == NULL)
01061 return ISC_R_NOTFOUND;
01062 }
01063 #endif
01064
01065 if (bootp_packet_handler) {
01066 ifrom.len = 4;
01067 memcpy (ifrom.iabuf, &from.sin_addr, ifrom.len);
01068
01069 (*bootp_packet_handler) (ip, &u.packet, (unsigned)result,
01070 from.sin_port, ifrom, &hfrom);
01071 }
01072
01073
01074
01075 if (ip -> rbuf_offset != ip -> rbuf_len)
01076 goto again;
01077 return ISC_R_SUCCESS;
01078 }
01079
01080 #ifdef DHCPv6
01081 isc_result_t
01082 got_one_v6(omapi_object_t *h) {
01083 struct sockaddr_in6 from;
01084 struct in6_addr to;
01085 struct iaddr ifrom;
01086 int result;
01087 char buf[65536];
01088 struct interface_info *ip;
01089 int is_unicast;
01090 unsigned int if_idx = 0;
01091
01092 if (h->type != dhcp_type_interface) {
01093 return DHCP_R_INVALIDARG;
01094 }
01095 ip = (struct interface_info *)h;
01096
01097 result = receive_packet6(ip, (unsigned char *)buf, sizeof(buf),
01098 &from, &to, &if_idx);
01099 if (result < 0) {
01100 log_error("receive_packet6() failed on %s: %m", ip->name);
01101 return ISC_R_UNEXPECTED;
01102 }
01103
01104
01105 if (if_idx == 0)
01106 return ISC_R_NOTFOUND;
01107
01108 if (dhcpv6_packet_handler != NULL) {
01109
01110
01111
01112 if (IN6_IS_ADDR_MULTICAST(&to)) {
01113 is_unicast = ISC_FALSE;
01114 } else {
01115 is_unicast = ISC_TRUE;
01116 }
01117
01118 ifrom.len = 16;
01119 memcpy(ifrom.iabuf, &from.sin6_addr, ifrom.len);
01120
01121
01122 ip = interfaces;
01123 while ((ip != NULL) && (if_nametoindex(ip->name) != if_idx))
01124 ip = ip->next;
01125
01126 if (ip == NULL)
01127 return ISC_R_NOTFOUND;
01128
01129 (*dhcpv6_packet_handler)(ip, buf,
01130 result, from.sin6_port,
01131 &ifrom, is_unicast);
01132 }
01133
01134 return ISC_R_SUCCESS;
01135 }
01136 #endif
01137
01138 isc_result_t dhcp_interface_set_value (omapi_object_t *h,
01139 omapi_object_t *id,
01140 omapi_data_string_t *name,
01141 omapi_typed_data_t *value)
01142 {
01143 struct interface_info *interface;
01144 isc_result_t status;
01145
01146 if (h -> type != dhcp_type_interface)
01147 return DHCP_R_INVALIDARG;
01148 interface = (struct interface_info *)h;
01149
01150 if (!omapi_ds_strcmp (name, "name")) {
01151 if ((value -> type == omapi_datatype_data ||
01152 value -> type == omapi_datatype_string) &&
01153 value -> u.buffer.len < sizeof interface -> name) {
01154 memcpy (interface -> name,
01155 value -> u.buffer.value,
01156 value -> u.buffer.len);
01157 interface -> name [value -> u.buffer.len] = 0;
01158 } else
01159 return DHCP_R_INVALIDARG;
01160 return ISC_R_SUCCESS;
01161 }
01162
01163
01164 if (h -> inner && h -> inner -> type -> set_value) {
01165 status = ((*(h -> inner -> type -> set_value))
01166 (h -> inner, id, name, value));
01167 if (status == ISC_R_SUCCESS || status == DHCP_R_UNCHANGED)
01168 return status;
01169 }
01170
01171 return ISC_R_NOTFOUND;
01172 }
01173
01174
01175 isc_result_t dhcp_interface_get_value (omapi_object_t *h,
01176 omapi_object_t *id,
01177 omapi_data_string_t *name,
01178 omapi_value_t **value)
01179 {
01180 return ISC_R_NOTIMPLEMENTED;
01181 }
01182
01183 isc_result_t dhcp_interface_destroy (omapi_object_t *h,
01184 const char *file, int line)
01185 {
01186 struct interface_info *interface;
01187
01188 if (h -> type != dhcp_type_interface)
01189 return DHCP_R_INVALIDARG;
01190 interface = (struct interface_info *)h;
01191
01192 if (interface -> ifp) {
01193 dfree (interface -> ifp, file, line);
01194 interface -> ifp = 0;
01195 }
01196 if (interface -> next)
01197 interface_dereference (&interface -> next, file, line);
01198 if (interface -> rbuf) {
01199 dfree (interface -> rbuf, file, line);
01200 interface -> rbuf = (unsigned char *)0;
01201 }
01202 if (interface -> client)
01203 interface -> client = (struct client_state *)0;
01204
01205 if (interface -> shared_network)
01206 omapi_object_dereference ((omapi_object_t **)
01207 &interface -> shared_network, MDL);
01208
01209 return ISC_R_SUCCESS;
01210 }
01211
01212 isc_result_t dhcp_interface_signal_handler (omapi_object_t *h,
01213 const char *name, va_list ap)
01214 {
01215 struct interface_info *ip, *interface;
01216 isc_result_t status;
01217
01218 if (h -> type != dhcp_type_interface)
01219 return DHCP_R_INVALIDARG;
01220 interface = (struct interface_info *)h;
01221
01222
01223
01224 if (!strcmp (name, "update")) {
01225 for (ip = dummy_interfaces; ip; ip = ip -> next)
01226 if (ip == interface)
01227 break;
01228 if (ip && dhcp_interface_startup_hook)
01229 return (*dhcp_interface_startup_hook) (ip);
01230
01231 for (ip = interfaces; ip; ip = ip -> next)
01232 if (ip == interface)
01233 break;
01234 if (!ip && dhcp_interface_startup_hook)
01235 return (*dhcp_interface_startup_hook) (ip);
01236 }
01237
01238
01239 if (h -> inner && h -> inner -> type -> signal_handler) {
01240 status = ((*(h -> inner -> type -> signal_handler))
01241 (h -> inner, name, ap));
01242 if (status == ISC_R_SUCCESS)
01243 return status;
01244 }
01245 return ISC_R_NOTFOUND;
01246 }
01247
01248 isc_result_t dhcp_interface_stuff_values (omapi_object_t *c,
01249 omapi_object_t *id,
01250 omapi_object_t *h)
01251 {
01252 struct interface_info *interface;
01253 isc_result_t status;
01254
01255 if (h -> type != dhcp_type_interface)
01256 return DHCP_R_INVALIDARG;
01257 interface = (struct interface_info *)h;
01258
01259
01260
01261 status = omapi_connection_put_name (c, "state");
01262 if (status != ISC_R_SUCCESS)
01263 return status;
01264 if ((interface->flags & INTERFACE_REQUESTED) != 0)
01265 status = omapi_connection_put_string (c, "up");
01266 else
01267 status = omapi_connection_put_string (c, "down");
01268 if (status != ISC_R_SUCCESS)
01269 return status;
01270
01271
01272 if (h -> inner && h -> inner -> type -> stuff_values) {
01273 status = ((*(h -> inner -> type -> stuff_values))
01274 (c, id, h -> inner));
01275 if (status == ISC_R_SUCCESS)
01276 return status;
01277 }
01278
01279 return ISC_R_SUCCESS;
01280 }
01281
01282 isc_result_t dhcp_interface_lookup (omapi_object_t **ip,
01283 omapi_object_t *id,
01284 omapi_object_t *ref)
01285 {
01286 omapi_value_t *tv = (omapi_value_t *)0;
01287 isc_result_t status;
01288 struct interface_info *interface;
01289
01290 if (!ref)
01291 return DHCP_R_NOKEYS;
01292
01293
01294 status = omapi_get_value_str (ref, id, "handle", &tv);
01295 if (status == ISC_R_SUCCESS) {
01296 status = omapi_handle_td_lookup (ip, tv -> value);
01297
01298 omapi_value_dereference (&tv, MDL);
01299 if (status != ISC_R_SUCCESS)
01300 return status;
01301
01302
01303 if ((*ip) -> type != dhcp_type_interface) {
01304 omapi_object_dereference (ip, MDL);
01305 return DHCP_R_INVALIDARG;
01306 }
01307 }
01308
01309
01310 status = omapi_get_value_str (ref, id, "name", &tv);
01311 if (status == ISC_R_SUCCESS) {
01312 char *s;
01313 unsigned len;
01314 for (interface = interfaces; interface;
01315 interface = interface -> next) {
01316 s = memchr (interface -> name, 0, IFNAMSIZ);
01317 if (s)
01318 len = s - &interface -> name [0];
01319 else
01320 len = IFNAMSIZ;
01321 if ((tv -> value -> u.buffer.len == len &&
01322 !memcmp (interface -> name,
01323 (char *)tv -> value -> u.buffer.value,
01324 len)))
01325 break;
01326 }
01327 if (!interface) {
01328 for (interface = dummy_interfaces;
01329 interface; interface = interface -> next) {
01330 s = memchr (interface -> name, 0, IFNAMSIZ);
01331 if (s)
01332 len = s - &interface -> name [0];
01333 else
01334 len = IFNAMSIZ;
01335 if ((tv -> value -> u.buffer.len == len &&
01336 !memcmp (interface -> name,
01337 (char *)
01338 tv -> value -> u.buffer.value,
01339 len)))
01340 break;
01341 }
01342 }
01343
01344 omapi_value_dereference (&tv, MDL);
01345 if (*ip && *ip != (omapi_object_t *)interface) {
01346 omapi_object_dereference (ip, MDL);
01347 return DHCP_R_KEYCONFLICT;
01348 } else if (!interface) {
01349 if (*ip)
01350 omapi_object_dereference (ip, MDL);
01351 return ISC_R_NOTFOUND;
01352 } else if (!*ip)
01353 omapi_object_reference (ip,
01354 (omapi_object_t *)interface,
01355 MDL);
01356 }
01357
01358
01359
01360 if (!*ip)
01361 return DHCP_R_NOKEYS;
01362 return ISC_R_SUCCESS;
01363 }
01364
01365
01366 isc_result_t dhcp_interface_create (omapi_object_t **lp,
01367 omapi_object_t *id)
01368 {
01369 struct interface_info *hp;
01370 isc_result_t status;
01371
01372 hp = (struct interface_info *)0;
01373 status = interface_allocate (&hp, MDL);
01374 if (status != ISC_R_SUCCESS)
01375 return status;
01376 hp -> flags = INTERFACE_REQUESTED;
01377 status = interface_reference ((struct interface_info **)lp, hp, MDL);
01378 interface_dereference (&hp, MDL);
01379 return status;
01380 }
01381
01382 isc_result_t dhcp_interface_remove (omapi_object_t *lp,
01383 omapi_object_t *id)
01384 {
01385 struct interface_info *interface, *ip, *last;
01386
01387 interface = (struct interface_info *)lp;
01388
01389
01390 last = 0;
01391 for (ip = interfaces; ip; ip = ip -> next) {
01392 if (ip == interface) {
01393 if (last) {
01394 interface_dereference (&last -> next, MDL);
01395 if (ip -> next)
01396 interface_reference (&last -> next,
01397 ip -> next, MDL);
01398 } else {
01399 interface_dereference (&interfaces, MDL);
01400 if (ip -> next)
01401 interface_reference (&interfaces,
01402 ip -> next, MDL);
01403 }
01404 if (ip -> next)
01405 interface_dereference (&ip -> next, MDL);
01406 break;
01407 }
01408 last = ip;
01409 }
01410 if (!ip)
01411 return ISC_R_NOTFOUND;
01412
01413
01414 if (dummy_interfaces) {
01415 interface_reference (&interface -> next,
01416 dummy_interfaces, MDL);
01417 interface_dereference (&dummy_interfaces, MDL);
01418 }
01419 interface_reference (&dummy_interfaces, interface, MDL);
01420
01421
01422 if (dhcp_interface_shutdown_hook)
01423 (*dhcp_interface_shutdown_hook) (interface);
01424
01425
01426 omapi_unregister_io_object ((omapi_object_t *)interface);
01427
01428 switch(local_family) {
01429 #ifdef DHCPv6
01430 case AF_INET6:
01431 if_deregister6(interface);
01432 break;
01433 #endif
01434 case AF_INET:
01435 default:
01436 if_deregister_send(interface);
01437 if_deregister_receive(interface);
01438 break;
01439 }
01440
01441 return ISC_R_SUCCESS;
01442 }
01443
01444 void interface_stash (struct interface_info *tptr)
01445 {
01446 struct interface_info **vec;
01447 int delta;
01448
01449
01450 if (tptr -> index == -1) {
01451 tptr -> index = interface_count++;
01452 while (tptr -> index < interface_max &&
01453 interface_vector [tptr -> index])
01454 tptr -> index = interface_count++;
01455 }
01456
01457 if (interface_max <= tptr -> index) {
01458 delta = tptr -> index - interface_max + 10;
01459 vec = dmalloc ((interface_max + delta) *
01460 sizeof (struct interface_info *), MDL);
01461 if (!vec)
01462 return;
01463 memset (&vec [interface_max], 0,
01464 (sizeof (struct interface_info *)) * delta);
01465 interface_max += delta;
01466 if (interface_vector) {
01467 memcpy (vec, interface_vector,
01468 (interface_count *
01469 sizeof (struct interface_info *)));
01470 dfree (interface_vector, MDL);
01471 }
01472 interface_vector = vec;
01473 }
01474 interface_reference (&interface_vector [tptr -> index], tptr, MDL);
01475 if (tptr -> index >= interface_count)
01476 interface_count = tptr -> index + 1;
01477 #if defined (TRACING)
01478 trace_interface_register (interface_trace, tptr);
01479 #endif
01480 }
01481
01482 void interface_snorf (struct interface_info *tmp, int ir)
01483 {
01484 tmp -> circuit_id = (u_int8_t *)tmp -> name;
01485 tmp -> circuit_id_len = strlen (tmp -> name);
01486 tmp -> remote_id = 0;
01487 tmp -> remote_id_len = 0;
01488 tmp -> flags = ir;
01489 if (interfaces) {
01490 interface_reference (&tmp -> next,
01491 interfaces, MDL);
01492 interface_dereference (&interfaces, MDL);
01493 }
01494 interface_reference (&interfaces, tmp, MDL);
01495 }