]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
FreeBSD, NetBSD, OpenBSD support added in (again).
authorShane Kerr <shane@isc.org>
Wed, 16 May 2007 22:27:35 +0000 (22:27 +0000)
committerShane Kerr <shane@isc.org>
Wed, 16 May 2007 22:27:35 +0000 (22:27 +0000)
See RT ticket #16865 for more (still expect some warnings).

RELNOTES
common/bpf.c
common/discover.c
common/lpf.c
common/socket.c
includes/dhcpd.h
server/mdb6.c

index c87ad4e1aa34b614db2043cb05bdfe307207e2ed..5a4c5c180e137b139b37b8c187dfdbf0ab4bd162 100644 (file)
--- 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.
 
index aa3fd9d2b33ba82f7d186e25689427aca0273c05..e3a4e11d8d066658a1d8e5453fb4db084eb6d90a 100644 (file)
@@ -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 <ifaddrs.h>
+
 /* 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
index f2442916c52be0a0440579109143fa45630a3740..86ec835475b8567b785e06a7ac46d213fb75a5a8 100644 (file)
@@ -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 <ifaddrs.h>
+
+/* 
+ * 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", "");
index 255fea8f7b02023fe0b4151c316c048d7b5eafaa..f9d256b34d4a417d3a50ca83d0a3fc7703a66de0 100644 (file)
@@ -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);
index de322d414395d3294ae5891c5a1e36a550967401..f41606c4845b8722732389039c05c9850d1d4a31 100644 (file)
 
 #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 <sys/uio.h>
+#include <sys/uio.h>
 
 #ifdef USE_SOCKET_FALLBACK
 # if !defined (USE_SOCKET_SEND)
index 4277df95b879d3ead922afd677f2bcaaf7e89b4c..8fac87392fb0ace0a31938ee90f45fb362128cc8 100644 (file)
@@ -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 *));
index 058122bc968d9bf0507a8828d831d01718efac83..3855ba84bc627031069f56a82de2b9d4564dc0b8 100644 (file)
@@ -17,6 +17,7 @@
 /* TODO: assert() */
 /* TODO: simplify functions, as pool is now in iaaddr */
 
+#include <sys/types.h>
 #include <time.h>
 #include <netinet/in.h>