BSD 4_3_Net_2 release
[unix-history] / usr / src / sbin / routed / startup.c
index 61c1426..f88d593 100644 (file)
@@ -1,12 +1,39 @@
 /*
 /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1983, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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) %G%";
-#endif not lint
+static char sccsid[] = "@(#)startup.c  5.19 (Berkeley) 2/28/91";
+#endif /* not lint */
 
 /*
  * Routing Table Management Daemon
 
 /*
  * Routing Table Management Daemon
@@ -15,8 +42,11 @@ static char sccsid[] = "@(#)startup.c        5.9 (Berkeley) %G%";
 #include <sys/ioctl.h>
 #include <net/if.h>
 #include <syslog.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
 #include <syslog.h>
+#include <stdlib.h>
+#include "pathnames.h"
 
 struct interface *ifnet;
 
 struct interface *ifnet;
+struct interface **ifnext = &ifnet;
 int    lookforinterfaces = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 int    foundloopback;                  /* valid flag for loopaddr */
 int    lookforinterfaces = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 int    foundloopback;                  /* valid flag for loopaddr */
@@ -31,8 +61,8 @@ struct        sockaddr loopaddr;              /* our address on loopback */
 ifinit()
 {
        struct interface ifs, *ifp;
 ifinit()
 {
        struct interface ifs, *ifp;
-       int s, n;
-       char buf[BUFSIZ];
+       int s;
+       char buf[BUFSIZ], *cp, *cplim;
         struct ifconf ifc;
         struct ifreq ifreq, *ifr;
         struct sockaddr_in *sin;
         struct ifconf ifc;
         struct ifreq ifreq, *ifr;
         struct sockaddr_in *sin;
@@ -40,23 +70,34 @@ ifinit()
 
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                syslog(LOG_ERR, "socket: %m");
 
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                syslog(LOG_ERR, "socket: %m");
-               exit(1);
+               close(s);
+                return;
        }
         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);
        }
         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);
-                return (0);
+                return;
         }
         ifr = ifc.ifc_req;
        lookforinterfaces = 0;
         }
         ifr = ifc.ifc_req;
        lookforinterfaces = 0;
-        for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) {
+#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)) {
+               ifr = (struct ifreq *)cp;
                bzero((char *)&ifs, sizeof(ifs));
                ifs.int_addr = ifr->ifr_addr;
                ifreq = *ifr;
                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
                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)");
+                        syslog(LOG_ERR, "%s: ioctl (get interface flags)",
+                           ifr->ifr_name);
                         continue;
                 }
                ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
                         continue;
                 }
                ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
@@ -65,39 +106,72 @@ ifinit()
                        lookforinterfaces = 1;
                        continue;
                }
                        lookforinterfaces = 1;
                        continue;
                }
-               /* already known to us? */
-               if (if_ifwithaddr(&ifs.int_addr))
-                       continue;
                /* argh, this'll have to change sometime */
                if (ifs.int_addr.sa_family != AF_INET)
                        continue;
                /* argh, this'll have to change sometime */
                if (ifs.int_addr.sa_family != AF_INET)
                        continue;
+                if (ifs.int_flags & IFF_POINTOPOINT) {
+                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
+                                   ifr->ifr_name);
+                                continue;
+                       }
+                       if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
+                               lookforinterfaces = 1;
+                               continue;
+                       }
+                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+               }
+               /*
+                * already known to us?
+                * This allows multiple point-to-point links
+                * to share a source address (possibly with one
+                * other link), but assumes that there will not be
+                * multiple links with the same destination address.
+                */
+               if (ifs.int_flags & IFF_POINTOPOINT) {
+                       if (if_ifwithdstaddr(&ifs.int_dstaddr))
+                               continue;
+               } else if (if_ifwithaddr(&ifs.int_addr))
+                       continue;
                if (ifs.int_flags & IFF_LOOPBACK) {
                if (ifs.int_flags & IFF_LOOPBACK) {
+                       ifs.int_flags |= IFF_PASSIVE;
                        foundloopback = 1;
                        loopaddr = ifs.int_addr;
                        for (ifp = ifnet; ifp; ifp = ifp->int_next)
                            if (ifp->int_flags & IFF_POINTOPOINT)
                                add_ptopt_localrt(ifp);
                }
                        foundloopback = 1;
                        loopaddr = ifs.int_addr;
                        for (ifp = ifnet; ifp; ifp = ifp->int_next)
                            if (ifp->int_flags & IFF_POINTOPOINT)
                                add_ptopt_localrt(ifp);
                }
-                if (ifs.int_flags & IFF_POINTOPOINT) {
-                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get dstaddr)");
-                                continue;
-                       }
-                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
-               }
                 if (ifs.int_flags & IFF_BROADCAST) {
                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
                 if (ifs.int_flags & IFF_BROADCAST) {
                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get broadaddr)");
+                                syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
+                                   ifr->ifr_name);
                                 continue;
                         }
                                 continue;
                         }
+#ifndef sun
                        ifs.int_broadaddr = ifreq.ifr_broadaddr;
                        ifs.int_broadaddr = ifreq.ifr_broadaddr;
+#else
+                       ifs.int_broadaddr = ifreq.ifr_addr;
+#endif
                }
                }
-               if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0)
-                       syslog(LOG_ERR, "ioctl (get metric)");
-               else
+#ifdef SIOCGIFMETRIC
+               if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
+                       syslog(LOG_ERR, "%s: ioctl (get metric)",
+                           ifr->ifr_name);
+                       ifs.int_metric = 0;
+               } else
                        ifs.int_metric = ifreq.ifr_metric;
                        ifs.int_metric = ifreq.ifr_metric;
+#else
+               ifs.int_metric = 0;
+#endif
+               /*
+                * Use a minimum metric of one;
+                * treat the interface metric (default 0)
+                * as an increment to the hop count of one.
+                */
+               ifs.int_metric++;
                if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
                if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
-                       syslog(LOG_ERR, "ioctl (get netmask)");
+                       syslog(LOG_ERR, "%s: ioctl (get netmask)",
+                           ifr->ifr_name);
                        continue;
                }
                sin = (struct sockaddr_in *)&ifreq.ifr_addr;
                        continue;
                }
                sin = (struct sockaddr_in *)&ifreq.ifr_addr;
@@ -142,11 +216,12 @@ ifinit()
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
                        syslog(LOG_ERR, "routed: ifinit: out of memory\n");
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
                        syslog(LOG_ERR, "routed: ifinit: out of memory\n");
+                       close(s);
                        return;
                }
                strcpy(ifp->int_name, ifr->ifr_name);
                        return;
                }
                strcpy(ifp->int_name, ifr->ifr_name);
-               ifp->int_next = ifnet;
-               ifnet = ifp;
+               *ifnext = ifp;
+               ifnext = &ifp->int_next;
                traceinit(ifp);
                addrouteforif(ifp);
        }
                traceinit(ifp);
                addrouteforif(ifp);
        }
@@ -166,7 +241,7 @@ addrouteforif(ifp)
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
-       int state, metric;
+       int state;
        register struct rt_entry *rt;
 
        if (ifp->int_flags & IFF_POINTOPOINT)
        register struct rt_entry *rt;
 
        if (ifp->int_flags & IFF_POINTOPOINT)
@@ -249,7 +324,7 @@ add_ptopt_localrt(ifp)
                        return;
                rtdelete(rt);
        }
                        return;
                rtdelete(rt);
        }
-       rtadd(dst, &loopaddr, 0, state);
+       rtadd(dst, &loopaddr, 1, state);
 }
 
 /*
 }
 
 /*
@@ -276,7 +351,7 @@ gwkludge()
        int metric, n;
        struct rt_entry route;
 
        int metric, n;
        struct rt_entry route;
 
-       fp = fopen("/etc/gateways", "r");
+       fp = fopen(_PATH_GATEWAYS, "r");
        if (fp == NULL)
                return;
        qual = buf;
        if (fp == NULL)
                return;
        qual = buf;
@@ -297,6 +372,8 @@ gwkludge()
                        continue;
                if (!gethostnameornumber(gname, &gate))
                        continue;
                        continue;
                if (!gethostnameornumber(gname, &gate))
                        continue;
+               if (metric == 0)                        /* XXX */
+                       metric = 1;
                if (strcmp(qual, "passive") == 0) {
                        /*
                         * Passive entries aren't placed in our tables,
                if (strcmp(qual, "passive") == 0) {
                        /*
                         * Passive entries aren't placed in our tables,