From: Shane Kerr Date: Wed, 16 May 2007 22:27:35 +0000 (+0000) Subject: FreeBSD, NetBSD, OpenBSD support added in (again). X-Git-Tag: v4_0_0a1~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=99fe695e1c6a409986e88d15a1448ffcc1de0a51;p=thirdparty%2Fdhcp.git FreeBSD, NetBSD, OpenBSD support added in (again). See RT ticket #16865 for more (still expect some warnings). --- diff --git a/RELNOTES b/RELNOTES index c87ad4e1a..5a4c5c180 100644 --- a/RELNOTES +++ b/RELNOTES @@ -21,7 +21,7 @@ pages. There are a number of DHCPv6 limitiations and features missing in this release, which will be addressed shortly: -- Only Solaris and Linux are supported. +- Only Solaris, Linux, FreeBSD, NetBSD, and OpenBSD are supported. - There is no DHCPv6 Relay support. diff --git a/common/bpf.c b/common/bpf.c index aa3fd9d2b..e3a4e11d8 100644 --- a/common/bpf.c +++ b/common/bpf.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: bpf.c,v 1.51 2007/04/27 23:54:05 each Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +"$Id: bpf.c,v 1.52 2007/05/16 22:27:34 shane Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -59,6 +59,8 @@ static char copyright[] = #include "includes/netinet/if_ether.h" #endif +#include + /* Reinitializes the specified interface after an address change. This is not required for packet-filter APIs. */ @@ -543,4 +545,60 @@ void maybe_setup_fallback () interface_dereference (&fbi, MDL); } } + +void +get_hw_addr(const char *name, struct hardware *hw) { + struct ifaddrs *ifa; + struct ifaddrs *p; + struct sockaddr *sa; + + if (getifaddrs(&ifa) != 0) { + log_fatal("Error getting interface information; %m"); + } + + /* + * Loop through our interfaces finding a match. + */ + sa = NULL; + for (p=ifa; (p != NULL) && (sa == NULL); p = p->ifa_next) { + if ((p->ifa_addr->sa_family == AF_LINK) && + !strcmp(p->ifa_name, name)) { + sa = p->ifa_addr; + } + } + if (sa == NULL) { + log_fatal("No interface called '%s'", name); + } + + /* + * Pull out the appropriate information. + */ + switch (sa->sa_family) { + case ARPHRD_ETHER: + hw->hlen = 7; + hw->hbuf[0] = HTYPE_ETHER; + memcpy(&hw->hbuf[1], sa->sa_data, 6); + break; + case ARPHRD_IEEE802: +#ifdef ARPHRD_IEEE802_TR + case ARPHRD_IEEE802_TR: +#endif /* ARPHRD_IEEE802_TR */ + hw->hlen = 7; + hw->hbuf[0] = HTYPE_IEEE802; + memcpy(&hw->hbuf[1], sa->sa_data, 6); + break; +#ifdef ARPHRD_FDDI + case ARPHRD_FDDI: + hw->hlen = 17; + hw->hbuf[0] = HTYPE_FDDI; + memcpy(&hw->hbuf[1], sa->sa_data, 16); + break; +#endif /* ARPHRD_FDDI */ + default: + log_fatal("Unsupported device type %d for \"%s\"", + sa->sa_family, name); + } + + freeifaddrs(ifa); +} #endif diff --git a/common/discover.c b/common/discover.c index f2442916c..86ec83547 100644 --- a/common/discover.c +++ b/common/discover.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: discover.c,v 1.53 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; +"$Id: discover.c,v 1.54 2007/05/16 22:27:34 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -225,7 +225,7 @@ begin_iface_scan(struct iface_conf_list *ifaces) { * Retrieve the next interface. * * Returns information in the info structure. - * Sets err to 1 if there is an error, otherwise 1. + * Sets err to 1 if there is an error, otherwise 0. */ int next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { @@ -635,7 +635,7 @@ next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { * Retrieve the next interface. * * Returns information in the info structure. - * Sets err to 1 if there is an error, otherwise 1. + * Sets err to 1 if there is an error, otherwise 0. */ int next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { @@ -664,8 +664,88 @@ end_iface_scan(struct iface_conf_list *ifaces) { ifaces->fp6 = NULL; #endif } -#else -/* XXX: need to define non-Solaris, non-Linux iterators */ +#else /* !HAVE_SIOCGLIFCONF, !__linux */ + +/* + * BSD support + * ----------- + * + * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs() + * function. + * + * The getifaddrs() man page describes the use. + */ + +#include + +/* + * Structure holding state about the scan. + */ +struct iface_conf_list { + struct ifaddrs *head; /* beginning of the list */ + struct ifaddrs *next; /* current position in the list */ +}; + +/* + * Structure used to return information about a specific interface. + */ +struct iface_info { + char name[IFNAMSIZ]; /* name of the interface, e.g. "bge0" */ + struct sockaddr_storage addr; /* address information */ + isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */ +}; + +/* + * Start a scan of interfaces. + * + * The iface_conf_list structure maintains state for this process. + */ +int +begin_iface_scan(struct iface_conf_list *ifaces) { + if (getifaddrs(&ifaces->head) != 0) { + log_error("Error getting interfaces; %m"); + return 0; + } + ifaces->next = ifaces->head; + return 1; +} + +/* + * Retrieve the next interface. + * + * Returns information in the info structure. + * Sets err to 1 if there is an error, otherwise 0. + */ +int +next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { + if (ifaces->next == NULL) { + *err = 0; + return 0; + } + if (strlen(ifaces->next->ifa_name) >= sizeof(info->name)) { + log_error("Interface name '%s' too long", + ifaces->next->ifa_name); + *err = 1; + return 0; + } + strcpy(info->name, ifaces->next->ifa_name); + memcpy(&info->addr, ifaces->next->ifa_addr, + ifaces->next->ifa_addr->sa_len); + info->flags = ifaces->next->ifa_flags; + ifaces->next = ifaces->next->ifa_next; + *err = 0; + return 1; +} + +/* + * End scan of interfaces. + */ +void +end_iface_scan(struct iface_conf_list *ifaces) { + freeifaddrs(ifaces->head); + ifaces->head = NULL; + ifaces->next = NULL; +} #endif /* XXX: perhaps create drealloc() rather than do it manually */ @@ -849,29 +929,6 @@ discover_interfaces(int state) { add_ipv4_addr_to_interface(tmp, &a->sin_addr); -/* - * XXX: We don't have ifreq in Solaris-land if we want IPv6. Fortunately, - * we don't actually need this for anything on Solaris. - */ -#if 0 - /* If this is the first real IP address we've - found, keep a pointer to ifreq structure in - which we found it. */ - if (!tmp -> ifp) { -#ifdef HAVE_SA_LEN - unsigned len = ((sizeof ifp -> ifr_name) + - ifp -> ifr_addr.sa_len); -#else - unsigned len = sizeof *ifp; -#endif - tif = (struct ifreq *)dmalloc (len, MDL); - if (!tif) - log_fatal ("no space for ifp."); - memcpy (tif, ifp, len); - tmp -> ifp = tif; - } -#endif /* 0 */ - /* invoke the setup hook */ addr.len = 4; memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len); @@ -898,30 +955,6 @@ discover_interfaces(int state) { add_ipv6_addr_to_interface(tmp, &a->sin6_addr); -/* - * XXX: We don't have ifreq in Solaris-land if we want IPv6. Fortunately, - * we don't actually need this for anything on Solaris. - */ -#if 0 - /* If this is the first real IP address we've - found, keep a pointer to ifreq structure in - which we found it. */ - if (!tmp -> ifp) { -#ifdef HAVE_SA_LEN - unsigned len = ((sizeof ifp -> ifr_name) + - ifp -> ifr_addr.sa_len); -#else - unsigned len = sizeof *ifp; -#endif - tif = (struct ifreq *)dmalloc (len, MDL); - if (!tif) - log_fatal ("no space for ifp."); - memcpy (tif, ifp, len); - tmp -> ifp = tif; - tmp -> primary_address = foo.sin_addr; - } -#endif /* 0 */ - /* invoke the setup hook */ addr.len = 16; memcpy(addr.iabuf, &a->sin6_addr, addr.len); @@ -937,95 +970,6 @@ discover_interfaces(int state) { end_iface_scan(&ifaces); -#if 0 -#if defined (LINUX_SLASHPROC_DISCOVERY) - /* On Linux, interfaces that don't have IP addresses don't - show up in the SIOCGIFCONF syscall. This only matters for - the DHCP client, of course - the relay agent and server - should only care about interfaces that are configured with - IP addresses anyway. - - The PROCDEV_DEVICE (/proc/net/dev) is a kernel-supplied file - that, when read, prints a human readable network status. We - extract the names of the network devices by skipping the first - two lines (which are header) and then parsing off everything - up to the colon in each subsequent line - these lines start - with the interface name, then a colon, then a bunch of - statistics. */ - - if (state == DISCOVER_UNCONFIGURED) { - FILE *proc_dev; - char buffer [256]; - int skip = 2; - - proc_dev = fopen (PROCDEV_DEVICE, "r"); - if (!proc_dev) - log_fatal ("%s: %m", PROCDEV_DEVICE); - - while (fgets (buffer, sizeof buffer, proc_dev)) { - char *name = buffer; - char *sep; - - /* Skip the first two blocks, which are header - lines. */ - if (skip) { - --skip; - continue; - } - - sep = strrchr (buffer, ':'); - if (sep) - *sep = '\0'; - while (*name == ' ') - name++; - - /* See if we've seen an interface that matches - this one. */ - for (tmp = interfaces; tmp; tmp = tmp -> next) - if (!strcmp (tmp -> name, name)) - break; - - /* If we found one, nothing more to do.. */ - if (tmp) - continue; - - strncpy (ifr.ifr_name, name, IFNAMSIZ); - - /* Skip non broadcast interfaces (plus loopback and - * point-to-point in case an OS incorrectly marks them - * as broadcast). - */ - if ((ioctl (sock, SIOCGIFFLAGS, &ifr) < 0) || - (!(ifr.ifr_flags & IFF_BROADCAST)) || - (ifr.ifr_flags & IFF_LOOPBACK ) || - (ifr.ifr_flags & IFF_POINTOPOINT)) - continue; - - /* Otherwise, allocate one. */ - tmp = (struct interface_info *)0; - status = interface_allocate (&tmp, MDL); - if (status != ISC_R_SUCCESS) - log_fatal ("Can't allocate interface %s: %s", - name, isc_result_totext (status)); - tmp -> flags = ir; - strncpy (tmp -> name, name, IFNAMSIZ); - if (interfaces) { - interface_reference (&tmp -> next, - interfaces, MDL); - interface_dereference (&interfaces, MDL); - } - interface_reference (&interfaces, tmp, MDL); - interface_dereference (&tmp, MDL); - tmp = interfaces; - - if (dhcp_interface_discovery_hook) - (*dhcp_interface_discovery_hook) (tmp); - - } - fclose (proc_dev); - } -#endif -#endif /* 0 */ /* Now cycle through all the interfaces we found, looking for hardware addresses. */ @@ -1167,8 +1111,6 @@ discover_interfaces(int state) { state == DISCOVER_REQUESTED) tmp -> flags &= ~(INTERFACE_AUTOMATIC | INTERFACE_REQUESTED); -/* XXX: no ifp in Solaris */ -/* if (!tmp -> ifp || !(tmp -> flags & INTERFACE_REQUESTED)) {*/ if (!(tmp->flags & INTERFACE_REQUESTED)) { if ((tmp -> flags & INTERFACE_REQUESTED) != ir) log_fatal ("%s: not found", tmp -> name); @@ -1202,10 +1144,6 @@ discover_interfaces(int state) { } last = tmp; -/* XXX: no ifp in Solaris */ -/* memcpy (&foo, &tmp -> ifp -> ifr_addr, - sizeof tmp -> ifp -> ifr_addr);*/ - /* We must have a subnet declaration for each interface. */ if (!tmp->shared_network && (state == DISCOVER_SERVER)) { log_error("%s", ""); diff --git a/common/lpf.c b/common/lpf.c index 255fea8f7..f9d256b34 100644 --- a/common/lpf.c +++ b/common/lpf.c @@ -28,7 +28,7 @@ #ifndef lint static char copyright[] = -"$Id: lpf.c,v 1.32 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; +"$Id: lpf.c,v 1.33 2007/05/16 22:27:34 shane Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -443,9 +443,9 @@ get_hw_addr(const char *name, struct hardware *hw) { memcpy(&hw->hbuf[1], sa->sa_data, 6); break; case ARPHRD_IEEE802: -#ifdef ARPHDR_IEEE802_TR +#ifdef ARPHRD_IEEE802_TR case ARPHRD_IEEE802_TR: -#endif /* ARPHDR_IEEE802_TR */ +#endif /* ARPHRD_IEEE802_TR */ hw->hlen = 7; hw->hbuf[0] = HTYPE_IEEE802; memcpy(&hw->hbuf[1], sa->sa_data, 6); diff --git a/common/socket.c b/common/socket.c index de322d414..f41606c48 100644 --- a/common/socket.c +++ b/common/socket.c @@ -42,12 +42,13 @@ #ifndef lint static char copyright[] = -"$Id: socket.c,v 1.61 2007/05/11 15:50:18 dhankins Exp $ " +"$Id: socket.c,v 1.62 2007/05/16 22:27:34 shane Exp $ " "Copyright (c) 2004-2006 Internet Systems Consortium.\n"; #endif /* not lint */ #include "dhcpd.h" #include +#include #ifdef USE_SOCKET_FALLBACK # if !defined (USE_SOCKET_SEND) diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 4277df95b..8fac87392 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -2046,6 +2046,13 @@ int supports_multiple_interfaces (struct interface_info *); void maybe_setup_fallback PROTO ((void)); #endif +void if_register6(struct interface_info *info, int do_multicast); +ssize_t receive_packet6(struct interface_info *interface, + unsigned char *buf, size_t len, + struct sockaddr_in6 *from, struct in6_addr *to_addr); +void if_deregister6(struct interface_info *info); + + /* bpf.c */ #if defined (USE_BPF_SEND) || defined (USE_BPF_RECEIVE) int if_register_bpf PROTO ( (struct interface_info *)); diff --git a/server/mdb6.c b/server/mdb6.c index 058122bc9..3855ba84b 100644 --- a/server/mdb6.c +++ b/server/mdb6.c @@ -17,6 +17,7 @@ /* TODO: assert() */ /* TODO: simplify functions, as pool is now in iaaddr */ +#include #include #include