BSD 4_4 release
[unix-history] / usr / src / sbin / XNSrouted / startup.c
index aa99968..bcb5615 100644 (file)
@@ -1,37 +1,57 @@
 /*
 /*
- * Copyright (c) 1985 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This file includes significant work done at Cornell University by
  * Bill Nesheim.  That work included by permission.
  *
  *
  * This file includes significant work done at Cornell University by
  * Bill Nesheim.  That work included by permission.
  *
- * Redistribution and use in source and binary forms are permitted
- * provided that: (1) source distributions retain this entire copyright
- * notice and comment, and (2) distributions including binaries display
- * the following acknowledgement:  ``This product includes software
- * developed by the University of California, Berkeley and its contributors''
- * in the documentation or other materials provided with the distribution
- * and in all advertising materials mentioning features or use of this
- * software. Neither the name of the University nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  5.9 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)startup.c  8.1 (Berkeley) 6/5/93";
 #endif /* not lint */
 
 /*
  * Routing Table Management Daemon
  */
 #include "defs.h"
 #endif /* not lint */
 
 /*
  * Routing Table Management Daemon
  */
 #include "defs.h"
+
+#include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
 #include <net/if.h>
 #include <net/if.h>
+#include <net/if_dl.h>
+
 #include <nlist.h>
 #include <nlist.h>
-#include <syslog.h>
+#include <stdlib.h>
 
 struct interface *ifnet;
 int    lookforinterfaces = 1;
 
 struct interface *ifnet;
 int    lookforinterfaces = 1;
@@ -41,6 +61,48 @@ int  externalinterfaces = 0;         /* # of remote and local interfaces */
 char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 
 char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 
+void
+quit(s)
+       char *s;
+{
+       extern int errno;
+       int sverrno = errno;
+
+       (void) fprintf(stderr, "route: ");
+       if (s)
+               (void) fprintf(stderr, "%s: ", s);
+       (void) fprintf(stderr, "%s\n", strerror(sverrno));
+       exit(1);
+       /* NOTREACHED */
+}
+
+struct rt_addrinfo info;
+/* Sleazy use of local variables throughout file, warning!!!! */
+#define netmask        info.rti_info[RTAX_NETMASK]
+#define ifaaddr        info.rti_info[RTAX_IFA]
+#define brdaddr        info.rti_info[RTAX_BRD]
+
+#define ROUNDUP(a) \
+       ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+void
+rt_xaddrs(cp, cplim, rtinfo)
+       register caddr_t cp, cplim;
+       register struct rt_addrinfo *rtinfo;
+{
+       register struct sockaddr *sa;
+       register int i;
+
+       bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
+       for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
+               if ((rtinfo->rti_addrs & (1 << i)) == 0)
+                       continue;
+               rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
+               ADVANCE(cp, sa);
+       }
+}
+
 /*
  * Find the network interfaces which have configured themselves.
  * If the interface is present but not yet up (for example an
 /*
  * Find the network interfaces which have configured themselves.
  * If the interface is present but not yet up (for example an
@@ -50,62 +112,73 @@ char ether_broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 ifinit()
 {
        struct interface ifs, *ifp;
 ifinit()
 {
        struct interface ifs, *ifp;
-       int s;
-        struct ifconf ifc;
-       char buf[BUFSIZ], *cp, *cplim;
-        struct ifreq ifreq, *ifr;
+       size_t needed;
+       int mib[6], no_nsaddr = 0, flags = 0;
+       char *buf, *cplim, *cp;
+       register struct if_msghdr *ifm;
+       register struct ifa_msghdr *ifam;
+       struct sockaddr_dl *sdl;
        u_long i;
 
        u_long i;
 
-       if ((s = socket(AF_NS, SOCK_DGRAM, 0)) < 0) {
-               syslog(LOG_ERR, "socket: %m");
-               exit(1);
-       }
-        ifc.ifc_len = sizeof (buf);
-        ifc.ifc_buf = buf;
-        if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
-                syslog(LOG_ERR, "ioctl (get interface configuration)");
-               close(s);
-                exit(1);
-        }
-        ifr = ifc.ifc_req;
+        mib[0] = CTL_NET;
+        mib[1] = PF_ROUTE;
+        mib[2] = 0;
+        mib[3] = AF_NS;
+        mib[4] = NET_RT_IFLIST;
+        mib[5] = 0;
+        if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+                quit("route-sysctl-estimate");
+       if ((buf = malloc(needed)) == NULL)
+               quit("malloc");
+        if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
        lookforinterfaces = 0;
        lookforinterfaces = 0;
-#ifdef RTM_ADD
-#define max(a, b) (a > b ? a : b)
-#define size(p)        max((p).sa_len, sizeof(p))
-#else
-#define size(p) (sizeof (p))
-#endif
-       cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
-       for (cp = buf; cp < cplim;
-                       cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
-               bzero((char *)&ifs, sizeof(ifs));
-               ifs.int_addr = ifr->ifr_addr;
-               ifreq = *ifr;
-                if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
-                        syslog(LOG_ERR, "ioctl (get interface flags)");
-                        continue;
-                }
-               ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
-               if ((ifs.int_flags & IFF_UP) == 0 ||
-                   ifr->ifr_addr.sa_family == AF_UNSPEC) {
-                       lookforinterfaces = 1;
+       cplim = buf + needed;
+       for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
+               ifm = (struct if_msghdr *)cp;
+               if (ifm->ifm_type == RTM_IFINFO) {
+                       bzero(&ifs, sizeof(ifs));
+                       ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE;
+                       if ((flags & IFF_UP) == 0 || no_nsaddr)
+                               lookforinterfaces = 1;
+                       sdl = (struct sockaddr_dl *) (ifm + 1);
+                       sdl->sdl_data[sdl->sdl_nlen] = 0;
+                       no_nsaddr = 1;
+                       continue;
+               }
+               if (ifm->ifm_type != RTM_NEWADDR)
+                       quit("ifinit: out of sync");
+               if ((flags & IFF_UP) == 0)
+                       continue;
+               ifam = (struct ifa_msghdr *)ifm;
+               info.rti_addrs = ifam->ifam_addrs;
+               rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
+               if (ifaaddr == 0) {
+                       syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
                        continue;
                }
                        continue;
                }
+               ifs.int_addr = *ifaaddr;
                if (ifs.int_addr.sa_family != AF_NS)
                        continue;
                if (ifs.int_addr.sa_family != AF_NS)
                        continue;
-                if (ifs.int_flags & IFF_POINTOPOINT) {
-                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get dstaddr): %m");
-                                continue;
+               no_nsaddr = 0;
+               if (ifs.int_flags & IFF_POINTOPOINT) {
+                       if (brdaddr == 0) {
+                               syslog(LOG_ERR, "%s: (get dstaddr)",
+                                       sdl->sdl_data);
+                               continue;
+                       }
+                       if (brdaddr->sa_family == AF_UNSPEC) {
+                               lookforinterfaces = 1;
+                               continue;
                        }
                        }
-                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+                       ifs.int_dstaddr = *brdaddr;
                }
                }
-                if (ifs.int_flags & IFF_BROADCAST) {
-                        if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get broadaddr: %m");
-                                continue;
-                        }
-                       ifs.int_broadaddr = ifreq.ifr_broadaddr;
+               if (ifs.int_flags & IFF_BROADCAST) {
+                       if (brdaddr == 0) {
+                               syslog(LOG_ERR, "%s: (get broadaddr)",
+                                       sdl->sdl_data);
+                               continue;
+                       }
+                       ifs.int_dstaddr = *brdaddr;
                }
                /* 
                 * already known to us? 
                }
                /* 
                 * already known to us? 
@@ -118,11 +191,13 @@ ifinit()
                        if_ifwithaddr(&ifs.int_addr)))
                        continue;
                /* no one cares about software loopback interfaces */
                        if_ifwithaddr(&ifs.int_addr)))
                        continue;
                /* no one cares about software loopback interfaces */
-               if (strncmp(ifr->ifr_name,"lo", 2)==0)
+               if (ifs.int_flags & IFF_LOOPBACK)
                        continue;
                        continue;
-               ifp = (struct interface *)malloc(sizeof (struct interface));
+               ifp = (struct interface *)
+                       malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
                if (ifp == 0) {
                if (ifp == 0) {
-                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
+                       syslog(LOG_ERR, "XNSrouted: out of memory\n");
+                       lookforinterfaces = 1;
                        break;
                }
                *ifp = ifs;
                        break;
                }
                *ifp = ifs;
@@ -143,13 +218,9 @@ ifinit()
                 */
                if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
                        supplier = 1;
                 */
                if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
                        supplier = 1;
-               ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
-               if (ifp->int_name == 0) {
-                       syslog(LOG_ERR,"XNSrouted: out of memory\n");
-                       exit(1);
-               }
-               strcpy(ifp->int_name, ifr->ifr_name);
-               ifp->int_metric = 0;
+               ifp->int_name = (char *)(ifp + 1);
+               strcpy(ifp->int_name, sdl->sdl_data);
+               ifp->int_metric = ifam->ifam_metric;
                ifp->int_next = ifnet;
                ifnet = ifp;
                traceinit(ifp);
                ifp->int_next = ifnet;
                ifnet = ifp;
                traceinit(ifp);
@@ -157,7 +228,7 @@ ifinit()
        }
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
        }
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
-       close(s);
+       free(buf);
 }
 
 addrouteforif(ifp)
 }
 
 addrouteforif(ifp)