]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Mostly complete interface code. DHCPv6_socket_pre_parsing
authorShane Kerr <shane@isc.org>
Wed, 9 Aug 2006 11:26:30 +0000 (11:26 +0000)
committerShane Kerr <shane@isc.org>
Wed, 9 Aug 2006 11:26:30 +0000 (11:26 +0000)
16 files changed:
client/dhclient.c
common/conflex.c
common/discover.c
common/dlpi.c
common/inet.c
common/parse.c
common/socket.c
common/tables.c
dhcpctl/omshell.c
includes/cf/sunos5-5.h
includes/dhcpd.h
includes/dhctoken.h
relay/dhcrelay.c
server/confpars.c
server/dhcpd.c
server/mdb.c

index 53ac8317a1552ec614ebe6e65a0fa8cc85eb43dc..155270548f78092396ad8b063bbf0f65d45efaef 100644 (file)
@@ -32,7 +32,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhclient.c,v 1.142 2006/07/19 17:14:55 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhclient.c,v 1.142.16.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -79,10 +79,8 @@ static void usage PROTO ((void));
 
 void do_release(struct client_state *);
 
-int main (argc, argv, envp)
-       int argc;
-       char **argv, **envp;
-{
+int 
+main(int argc, char **argv) {
        int fd;
        int i;
        struct servent *ent;
index 7184a4aae13679f40898eb14baa91bf77223111e..405c1c59ab139ef28ca7460ce23754527d2e731f 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: conflex.c,v 1.101 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: conflex.c,v 1.101.8.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -1117,6 +1117,8 @@ static enum dhcp_token intern (atom, dfv)
                                 return SUBCLASS;
                         if (!strcasecmp(atom + 3, "net"))
                                 return SUBNET;
+                        if (!strcasecmp(atom + 3, "net6"))
+                                return SUBNET6;
                         if (!strcasecmp(atom + 3, "string"))
                                 return SUBSTRING;
                         break;
index 4d22d149ed5c598364efa3bfa7a8abeccf2643c2..e1ebf95509d9d1d6d935fca87124bfafb8f8d9d6 100644 (file)
@@ -1,6 +1,6 @@
-/* dispatch.c
+/* discover.c
 
-   Network input dispatcher... */
+   Find and identify the network interfaces. */
 
 /*
  * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: discover.c,v 1.50 2006/02/27 23:56:13 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: discover.c,v 1.50.98.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -51,7 +51,10 @@ isc_result_t (*dhcp_interface_startup_hook) (struct interface_info *);
 int (*dhcp_interface_shutdown_hook) (struct interface_info *);
 
 struct in_addr limited_broadcast;
+
+int local_family = AF_INET;
 struct in_addr local_address;
+struct in6_addr local_address6;
 
 void (*bootp_packet_handler) PROTO ((struct interface_info *,
                                     struct dhcp_packet *, unsigned,
@@ -116,94 +119,215 @@ isc_result_t interface_initialize (omapi_object_t *ipo,
        return ISC_R_SUCCESS;
 }
 
-/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
-   For each interface that's of type INET and not the loopback interface,
-   register that interface with the network I/O software, figure out what
-   subnet it's on, and add it to the list of interfaces. */
+/* XXX: needs to be autoconfiscated */
+#define HAVE_SIOCGLIFCONF
 
-void discover_interfaces (state)
-       int state;
-{
-       struct interface_info *tmp, *ip;
-       struct interface_info *last, *next;
-       char buf [2048];
-       struct ifconf ic;
-       struct ifreq ifr;
-       int i;
+/* 
+ * Solaris' extended interface is documented in the if_tcp man page.
+ */
+#ifdef HAVE_SIOCGLIFCONF
+struct iface_conf_list {
        int sock;
-       int address_count = 0;
-       struct subnet *subnet;
-       struct shared_network *share;
-       struct sockaddr_in foo;
-       int ir;
-       struct ifreq *tif;
-#ifdef ALIAS_NAMES_PERMUTED
+       int num;
+       struct lifconf conf;
+       int next;
+};
+
+struct iface_info {
+       char name[LIFNAMSIZ];
+       struct sockaddr_storage addr;
+       uint64_t flags;
+};
+
+int 
+begin_iface_scan(struct iface_conf_list *ifaces) {
+       struct lifnum lifnum;
+
+       ifaces->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       if (ifaces->sock < 0) {
+               log_error("Error creating socket to list interfaces; %m");
+               return 0;
+       }
+
+       memset(&lifnum, 0, sizeof(lifnum));
+       lifnum.lifn_family = AF_UNSPEC;
+       if (ioctl(ifaces->sock, SIOCGLIFNUM, &lifnum) < 0) {
+               log_error("Error finding total number of interfaces; %m");
+               close(ifaces->sock);
+               ifaces->sock = -1;
+               return 0;
+       }
+
+       ifaces->num = lifnum.lifn_count;
+       memset(&ifaces->conf, 0, sizeof(ifaces->conf));
+       ifaces->conf.lifc_family = AF_UNSPEC;
+       ifaces->conf.lifc_len = ifaces->num * sizeof(struct lifreq);
+       ifaces->conf.lifc_buf = dmalloc(ifaces->conf.lifc_len, MDL);
+       if (ifaces->conf.lifc_buf == NULL) {
+               log_fatal("Out of memory getting interface list.");
+       }
+
+       if (ioctl(ifaces->sock, SIOCGLIFCONF, &ifaces->conf) < 0) {
+               log_error("Error getting interfaces configuration list; %m");
+               dfree(ifaces->conf.lifc_buf, MDL);
+               close(ifaces->sock);
+               ifaces->sock = -1;
+               return 0;
+       }
+
+       ifaces->next = 0;
+
+       return 1;
+}
+
+int
+next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
+       struct lifreq *p;
+       struct lifreq tmp;
        char *s;
-#endif
-       isc_result_t status;
-       static int setup_fallback = 0;
-       int wifcount = 0;
 
-       /* Create an unbound datagram socket to do the SIOCGIFADDR ioctl on. */
-       if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
-               log_fatal ("Can't create addrlist socket");
+       do {
+               if (ifaces->next >= ifaces->num) {
+                       *err = 0;
+                       return 0;
+               }
 
-       /* Get the interface configuration information... */
+               p = ifaces->conf.lifc_req;
+               p += ifaces->next;
 
-#ifdef SIOCGIFCONF_ZERO_PROBE
-       /* linux will only tell us how long a buffer it wants if we give it
-        * a null buffer first. So, do a dry run to figure out the length.
-        * 
-        * XXX this code is duplicated from below because trying to fold
-        * the logic into the if statement and goto resulted in excesssive
-        * obfuscation. The intent is that unless you run Linux you shouldn't
-        * have to deal with this. */
+               strcpy(info->name, p->lifr_name);
+               info->addr = p->lifr_addr;
 
-       ic.ifc_len = 0;
-       ic.ifc_ifcu.ifcu_buf = (caddr_t)NULL;
-#else
-       /* otherwise, we just feed it a starting size, and it'll tell us if
-        * it needs more */
+#ifdef ALIAS_NAMED_PERMUTED
+               /* interface aliases look like "eth0:1" or "wlan1:3" */
+               s = strchr(info->name, ':');
+               if (s != NULL) {
+                       *s = '\0';
+               }
+#endif
 
-       ic.ifc_len = sizeof buf;
-       ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
+#ifdef SKIP_DUMMY_INTERFACES
+       } while (strncmp(info->name, "dummy", 5) == 0);
+#else
+       } while (0);
 #endif
+       
+       memset(&tmp, 0, sizeof(tmp));
+       strcpy(tmp.lifr_name, p->lifr_name);
+       if (ioctl(ifaces->sock, SIOCGLIFFLAGS, &tmp) < 0) {
+               log_error("Error getting interfaces flags for %s; %m", 
+                         p->lifr_name);
+               *err = 1;
+               return 0;
+       }
+       info->flags = tmp.lifr_flags;
 
-      gifconf_again:
-       i = ioctl(sock, SIOCGIFCONF, &ic);
+       ifaces->next++;
+       *err = 0;
+       return 1;
+}
 
-       if (i < 0)
-               log_fatal ("ioctl: SIOCGIFCONF: %m");
+void
+end_iface_scan(struct iface_conf_list *ifaces) {
+       dfree(ifaces->conf.lifc_buf, MDL);
+       close(ifaces->sock);
+       ifaces->sock = -1;
+}
+#else
+/* XXX: need non-Solaris versions */
+#endif 
+
+/* XXX: perhaps create drealloc() rather than do it manually */
+void
+add_ipv4_addr_to_interface(struct interface_info *iface, 
+                          const struct in_addr *addr) {
+       if (iface->addresses == NULL) {
+               iface->addresses = dmalloc(4 * sizeof(struct in_addr), MDL);
+               if (iface->addresses == NULL) {
+                       log_fatal("Out of memory saving IPv4 address "
+                                 "on interface.");
+               }
+               iface->address_count = 0;
+               iface->address_max = 4;
+       } else if (iface->address_count >= iface->address_max) {
+               struct in_addr *tmp;
+               int new_max;
+
+               new_max = iface->address_max * 2;
+               tmp = dmalloc(new_max * sizeof(struct in_addr), MDL);
+               if (tmp == NULL) {
+                       log_fatal("Out of memory saving IPv4 address "
+                                 "on interface.");
+               }
+               memcpy(tmp, 
+                      iface->addresses, 
+                      iface->address_max * sizeof(struct in_addr));
+               dfree(iface->addresses, MDL);
+               iface->addresses = tmp;
+               iface->address_max = new_max;
+       }
+       iface->addresses[iface->address_count++] = *addr;
+}
 
-#ifdef SIOCGIFCONF_ZERO_PROBE
-       /* Workaround for SIOCGIFCONF bug on some Linux versions. */
-       if (ic.ifc_ifcu.ifcu_buf == 0 && ic.ifc_len == 0) {
-               ic.ifc_len = sizeof buf;
-               ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
-               goto gifconf_again;
+/* XXX: perhaps create drealloc() rather than do it manually */
+void
+add_ipv6_addr_to_interface(struct interface_info *iface, 
+                          const struct in6_addr *addr) {
+       if (iface->v6addresses == NULL) {
+               iface->v6addresses = dmalloc(4 * sizeof(struct in6_addr), MDL);
+               if (iface->v6addresses == NULL) {
+                       log_fatal("Out of memory saving IPv6 address "
+                                 "on interface.");
+               }
+               iface->v6address_count = 0;
+               iface->v6address_max = 4;
+       } else if (iface->v6address_count >= iface->v6address_max) {
+               struct in6_addr *tmp;
+               int new_max;
+
+               new_max = iface->v6address_max * 2;
+               tmp = dmalloc(new_max * sizeof(struct in6_addr), MDL);
+               if (tmp == NULL) {
+                       log_fatal("Out of memory saving IPv6 address "
+                                 "on interface.");
+               }
+               memcpy(tmp, 
+                      iface->v6addresses, 
+                      iface->v6address_max * sizeof(struct in6_addr));
+               dfree(iface->v6addresses, MDL);
+               iface->v6addresses = tmp;
+               iface->v6address_max = new_max;
        }
-#endif
+       iface->v6addresses[iface->v6address_count++] = *addr;
+}
 
-       /* If the SIOCGIFCONF resulted in more data than would fit in
-          a buffer, allocate a bigger buffer. */
-       if ((ic.ifc_ifcu.ifcu_buf == buf 
-#ifdef SIOCGIFCONF_ZERO_PROBE
-            || ic.ifc_ifcu.ifcu_buf == 0
-#endif
-               ) && ic.ifc_len > sizeof buf) {
-               ic.ifc_ifcu.ifcu_buf = dmalloc ((size_t)ic.ifc_len, MDL);
-               if (!ic.ifc_ifcu.ifcu_buf)
-                       log_fatal ("Can't allocate SIOCGIFCONF buffer.");
-               goto gifconf_again;
-#ifdef SIOCGIFCONF_ZERO_PROBE
-       } else if (ic.ifc_ifcu.ifcu_buf == 0) {
-               ic.ifc_ifcu.ifcu_buf = (caddr_t)buf;
-               ic.ifc_len = sizeof buf;
-               goto gifconf_again;
-#endif
+/* Use the SIOCGIFCONF ioctl to get a list of all the attached interfaces.
+   For each interface that's of type INET and not the loopback interface,
+   register that interface with the network I/O software, figure out what
+   subnet it's on, and add it to the list of interfaces. */
+
+void 
+discover_interfaces(int state) {
+       struct iface_conf_list ifaces;
+       struct iface_info info;
+       int err;
+
+       struct interface_info *tmp, *ip;
+       struct interface_info *last, *next;
+
+       char abuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+
+       struct subnet *subnet;
+       int ir;
+       isc_result_t status;
+       int wifcount = 0;
+
+       static int setup_fallback = 0;
+
+       if (!begin_iface_scan(&ifaces)) {
+               log_fatal("Can't get list of interfaces.");
        }
 
-               
        /* If we already have a list of interfaces, and we're running as
           a DHCP server, the interfaces were requested. */
        if (interfaces && (state == DISCOVER_SERVER ||
@@ -216,130 +340,81 @@ void discover_interfaces (state)
                ir = INTERFACE_REQUESTED;
 
        /* Cycle through the list of interfaces looking for IP addresses. */
-       for (i = 0; i < ic.ifc_len;) {
-               struct ifreq *ifp = (struct ifreq *)((caddr_t)ic.ifc_req + i);
-#ifdef HAVE_SA_LEN
-               if (ifp -> ifr_addr.sa_len > sizeof (struct sockaddr))
-                       i += (sizeof ifp -> ifr_name) + ifp -> ifr_addr.sa_len;
-               else
-#endif
-                       i += sizeof *ifp;
-
-#ifdef ALIAS_NAMES_PERMUTED
-               if ((s = strrchr (ifp -> ifr_name, ':'))) {
-                       *s = 0;
-               }
-#endif
-
-#ifdef SKIP_DUMMY_INTERFACES
-               if (!strncmp (ifp -> ifr_name, "dummy", 5))
-                       continue;
-#endif
-
-
-               /* See if this is the sort of interface we want to
-                  deal with. */
-               strcpy (ifr.ifr_name, ifp -> ifr_name);
-               if (ioctl (sock, SIOCGIFFLAGS, &ifr) < 0)
-                       log_fatal ("Can't get interface flags for %s: %m",
-                              ifr.ifr_name);
+       while (next_iface(&info, &err, &ifaces)) {
 
                /* See if we've seen an interface that matches this one. */
-               for (tmp = interfaces; tmp; tmp = tmp -> next)
-                       if (!strcmp (tmp -> name, ifp -> ifr_name))
+               for (tmp = interfaces; tmp; tmp = tmp->next) {
+                       if (!strcmp(tmp->name, info.name))
                                break;
+               }
 
                /* Skip non broadcast interfaces (plus loopback and
                   point-to-point in case an OS incorrectly marks them
                   as broadcast). Also skip down interfaces unless we're
                   trying to get a list of configurable interfaces. */
-               if (((!(ifr.ifr_flags & IFF_BROADCAST) ||
-                     ifr.ifr_flags & IFF_LOOPBACK ||
-                     ifr.ifr_flags & IFF_POINTOPOINT) && !tmp) ||
-                   (!(ifr.ifr_flags & IFF_UP) &&
+               if (((!(info.flags & IFF_BROADCAST) ||
+                     info.flags & IFF_LOOPBACK ||
+                     info.flags & IFF_POINTOPOINT) && !tmp) ||
+                   (!(info.flags & IFF_UP) &&
                     state != DISCOVER_UNCONFIGURED))
                        continue;
                
                /* If there isn't already an interface by this name,
                   allocate one. */
                if (!tmp) {
-                       tmp = (struct interface_info *)0;
-                       status = interface_allocate (&tmp, MDL);
-                       if (status != ISC_R_SUCCESS)
-                               log_fatal ("Error allocating interface %s: %s",
-                                          ifp -> ifr_name,
-                                          isc_result_totext (status));
-                       strcpy (tmp -> name, ifp -> ifr_name);
-                       interface_snorf (tmp, ir);
-                       interface_dereference (&tmp, MDL);
+                       tmp = NULL;
+                       status = interface_allocate(&tmp, MDL);
+                       if (status != ISC_R_SUCCESS) {
+                               log_fatal("Error allocating interface %s: %s",
+                                         info.name, isc_result_totext(status));
+                       }
+                       strcpy(tmp->name, info.name);
+                       interface_snorf(tmp, ir);
+                       interface_dereference(&tmp, MDL);
                        tmp = interfaces; /* XXX */
                }
 
-               if (dhcp_interface_discovery_hook)
-                       (*dhcp_interface_discovery_hook) (tmp);
+               if (dhcp_interface_discovery_hook) {
+                       (*dhcp_interface_discovery_hook)(tmp);
+               }
 
                /* If we have the capability, extract link information
-                  and record it in a linked list. */
+                  and record it in. */
 #ifdef HAVE_AF_LINK
-               if (ifp -> ifr_addr.sa_family == AF_LINK) {
-                       struct sockaddr_dl *foo = ((struct sockaddr_dl *)
-                                                  (&ifp -> ifr_addr));
-#if defined (HAVE_SIN_LEN)
-                       tmp -> hw_address.hlen = foo -> sdl_alen;
-#else
-                       tmp -> hw_address.hlen = 6; /* XXX!!! */
-#endif
-                       tmp -> hw_address.hbuf [0] = HTYPE_ETHER; /* XXX */
-                       memcpy (&tmp -> hw_address.hbuf [1],
-                               LLADDR (foo), tmp -> hw_address.hlen);
-                       tmp -> hw_address.hlen++;       /* for type. */
+               if (info.addr.ss_family == AF_LINK) {
+                       struct sockaddr_dl *d = (struct sockaddr_dl*)&info.addr;
+                       tmp->hw_address.hlen = d->sdl_alen;
+                       tmp->hw_address.hbuf[0] = HTYPE_ETHER; /* XXX */
+                       memcpy(&tmp->hw_address.hbuf[1], 
+                              LLADDR(d),
+                              tmp->hw_address.hlen);
+                       tmp->hw_address.hlen++; /* for type. */
                } else
 #endif /* AF_LINK */
 
-               if (ifp -> ifr_addr.sa_family == AF_INET) {
+               if ((info.addr.ss_family == AF_INET) && 
+                   (local_family == AF_INET)) {
+                       struct sockaddr_in *a = (struct sockaddr_in*)&info.addr;
                        struct iaddr addr;
 
-                       /* Get a pointer to the address... */
-                       memcpy (&foo, &ifp -> ifr_addr,
-                               sizeof ifp -> ifr_addr);
-
                        /* We don't want the loopback interface. */
-                       if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK) &&
-                           ((tmp -> flags & INTERFACE_AUTOMATIC) &&
+                       if (a->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
+                           ((tmp->flags & INTERFACE_AUTOMATIC) &&
                             state == DISCOVER_SERVER))
                                continue;
 
                        /* If the only address we have is 0.0.0.0, we
                           shouldn't consider the interface configured. */
-                       if (foo.sin_addr.s_addr != htonl(INADDR_ANY))
+                       if (a->sin_addr.s_addr != htonl(INADDR_ANY))
                                tmp->configured = 1;
 
-                       if (!tmp -> addresses) {
-                               tmp -> addresses =
-                                       dmalloc (10 * sizeof (struct in_addr),
-                                                MDL);
-                               if (!tmp -> addresses)
-                                       log_fatal ("no memory for ifaddrlist");
-                               tmp -> address_count = 0;
-                               tmp -> address_max = 10;
-                       } else if (tmp -> address_count >= tmp -> address_max) {
-                               struct in_addr *ta;
-                               int newmax = tmp -> address_max * 2;
-                               ta = dmalloc (newmax *
-                                             sizeof (struct in_addr), MDL);
-                               if (!ta)
-                                       log_fatal ("no memory for new "
-                                                  "ifaddrlist");
-                               memcpy (ta, tmp -> addresses,
-                                       tmp -> address_max *
-                                       sizeof (struct in_addr));
-                               dfree (tmp -> addresses, MDL);
-                               tmp -> addresses = ta;
-                               tmp -> address_max = newmax;
-                       }
-                       tmp -> addresses [tmp -> address_count++] =
-                               foo.sin_addr;
+                       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. */
@@ -356,19 +431,71 @@ void discover_interfaces (state)
                                memcpy (tif, ifp, len);
                                tmp -> ifp = tif;
                        }
+#endif /* 0 */
 
-                       /* Grab the address... */
+                       /* invoke the setup hook */
                        addr.len = 4;
-                       memcpy (addr.iabuf, &foo.sin_addr.s_addr,
-                               addr.len);
-                       if (dhcp_interface_setup_hook)
-                               (*dhcp_interface_setup_hook) (tmp, &addr);
+                       memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len);
+                       if (dhcp_interface_setup_hook) {
+                               (*dhcp_interface_setup_hook)(tmp, &addr);
+                       }
                }
+               else if ((info.addr.ss_family == AF_INET6) && 
+                        (local_family == AF_INET6)) {
+                       struct sockaddr_in6 *a = 
+                                       (struct sockaddr_in6*)&info.addr;
+                       struct iaddr addr;
+
+                       /* We don't want the loopback interface. */
+                       if (IN6_IS_ADDR_LOOPBACK(&a->sin6_addr) && 
+                           ((tmp->flags & INTERFACE_AUTOMATIC) &&
+                            state == DISCOVER_SERVER))
+                               continue;
+
+                       /* If the only address we have is 0.0.0.0, we
+                          shouldn't consider the interface configured. */
+                       if (IN6_IS_ADDR_UNSPECIFIED(&a->sin6_addr))
+                               tmp->configured = 1;
+
+                       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;
+                       }
+#endif /* 0 */
+
+                       /* invoke the setup hook */
+                       addr.len = 16;
+                       memcpy(addr.iabuf, &a->sin6_addr, addr.len);
+                       if (dhcp_interface_setup_hook) {
+                               (*dhcp_interface_setup_hook)(tmp, &addr);
+                       }
+               }
+       }
+
+       if (err) {
+               log_fatal("Error getting interface information.");
        }
 
-       /* If we allocated a buffer, free it. */
-       if (ic.ifc_ifcu.ifcu_buf != buf)
-               dfree (ic.ifc_ifcu.ifcu_buf, MDL);
+       end_iface_scan(&ifaces);
 
 #if defined (LINUX_SLASHPROC_DISCOVERY)
        /* On Linux, interfaces that don't have IP addresses don't
@@ -460,8 +587,10 @@ void discover_interfaces (state)
 
        /* Now cycle through all the interfaces we found, looking for
           hardware addresses. */
+       /* XXX: The dlpi interface code will get this information in Solaris */
+#if 0
 #if defined (HAVE_SIOCGIFHWADDR) && !defined (HAVE_AF_LINK)
-       for (tmp = interfaces; tmp; tmp = tmp -> next) {
+       for (tmp = interfaces; tmp != NULL; tmp = tmp->next) {
                struct ifreq ifr;
                struct sockaddr sa;
                int b, sk;
@@ -568,16 +697,16 @@ void discover_interfaces (state)
                }
        }
 #endif /* defined (HAVE_SIOCGIFHWADDR) && !defined (HAVE_AF_LINK) */
+#endif /* 0 */
 
        /* If we're just trying to get a list of interfaces that we might
           be able to configure, we can quit now. */
        if (state == DISCOVER_UNCONFIGURED) {
-               close (sock);
                return;
        }
 
        /* Weed out the interfaces that did not have IP addresses. */
-       tmp = last = next = (struct interface_info *)0;
+       tmp = last = next = NULL;
        if (interfaces)
                interface_reference (&tmp, interfaces, MDL);
        while (tmp) {
@@ -596,7 +725,9 @@ void discover_interfaces (state)
                    state == DISCOVER_REQUESTED)
                        tmp -> flags &= ~(INTERFACE_AUTOMATIC |
                                          INTERFACE_REQUESTED);
-               if (!tmp -> ifp || !(tmp -> flags & 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);
                        if (!last) {
@@ -629,15 +760,31 @@ void discover_interfaces (state)
                }
                last = tmp;
 
-               memcpy (&foo, &tmp -> ifp -> ifr_addr,
-                       sizeof tmp -> ifp -> ifr_addr);
+/* 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", "");
-                       log_error ("No subnet declaration for %s (%s).",
-                                  tmp -> name, inet_ntoa (foo.sin_addr));
-                       if (supports_multiple_interfaces (tmp)) {
+               if (!tmp->shared_network && (state == DISCOVER_SERVER)) {
+                       log_error("%s", "");
+                       if (local_family == AF_INET) {
+                               log_error("No subnet declaration for %s (%s).",
+                                         tmp->name, 
+                                         inet_ntoa(tmp->addresses[0]));
+                       } else {
+                               if (tmp->v6addresses != NULL) {
+                                       inet_ntop(AF_INET6, 
+                                                 &tmp->v6addresses[0],
+                                                 abuf,
+                                                 sizeof(abuf));
+                               } else {
+                                       strcpy(abuf, "no addresses");
+                               }
+                               log_error("No subnet declaration for %s (%s).",
+                                         tmp->name,
+                                         abuf);
+                       }
+                       if (supports_multiple_interfaces(tmp)) {
                                log_error ("** Ignoring requests on %s.  %s",
                                           tmp -> name, "If this is not what");
                                log_error ("   you want, please write %s",
@@ -672,7 +819,7 @@ void discover_interfaces (state)
                                   to the first address we found. */
                                subnet -> interface_address.len = 4;
                                memcpy (subnet -> interface_address.iabuf,
-                                       &foo.sin_addr.s_addr, 4);
+                                       &tmp->addresses[0].s_addr, 4);
                        }
                }
 
@@ -717,8 +864,6 @@ void discover_interfaces (state)
                                   tmp -> name, isc_result_totext (status));
        }
 
-       close (sock);
-
        if (state == DISCOVER_SERVER && wifcount == 0) {
                log_info ("%s", "");
                log_fatal ("Not configured to listen on any interfaces!");
index e43240c11ba00f18666480fe497fd08358349c1f..bfcb31506049c897659775c09034b65a89d09ddb 100644 (file)
  * to sleep.
  */
 
+/*
+ * The Open Group Technical Standard can be found here:
+ * http://www.opengroup.org/onlinepubs/009618899/index.htm
+ *
+ * The HP DLPI Programmer's Guide can be found here:
+ * http://docs.hp.com/en/B2355-90139/index.html
+ */
+
 #ifndef lint
 static char copyright[] =
-"$Id: dlpi.c,v 1.29 2005/03/17 20:14:57 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dlpi.c,v 1.29.124.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
index 934eba19832a67422607368452af7609e4a7fb56..7a022e1da4794ea0c1886c85ff6841c08263f846 100644 (file)
@@ -35,7 +35,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: inet.c,v 1.11 2006/05/15 15:07:49 dhankins Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: inet.c,v 1.11.68.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2005 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -210,29 +210,32 @@ addr_match(addr, match)
        return 1;
 }
 
-char *piaddr (addr)
-       struct iaddr addr;
-{
-       static char pbuf [4 * 16];
-       char *s = pbuf;
-       int i;
+/* XXX: should use a const pointer rather than passing the structure */
+const char *
+piaddr(struct iaddr addr) {
+       static char 
+               pbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
 
-       if (addr.len > sizeof(addr.iabuf))
-               log_fatal("piaddr():%s:%d: Address length too long.", MDL);
+       /* INSIST((addr.len == 0) || (addr.len == 4) || (addr.len == 16)); */
 
        if (addr.len == 0) {
-               strcpy (s, "<null address>");
+               return "<null address>";
        }
-       for (i = 0; i < addr.len; i++) {
-               sprintf (s, "%s%d", i ? "." : "", addr.iabuf [i]);
-               s += strlen (s);
+       if (addr.len == 4) {
+               return inet_ntop(AF_INET, addr.iabuf, pbuf, sizeof(pbuf));
+       } 
+       if (addr.len == 16) {
+               return inet_ntop(AF_INET6, addr.iabuf, pbuf, sizeof(pbuf));
        }
-       return pbuf;
+
+       log_fatal("piaddr():%s:%d: Invalid address length %d.", MDL, addr.len);
+       /* quell compiler warnings */
+       return NULL;
 }
 
-char *piaddrmask (struct iaddr addr, struct iaddr mask,
-                 const char *file, int line)
-{
+/* XXX: should use a const pointer rather than passing the structure */
+char *
+piaddrmask(struct iaddr addr, struct iaddr mask, const char *file, int line) {
        char *s, tbuf[sizeof("255.255.255.255/32")];
        int mw;
        unsigned i, oct, bit;
@@ -270,3 +273,35 @@ char *piaddrmask (struct iaddr addr, struct iaddr mask,
        return s;
 }
 
+char *
+piaddrcidr(const struct iaddr *addr, unsigned int bits, 
+          const char *file, int line) {
+       const char *tmp;
+       int tmp_len;
+       char *ret;
+
+       /* INSIST(addr != NULL); */
+       /* INSIST((addr->len == 4) || (addr->len == 16)); */
+       /* INSIST(bits <= (addr->len * 8)); */
+
+       tmp = piaddr(*addr);
+
+       /*
+        * Figure out how much space we need for the address plus
+        * the bit count, and the trailing NUL character. 
+        * "2001::/96", for instance.
+        */
+       tmp_len = strlen(tmp) + 3;
+       if (bits >= 100) {
+               tmp_len += 2;
+       } else if (bits >= 10) {
+               tmp_len += 1;
+       }
+
+       ret = dmalloc(tmp_len, file, line);
+       if (ret != NULL) {
+               sprintf(ret, "%s/%d", tmp, bits);
+       }
+       return ret;
+}
+
index b1c059e6e30a0d86b27a1cead7e07ca5c478ef6b..a8626cbdecf0eb05b3950dcd5785208d1910ebe7 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.113.2.1 2006/07/25 10:01:33 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.113.2.1.2.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -321,6 +321,88 @@ int parse_ip_addr (cfile, addr)
        return 0;
 }      
 
+/*
+ * Return true if every character in the string is hexidecimal.
+ */
+static int
+is_hex_string(const char *s) {
+       while (*s != '\0') {
+               if (!isxdigit(*s)) {
+                       return 0;
+               }
+               s++;
+       }
+       return 1;
+}
+
+/*
+ * ip-address6 :== (complicated set of rules)
+ *
+ * See section 2.2 of RFC 1884 for details.
+ *
+ * We are lazy for this. We pull numbers, names, colons, and dots 
+ * together and then throw the resulting string at the inet_pton()
+ * function.
+ */
+
+int
+parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
+       enum dhcp_token token;
+       const char *val;
+       int val_len;
+
+       char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+       int v6_len;
+
+       v6_len = 0;
+       for (;;) {
+               token = peek_token(&val, NULL, cfile);
+               if ((((token == NAME) || (token == NUMBER_OR_NAME)) && 
+                    is_hex_string(val)) ||
+                   (token == NUMBER) || 
+                   (token == DOT) || 
+                   (token == COLON)) {
+
+                       next_token(&val, NULL, cfile);
+                       val_len = strlen(val);
+                       if ((v6_len + val_len) >= sizeof(v6)) {
+                               parse_warn(cfile, "Invalid IPv6 address.");
+                               skip_to_semi(cfile);
+                               return 0;
+                       }
+                       memcpy(v6+v6_len, val, val_len);
+                       v6_len += val_len;
+
+               } else {
+                       break;
+               }
+       }
+       v6[v6_len] = '\0';
+
+       if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
+               parse_warn(cfile, "Invalid IPv6 address.");
+               skip_to_semi(cfile);
+               return 0;
+       }
+       addr->len = 16;
+       return 1;
+}
+
+/*
+ * Same as parse_ip6_addr() above, but returns the value in the 
+ * expression rather than in an address structure.
+ */
+int
+parse_ip6_addr_expr(struct expression **expr, 
+                   struct parse *cfile) {
+       struct iaddr addr;
+
+       if (!parse_ip6_addr(cfile, &addr)) {
+               return 0;
+       }
+       return make_const_data(expr, addr.iabuf, addr.len, 0, 1, MDL);
+}
+
 /*
  * ip-address-with-subnet :== ip-address |
  *                          ip-address "/" NUMBER
@@ -1387,6 +1469,9 @@ int parse_option_code_definition (cfile, option)
              case IP_ADDRESS:
                type = 'I';
                break;
+             case IP6_ADDRESS:
+               type = '6';
+               break;
              case DOMAIN_NAME:
                type = 'd';
                goto no_arrays;
@@ -4782,6 +4867,15 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
                                return 0;
                }
                break;
+
+             case '6': /* IPv6 address. */
+               if (!parse_ip6_addr(cfile, &addr)) {
+                       return 0;
+               }
+               if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) {
+                       return 0;
+               }
+               break;
                
              case 'T': /* Lease interval. */
                token = next_token (&val, (unsigned *)0, cfile);
index 714321a575ad20e68f362c3934984e561c7f6149..a8d6cc2c3df7b3b2768edf9a594bd49683442a16 100644 (file)
@@ -3,7 +3,7 @@
    BSD socket interface code... */
 
 /*
- * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -42,7 +42,8 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: socket.c,v 1.58 2005/03/17 20:15:00 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: socket.c,v 1.58.122.1 2006/08/09 11:26:29 shane Exp $ "
+"Copyright (c) 2004-2006 Internet Systems Consortium.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -51,6 +52,7 @@ static char copyright[] =
 # if !defined (USE_SOCKET_SEND)
 #  define if_register_send if_register_fallback
 #  define send_packet send_fallback
+#  define send_packet6 send_fallback6
 #  define if_reinitialize_send if_reinitialize_fallback
 # endif
 #endif
@@ -90,62 +92,89 @@ void if_reinitialize_receive (info)
        defined (USE_SOCKET_RECEIVE) || \
                defined (USE_SOCKET_FALLBACK)
 /* Generic interface registration routine... */
-int if_register_socket (info)
-       struct interface_info *info;
-{
-       struct sockaddr_in name;
+int
+if_register_socket(struct interface_info *info) {
+       struct sockaddr_storage name;
+       int name_len;
        int sock;
        int flag;
+       int domain;
+
+       /* INSIST((local_family == AF_INET) || (local_family == AF_INET6)); */
 
 #if !defined (HAVE_SO_BINDTODEVICE) && !defined (USE_FALLBACK)
        /* Make sure only one interface is registered. */
-       if (once)
+       if (once) {
                log_fatal ("The standard socket API can only support %s",
                       "hosts with a single network interface.");
+       }
        once = 1;
 #endif
 
-       memset (&name, 0, sizeof (name));
-       /* Set up the address we're going to bind to. */
-       name.sin_family = AF_INET;
-       name.sin_port = local_port;
-       name.sin_addr = local_address;
+       /* 
+        * Set up the address we're going to bind to, depending on the
+        * address family. 
+        */ 
+       memset(&name, 0, sizeof(name));
+       if (local_family == AF_INET) {
+               struct sockaddr_in *addr = (struct sockaddr_in *)&name; 
+               addr->sin_family = AF_INET;
+               addr->sin_port = local_port;
+               memcpy(&addr->sin_addr,
+                      &local_address,
+                      sizeof(addr->sin_addr));
+               name_len = sizeof(*addr);
+               domain = PF_INET;
+       } else { 
+               struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&name; 
+               addr->sin6_family = AF_INET6;
+               addr->sin6_port = local_port;
+               memcpy(&addr->sin6_addr,
+                      &local_address6, 
+                      sizeof(addr->sin6_addr));
+               name_len = sizeof(*addr);
+               domain = PF_INET6;
+       }
 
        /* Make a socket... */
-       if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
-               log_fatal ("Can't create dhcp socket: %m");
+       sock = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
+       if (sock < 0) {
+               log_fatal("Can't create dhcp socket: %m");
+       }
 
        /* Set the REUSEADDR option so that we don't fail to start if
           we're being restarted. */
        flag = 1;
-       if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
-                       (char *)&flag, sizeof flag) < 0)
-               log_fatal ("Can't set SO_REUSEADDR option on dhcp socket: %m");
+       if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+                       (char *)&flag, sizeof(flag)) < 0) {
+               log_fatal("Can't set SO_REUSEADDR option on dhcp socket: %m");
+       }
 
        /* Set the BROADCAST option so that we can broadcast DHCP responses.
           We shouldn't do this for fallback devices, and we can detect that
           a device is a fallback because it has no ifp structure. */
-       if (info -> ifp &&
-           (setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
-                        (char *)&flag, sizeof flag) < 0))
-               log_fatal ("Can't set SO_BROADCAST option on dhcp socket: %m");
+       if (info->ifp &&
+           (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
+                        (char *)&flag, sizeof(flag)) < 0)) {
+               log_fatal("Can't set SO_BROADCAST option on dhcp socket: %m");
+       }
 
        /* Bind the socket to this interface's IP address. */
-       if (bind (sock, (struct sockaddr *)&name, sizeof name) < 0) {
-               log_error ("Can't bind to dhcp address: %m");
-               log_error ("Please make sure there is no other dhcp server");
-               log_error ("running and that there's no entry for dhcp or");
-               log_error ("bootp in /etc/inetd.conf.   Also make sure you");
-               log_error ("are not running HP JetAdmin software, which");
-               log_fatal ("includes a bootp server.");
+       if (bind(sock, (struct sockaddr *)&name, name_len) < 0) {
+               log_error("Can't bind to dhcp address: %m");
+               log_error("Please make sure there is no other dhcp server");
+               log_error("running and that there's no entry for dhcp or");
+               log_error("bootp in /etc/inetd.conf.   Also make sure you");
+               log_error("are not running HP JetAdmin software, which");
+               log_fatal("includes a bootp server.");
        }
 
 #if defined (HAVE_SO_BINDTODEVICE)
        /* Bind this socket to this interface. */
-       if (info -> ifp &&
-           setsockopt (sock, SOL_SOCKET, SO_BINDTODEVICE,
-                       (char *)(info -> ifp), sizeof *(info -> ifp)) < 0) {
-               log_fatal ("setsockopt: SO_BINDTODEVICE: %m");
+       if (info->ifp &&
+           setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+                       (char *)(info -> ifp), sizeof(*(info -> ifp))) < 0) {
+               log_fatal("setsockopt: SO_BINDTODEVICE: %m");
        }
 #endif
 
@@ -256,6 +285,23 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto)
        }
        return result;
 }
+
+ssize_t send_packet6(struct interface_info *interface,
+                    struct packet *packet,
+                    struct dhcp_packet *raw, 
+                    size_t len, 
+                    struct in6_addr from, 
+                    struct sockaddr_in6 *to, 
+                    struct hardware *hto) {
+       int result;
+
+       result = sendto(interface->wfdesc, (char *)raw, len, 0,
+                       (struct sockaddr *)to, sizeof(*to));
+       if (result < 0) {
+               log_error("send_packet6: %m");
+       }
+       return result;
+}
 #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */
 
 #ifdef USE_SOCKET_RECEIVE
@@ -283,6 +329,17 @@ ssize_t receive_packet (interface, buf, len, from, hfrom)
 #endif
        return result;
 }
+
+ssize_t receive_packet6(struct interface_info *interface, unsigned char *buf,
+                       size_t len, struct sockaddr_in6 *from,
+                       struct hardware *hfrom) {
+       SOCKLEN_T flen = sizeof(*from);
+       int result;
+
+       result = recvfrom(interface->rfdesc, (char *)buf, len, 0,
+                         (struct sockaddr *)from, &flen);
+       return result;
+}
 #endif /* USE_SOCKET_RECEIVE */
 
 #if defined (USE_SOCKET_FALLBACK)
index eefad58f357aa82eef619e4b28fcefb11e230b06..e5b4af5dbf6b79e05cc584f74eb65343e9f36604 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: tables.c,v 1.56 2006/07/22 02:24:16 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: tables.c,v 1.56.8.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -55,7 +55,8 @@ HASH_FUNCTIONS (option_code, const unsigned *, struct option,
 
    Format codes:
 
-   I - IP address
+   I - IPv4 address
+   6 - IPv6 address
    l - 32-bit signed integer
    L - 32-bit unsigned integer
    s - 16-bit signed integer
index afac88ac705877b5b04eb7b6174b1d25b1ce088a..ddcb3f5a86a22c675017e8c72a41fec28786b1c1 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: omshell.c,v 1.11 2006/02/24 23:16:29 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: omshell.c,v 1.11.100.1 2006/08/09 11:26:29 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include <time.h>
@@ -76,8 +76,8 @@ static void check (isc_result_t status, const char *func) {
        }
 }
 
-int main (int argc, char **argv, char **envp)
-{
+int 
+main(int argc, char **argv) {
        isc_result_t status, waitstatus;
        dhcpctl_handle connection;
        dhcpctl_handle authenticator;
index e9789d60a686c162db4f82e46fe008539b5dd11e..198f3c22b213ddf6aa3c897c377fce6ea36cb7bb 100644 (file)
@@ -38,6 +38,7 @@
 typedef uint8_t                u_int8_t;
 typedef uint16_t       u_int16_t;
 typedef uint32_t       u_int32_t;
+typedef uint64_t       u_int64_t;
 #else /* Older SunOS has no idea what these things mean. */
 typedef int8_t char
 typedef int16_t short
index 2f66d1c121134ebe0b33d26ebc80bd193e53a068..3a9eda9a03dc2c80bd3b5557fd14866bef0f97eb 100644 (file)
@@ -688,6 +688,7 @@ struct subnet {
        struct iaddr interface_address;
        struct iaddr net;
        struct iaddr netmask;
+       int prefix_len;                 /* XXX: currently for IPv6 only */
 
        struct group *group;
 };
@@ -889,6 +890,13 @@ struct interface_info {
        int address_max;                /* Max number of addresses we can
                                           store in current buffer. */
 
+       struct in6_addr *v6addresses;   /* IPv6 addresses associated with 
+                                          this interface. */
+       int v6address_count;            /* Number of IPv6 addresses associated
+                                          with this interface. */
+       int v6address_max;              /* Maximum number of IPv6 addresses
+                                          we can store in current buffer. */
+
        u_int8_t *circuit_id;           /* Circuit ID associated with this
                                           interface. */
        unsigned circuit_id_len;        /* Length of Circuit ID, if there
@@ -1260,9 +1268,9 @@ extern const char *path_dhcpd_pid;
 
 extern int dhcp_max_agent_option_packet_length;
 
-int main PROTO ((int, char **, char **));
-void postconf_initialization (int);
-void postdb_startup (void);
+int main(int, char **);
+void postconf_initialization(int);
+void postdb_startup(void);
 void cleanup PROTO ((void));
 void lease_pinged PROTO ((struct iaddr, u_int8_t *, int));
 void lease_ping_timeout PROTO ((void *));
@@ -1308,8 +1316,11 @@ int parse_class_declaration PROTO ((struct class **, struct parse *,
 void parse_shared_net_declaration PROTO ((struct parse *, struct group *));
 void parse_subnet_declaration PROTO ((struct parse *,
                                      struct shared_network *));
+void parse_subnet6_declaration PROTO ((struct parse *,
+                                      struct shared_network *));
 void parse_group_declaration PROTO ((struct parse *, struct group *));
-int parse_fixed_addr_param PROTO ((struct option_cache **, struct parse *));
+int parse_fixed_addr_param PROTO ((struct option_cache **, 
+                                  struct parse *, enum dhcp_token));
 TIME parse_timestamp PROTO ((struct parse *));
 int parse_lease_declaration PROTO ((struct lease **, struct parse *));
 void parse_address_range PROTO ((struct parse *, struct group *, int,
@@ -1704,6 +1715,9 @@ ssize_t send_fallback PROTO ((struct interface_info *,
                              struct packet *, struct dhcp_packet *, size_t, 
                              struct in_addr,
                              struct sockaddr_in *, struct hardware *));
+ssize_t send_fallback6(struct interface_info *, struct packet *, 
+                      struct dhcp_packet *, size_t, struct in6_addr,
+                      struct sockaddr_in6 *, struct hardware *);
 #endif
 
 #ifdef USE_SOCKET_SEND
@@ -1714,6 +1728,9 @@ ssize_t send_packet PROTO ((struct interface_info *,
                            struct packet *, struct dhcp_packet *, size_t, 
                            struct in_addr,
                            struct sockaddr_in *, struct hardware *));
+ssize_t send_packet6(struct interface_info *, struct packet *, 
+                    struct dhcp_packet *, size_t, struct in6_addr,
+                    struct sockaddr_in6 *, struct hardware *);
 #endif
 #ifdef USE_SOCKET_RECEIVE
 void if_reinitialize_receive PROTO ((struct interface_info *));
@@ -1722,6 +1739,8 @@ void if_deregister_receive PROTO ((struct interface_info *));
 ssize_t receive_packet PROTO ((struct interface_info *,
                               unsigned char *, size_t,
                               struct sockaddr_in *, struct hardware *));
+ssize_t receive_packet6(struct interface_info *, unsigned char *, size_t,
+                       struct sockaddr_in *, struct hardware *);
 #endif
 
 #if defined (USE_SOCKET_FALLBACK)
@@ -1868,7 +1887,9 @@ isc_result_t interface_setup (void);
 void interface_trace_setup (void);
 
 extern struct in_addr limited_broadcast;
+extern int local_family;
 extern struct in_addr local_address;
+extern struct in6_addr local_address6;
 
 extern u_int16_t local_port;
 extern u_int16_t remote_port;
@@ -1967,8 +1988,9 @@ struct iaddr broadcast_addr PROTO ((struct iaddr, struct iaddr));
 u_int32_t host_addr PROTO ((struct iaddr, struct iaddr));
 int addr_eq PROTO ((struct iaddr, struct iaddr));
 int addr_match(struct iaddr *, struct iaddrmatch *);
-char *piaddr PROTO ((struct iaddr));
-char *piaddrmask (struct iaddr, struct iaddr, const char *, int);
+const char *piaddr PROTO ((struct iaddr));
+char *piaddrmask(struct iaddr, struct iaddr, const char *, int);
+char *piaddrcidr(const struct iaddr *, unsigned int, const char *, int);
 
 /* dhclient.c */
 extern const char *path_dhclient_conf;
@@ -2568,12 +2590,12 @@ isc_result_t dhcp_lease_free (omapi_object_t *, const char *, int);
 isc_result_t dhcp_lease_get (omapi_object_t **, const char *, int);
 int find_grouped_subnet PROTO ((struct subnet **, struct shared_network *,
                                struct iaddr, const char *, int));
-int find_subnet (struct subnet **, struct iaddr, const char *, int);
+int find_subnet(struct subnet **, struct iaddr, const char *, int);
 void enter_shared_network PROTO ((struct shared_network *));
 void new_shared_network_interface PROTO ((struct parse *,
                                          struct shared_network *,
                                          const char *));
-int subnet_inner_than PROTO ((struct subnet *, struct subnet *, int));
+int subnet_inner_than(const struct subnet *, const struct subnet *, int);
 void enter_subnet PROTO ((struct subnet *));
 void enter_lease PROTO ((struct lease *));
 int supersede_lease PROTO ((struct lease *, struct lease *, int, int, int));
index 0315c7c9fecbe79ffd1b04f61eec45ec3503f75f..14f2c2fe37975e33e166986edb9a1b08d0cff65b 100644 (file)
@@ -323,7 +323,10 @@ enum dhcp_token {
        MAX_LEASE_OWNERSHIP = 627,
        MAX_BALANCE = 628,
        MIN_BALANCE = 629,
-       DOMAIN_LIST = 630
+       DOMAIN_LIST = 630,
+       IP6_ADDRESS = 631,
+       FIXED_ADDR6 = 632,
+       SUBNET6 = 633
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index 859fcf0f6c7ee5e70a9e5b20b21f640229893b92..a6921343cde188fe47f3560b88aca7530d837645 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhcrelay.c,v 1.58 2006/05/11 14:48:59 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: dhcrelay.c,v 1.58.72.1 2006/08/09 11:26:30 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -97,10 +97,8 @@ static char arr [] = "All rights reserved.";
 static char message [] = "Internet Systems Consortium DHCP Relay Agent";
 static char url [] = "For info, please visit http://www.isc.org/sw/dhcp/";
 
-int main (argc, argv, envp)
-       int argc;
-       char **argv, **envp;
-{
+int 
+main(int argc, char **argv) {
        int fd;
        int i;
        struct servent *ent;
index a8907e70857e71f9c49cc9ed16cf043d06ec7593..d2a830dad39aa370ef3a84b191b02ef33cd13381 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: confpars.c,v 1.158 2006/07/20 16:04:03 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: confpars.c,v 1.158.12.1 2006/08/09 11:26:30 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -416,6 +416,7 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                return 1;
 
              case SUBNET:
+             case SUBNET6:
                next_token (&val, (unsigned *)0, cfile);
                if (type == HOST_DECL || type == SUBNET_DECL ||
                    type == CLASS_DECL) {
@@ -426,9 +427,14 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                }
 
                /* If we're in a subnet declaration, just do the parse. */
-               if (group -> shared_network) {
-                       parse_subnet_declaration (cfile,
-                                                 group -> shared_network);
+               if (group->shared_network) {
+                       if (token == SUBNET) {
+                               parse_subnet_declaration(cfile,
+                                                        group->shared_network);
+                       } else {
+                               parse_subnet6_declaration(cfile,
+                                                        group->shared_network);
+                       }
                        break;
                }
 
@@ -445,26 +451,37 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                shared_network_reference (&share -> group -> shared_network,
                                          share, MDL);
 
-               parse_subnet_declaration (cfile, share);
+               if (token == SUBNET) {
+                       parse_subnet_declaration(cfile, share);
+               } else {
+                       parse_subnet6_declaration(cfile, share);
+               }
 
                /* share -> subnets is the subnet we just parsed. */
-               if (share -> subnets) {
-                       interface_reference (&share -> interface,
-                                            share -> subnets -> interface,
-                                            MDL);
+               if (share->subnets) {
+                       interface_reference(&share->interface,
+                                           share->subnets->interface,
+                                           MDL);
 
                        /* Make the shared network name from network number. */
-                       n = piaddrmask (share -> subnets -> net,
-                                       share -> subnets -> netmask, MDL);
-                       share -> name = n;
+                       if (token == SUBNET) {
+                               n = piaddrmask(share->subnets->net,
+                                              share->subnets->netmask, MDL);
+                       } else {
+                               n = piaddrcidr(&share->subnets->net,
+                                              share->subnets->prefix_len, MDL);
+                       }
+
+                       /* XXX: do something if n is NULL */
+                       share->name = n;
 
                        /* Copy the authoritative parameter from the subnet,
                           since there is no opportunity to declare it here. */
-                       share -> group -> authoritative =
-                               share -> subnets -> group -> authoritative;
-                       enter_shared_network (share);
+                       share->group->authoritative =
+                               share->subnets->group->authoritative;
+                       enter_shared_network(share);
                }
-               shared_network_dereference (&share, MDL);
+               shared_network_dereference(&share, MDL);
                return 1;
 
              case VENDOR_CLASS:
@@ -531,23 +548,24 @@ int parse_statement (cfile, group, type, host_decl, declaration)
                break;
 
              case FIXED_ADDR:
-               next_token (&val, (unsigned *)0, cfile);
-               cache = (struct option_cache *)0;
-               if (parse_fixed_addr_param (&cache, cfile)) {
+             case FIXED_ADDR6:
+               next_token(&val, NULL, cfile);
+               cache = NULL;
+               if (parse_fixed_addr_param(&cache, cfile, token)) {
                        if (host_decl) {
-                               if (host_decl -> fixed_addr) {
-                                       option_cache_dereference (&cache, MDL);
-                                       parse_warn (cfile,
-                                                   "Only one fixed address%s",
-                                                   " declaration per host.");
+                               if (host_decl->fixed_addr) {
+                                       option_cache_dereference(&cache, MDL);
+                                       parse_warn(cfile,
+                                                  "Only one fixed address "
+                                                  "declaration per host.");
                                } else {
-                                       host_decl -> fixed_addr = cache;
+                                       host_decl->fixed_addr = cache;
                                }
                        } else {
-                               parse_warn (cfile,
-                                           "fixed-address parameter not %s",
-                                           "allowed here.");
-                               option_cache_dereference (&cache, MDL);
+                               parse_warn(cfile,
+                                          "fixed-address parameter not "
+                                          "allowed here.");
+                               option_cache_dereference(&cache, MDL);
                        }
                }
                break;
@@ -2318,6 +2336,75 @@ void parse_shared_net_declaration (cfile, group)
        shared_network_dereference (&share, MDL);
 }
 
+
+static void
+common_subnet_parsing(struct parse *cfile, 
+                     struct shared_network *share,
+                     struct subnet *subnet) {
+       enum dhcp_token token;
+       struct subnet *t, *u;
+       const char *val;
+       int declaration = 0;
+
+       enter_subnet(subnet);
+
+       if (!parse_lbrace(cfile)) {
+               subnet_dereference(&subnet, MDL);
+               return;
+       }
+
+       do {
+               token = peek_token(&val, NULL, cfile);
+               if (token == RBRACE) {
+                       token = next_token(&val, NULL, cfile);
+                       break;
+               } else if (token == END_OF_FILE) {
+                       token = next_token(&val, NULL, cfile);
+                       parse_warn (cfile, "unexpected end of file");
+                       break;
+               } else if (token == INTERFACE) {
+                       token = next_token(&val, NULL, cfile);
+                       token = next_token(&val, NULL, cfile);
+                       new_shared_network_interface(cfile, share, val);
+                       if (!parse_semi(cfile))
+                               break;
+                       continue;
+               }
+               declaration = parse_statement(cfile, subnet->group,
+                                             SUBNET_DECL,
+                                             NULL,
+                                             declaration);
+       } while (1);
+
+       /* Add the subnet to the list of subnets in this shared net. */
+       if (share->subnets == NULL) {
+               subnet_reference(&share->subnets, subnet, MDL);
+       } else {
+               u = NULL;
+               for (t = share->subnets; t->next_sibling; t = t->next_sibling) {
+                       if (subnet_inner_than(subnet, t, 0)) {
+                               subnet_reference(&subnet->next_sibling, t, MDL);
+                               if (u) {
+                                       subnet_dereference(&u->next_sibling,
+                                                          MDL);
+                                       subnet_reference(&u->next_sibling,
+                                                        subnet, MDL);
+                               } else {
+                                       subnet_dereference(&share->subnets,
+                                                          MDL);
+                                       subnet_reference(&share->subnets,
+                                                        subnet, MDL);
+                               }
+                               subnet_dereference(&subnet, MDL);
+                               return;
+                       }
+                       u = t;
+               }
+               subnet_reference(&t->next_sibling, subnet, MDL);
+       }
+       subnet_dereference(&subnet, MDL);
+}
+
 /* subnet-declaration :==
        net NETMASK netmask RBRACE parameters declarations LBRACE */
 
@@ -2331,8 +2418,6 @@ void parse_subnet_declaration (cfile, share)
        struct iaddr iaddr;
        unsigned char addr [4];
        unsigned len = sizeof addr;
-       int declaration = 0;
-       struct interface_info *ip;
        isc_result_t status;
 
        subnet = (struct subnet *)0;
@@ -2384,65 +2469,86 @@ void parse_subnet_declaration (cfile, share)
                return;
        }
 
-       enter_subnet (subnet);
+       common_subnet_parsing(cfile, share, subnet);
+}
 
-       if (!parse_lbrace (cfile)) {
-               subnet_dereference (&subnet, MDL);
+/* subnet6-declaration :==
+       net / bits RBRACE parameters declarations LBRACE */
+
+void
+parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
+       struct subnet *subnet;
+       isc_result_t status;
+       enum dhcp_token token;
+       const char *val;
+       char *endp;
+       int ofs;
+       const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0, 
+                                   0xF0, 0xF8, 0xFC, 0xFE };
+       struct iaddr iaddr;
+
+       subnet = NULL;
+       status = subnet_allocate(&subnet, MDL);
+       if (status != ISC_R_SUCCESS) {
+               log_fatal("Allocation of new subnet failed: %s",
+                         isc_result_totext(status));
+       }
+       shared_network_reference(&subnet->shared_network, share, MDL);
+       if (!clone_group(&subnet->group, share->group, MDL)) {
+               log_fatal("Allocation of group for new subnet failed.");
+       }
+       subnet_reference(&subnet->group->subnet, subnet, MDL);
+
+       if (!parse_ip6_addr(cfile, &subnet->net)) {
+               subnet_dereference(&subnet, MDL);
                return;
        }
 
-       do {
-               token = peek_token (&val, (unsigned *)0, cfile);
-               if (token == RBRACE) {
-                       token = next_token (&val, (unsigned *)0, cfile);
-                       break;
-               } else if (token == END_OF_FILE) {
-                       token = next_token (&val, (unsigned *)0, cfile);
-                       parse_warn (cfile, "unexpected end of file");
-                       break;
-               } else if (token == INTERFACE) {
-                       token = next_token (&val, (unsigned *)0, cfile);
-                       token = next_token (&val, (unsigned *)0, cfile);
-                       new_shared_network_interface (cfile, share, val);
-                       if (!parse_semi (cfile))
-                               break;
-                       continue;
-               }
-               declaration = parse_statement (cfile, subnet -> group,
-                                              SUBNET_DECL,
-                                              (struct host_decl *)0,
-                                              declaration);
-       } while (1);
+       token = next_token(&val, NULL, cfile);
+       if (token != SLASH) {
+               parse_warn(cfile, "Expecting a '/'.");
+               skip_to_semi(cfile);
+               return;
+       }
 
-       /* Add the subnet to the list of subnets in this shared net. */
-       if (!share -> subnets)
-               subnet_reference (&share -> subnets, subnet, MDL);
-       else {
-               u = (struct subnet *)0;
-               for (t = share -> subnets;
-                    t -> next_sibling; t = t -> next_sibling) {
-                       if (subnet_inner_than (subnet, t, 0)) {
-                               subnet_reference (&subnet -> next_sibling,
-                                                 t, MDL);
-                               if (u) {
-                                       subnet_dereference (&u -> next_sibling,
-                                                           MDL);
-                                       subnet_reference (&u -> next_sibling,
-                                                         subnet, MDL);
-                               } else {
-                                       subnet_dereference (&share -> subnets,
-                                                           MDL);
-                                       subnet_reference (&share -> subnets,
-                                                         subnet, MDL);
-                               }
-                               subnet_dereference (&subnet, MDL);
-                               return;
-                       }
-                       u = t;
-               }
-               subnet_reference (&t -> next_sibling, subnet, MDL);
+       token = next_token(&val, NULL, cfile);
+       if (token != NUMBER) {
+               parse_warn(cfile, "Expecting a number.");
+               skip_to_semi(cfile);
+               return;
+       }
+
+       subnet->prefix_len = strtol(val, &endp, 10);
+       if ((subnet->prefix_len < 0) || 
+           (subnet->prefix_len > 128) || 
+           (*endp != '\0')) {
+               parse_warn(cfile, "Expecting a number between 0 and 128.");
+               skip_to_semi(cfile);
+               return;
        }
-       subnet_dereference (&subnet, MDL);
+
+       /* 
+        * Create a netmask. 
+        */
+       subnet->netmask.len = 16;
+       ofs = subnet->prefix_len / 8;
+       subnet->netmask.iabuf[ofs--] = mask[subnet->prefix_len % 8];
+       while (ofs >= 0) {
+               subnet->netmask.iabuf[ofs--] = 0xFF;
+       }
+
+       /* Validate the network number/netmask pair. */
+       iaddr = subnet_number(subnet->net, subnet->netmask);
+       if (memcmp(&iaddr, &subnet->net, 16) != 0) {
+               parse_warn(cfile,
+                  "subnet %s/%d: prefix not long enough for address.",
+                           piaddr(subnet->net), subnet->prefix_len);
+               subnet_dereference(&subnet, MDL);
+               skip_to_semi(cfile);
+               return;
+       }
+
+       common_subnet_parsing(cfile, share, subnet);
 }
 
 /* group-declaration :== RBRACE parameters declarations LBRACE */
@@ -2540,47 +2646,59 @@ void parse_group_declaration (cfile, group)
    ip-addrs-or-hostnames :== ip-addr-or-hostname
                           | ip-addrs-or-hostnames ip-addr-or-hostname */
 
-int parse_fixed_addr_param (oc, cfile)
-       struct option_cache **oc;
-       struct parse *cfile;
-{
+int
+parse_fixed_addr_param(struct option_cache **oc, 
+                      struct parse *cfile, 
+                      enum dhcp_token type) {
+       int parse_ok;
        const char *val;
        enum dhcp_token token;
-       struct expression *expr = (struct expression *)0;
+       struct expression *expr = NULL;
        struct expression *tmp, *new;
        int status;
 
        do {
-               tmp = (struct expression *)0;
-               if (parse_ip_addr_or_hostname (&tmp, cfile, 1)) {
-                       if (expr) {
-                               new = (struct expression *)0;
-                               status = make_concat (&new, expr, tmp);
-                               expression_dereference (&expr, MDL);
-                               expression_dereference (&tmp, MDL);
-                               if (!status)
+               tmp = NULL;
+               if (type == FIXED_ADDR) {
+                       parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1);
+               } else {
+                       /* INSIST(type == FIXED_ADDR6); */
+                       parse_ok = parse_ip6_addr_expr(&tmp, cfile);
+               }
+               if (parse_ok) {
+                       if (expr != NULL) {
+                               new = NULL;
+                               status = make_concat(&new, expr, tmp);
+                               expression_dereference(&expr, MDL);
+                               expression_dereference(&tmp, MDL);
+                               if (!status) {
                                        return 0;
+                               }
                                expr = new;
-                       } else
+                       } else {
                                expr = tmp;
+                       }
                } else {
-                       if (expr)
+                       if (expr != NULL) {
                                expression_dereference (&expr, MDL);
+                       }
                        return 0;
                }
-               token = peek_token (&val, (unsigned *)0, cfile);
-               if (token == COMMA)
-                       token = next_token (&val, (unsigned *)0, cfile);
+               token = peek_token(&val, NULL, cfile);
+               if (token == COMMA) {
+                       token = next_token(&val, NULL, cfile);
+               }
        } while (token == COMMA);
 
-       if (!parse_semi (cfile)) {
-               if (expr)
+       if (!parse_semi(cfile)) {
+               if (expr) {
                        expression_dereference (&expr, MDL);
+               }
                return 0;
        }
-       status = option_cache (oc, (struct data_string *)0, expr,
-                              (struct option *)0, MDL);
-       expression_dereference (&expr, MDL);
+
+       status = option_cache(oc, NULL, expr, NULL, MDL);
+       expression_dereference(&expr, MDL);
        return status;
 }
 
index 6eb66cdf804ec5faa4c04ee233a88a5eda189d07..825c394b5eb74db72c88036193c09eb2e967386f 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char ocopyright[] =
-"$Id: dhcpd.c,v 1.121 2006/07/17 15:21:45 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
+"$Id: dhcpd.c,v 1.121.26.1 2006/08/09 11:26:30 shane Exp $ Copyright 2004-2006 Internet Systems Consortium.";
 #endif
 
   static char copyright[] =
@@ -193,10 +193,8 @@ static void omapi_listener_start (void *foo)
        omapi_object_dereference (&listener, MDL);
 }
 
-int main (argc, argv, envp)
-       int argc;
-       char **argv, **envp;
-{
+int 
+main(int argc, char **argv) {
        int fd;
        int i, status;
        struct servent *ent;
@@ -222,6 +220,7 @@ int main (argc, argv, envp)
        int no_dhcpd_conf = 0;
        int no_dhcpd_db = 0;
        int no_dhcpd_pid = 0;
+       int local_family_set = 0;
 #if defined (TRACING)
        char *traceinfile = (char *)0;
        char *traceoutfile = (char *)0;
@@ -324,6 +323,20 @@ int main (argc, argv, envp)
                } else if (!strcmp (argv [i], "-q")) {
                        quiet = 1;
                        quiet_interface_discovery = 1;
+               } else if (!strcmp(argv[i], "-4")) {
+                       if (local_family_set && (local_family != AF_INET)) {
+                               log_fatal("Server cannot run in both IPv4 and "
+                                         "IPv6 mode at the same time.");
+                       }
+                       local_family = AF_INET;
+                       local_family_set = 1;
+               } else if (!strcmp(argv[i], "-6")) {
+                       if (local_family_set && (local_family != AF_INET6)) {
+                               log_fatal("Server cannot run in both IPv4 and "
+                                         "IPv6 mode at the same time.");
+                       }
+                       local_family = AF_INET6;
+                       local_family_set = 1;
                } else if (!strcmp (argv [i], "--version")) {
                        log_info ("isc-dhcpd-%s", DHCP_VERSION);
                        exit (0);
index 000f027b8e948f33e898f83c45966baa144cbd8d..446b16d242ddc8a7a46395afad51b044a9e030a3 100644 (file)
@@ -34,7 +34,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: mdb.c,v 1.82 2006/07/18 18:15:53 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
+"$Id: mdb.c,v 1.82.16.1 2006/08/09 11:26:30 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -686,29 +686,29 @@ int find_grouped_subnet (struct subnet **sp,
        return 0;
 }
 
-int subnet_inner_than (subnet, scan, warnp)
-       struct subnet *subnet, *scan;
-       int warnp;
-{
-       if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
-                    scan -> net) ||
-           addr_eq (subnet_number (scan -> net, subnet -> netmask),
-                    subnet -> net)) {
-               char n1buf [16];
+/* XXX: could speed up if everyone had a prefix length */
+int 
+subnet_inner_than(const struct subnet *subnet, 
+                 const struct subnet *scan,
+                 int warnp) {
+       if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) ||
+           addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) {
+               char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
                int i, j;
-               for (i = 0; i < 32; i++)
-                       if (subnet -> netmask.iabuf [3 - (i >> 3)]
+               for (i = 0; i < 128; i++)
+                       if (subnet->netmask.iabuf[3 - (i >> 3)]
                            & (1 << (i & 7)))
                                break;
-               for (j = 0; j < 32; j++)
-                       if (scan -> netmask.iabuf [3 - (j >> 3)] &
+               for (j = 0; j < 128; j++)
+                       if (scan->netmask.iabuf[3 - (j >> 3)] &
                            (1 << (j & 7)))
                                break;
-               strcpy (n1buf, piaddr (subnet -> net));
-               if (warnp)
-                       log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
-                             "Warning: ", n1buf, 32 - i,
-                             piaddr (scan -> net), 32 - j);
+               if (warnp) {
+                       strcpy(n1buf, piaddr(subnet->net));
+                       log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
+                             n1buf, 32 - i,
+                             piaddr(scan->net), 32 - j);
+               }
                if (i < j)
                        return 1;
        }