must not do ginode() on numbers less than ROOTINO
[unix-history] / usr / src / sbin / routed / startup.c
index 67ffafe..51503b1 100644 (file)
@@ -1,19 +1,22 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  4.3 %G%";
+static char sccsid[] = "@(#)startup.c  4.8 (Berkeley) %G%";
 #endif
 
 /*
  * Routing Table Management Daemon
  */
 #include "defs.h"
 #endif
 
 /*
  * Routing Table Management Daemon
  */
 #include "defs.h"
+#include <sys/ioctl.h>
 #include <net/if.h>
 #include <nlist.h>
 #include <net/if.h>
 #include <nlist.h>
+#include <syslog.h>
 
 struct interface *ifnet;
 int    kmem = -1;
 int    lookforinterfaces = 1;
 int    performnlist = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 
 struct interface *ifnet;
 int    kmem = -1;
 int    lookforinterfaces = 1;
 int    performnlist = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
+int    gateway = 0;            /* 1 if we are a gateway to parts beyond */
 
 struct nlist nl[] = {
 #define        N_IFNET         0
 
 struct nlist nl[] = {
 #define        N_IFNET         0
@@ -41,6 +44,8 @@ ifinit()
                        goto bad;
                }
                performnlist = 0;
                        goto bad;
                }
                performnlist = 0;
+               if (gateway > 0)
+                       rtdefault();
        }
        if (kmem < 0) {
                kmem = open("/dev/kmem", 0);
        }
        if (kmem < 0) {
                kmem = open("/dev/kmem", 0);
@@ -89,6 +94,14 @@ ifinit()
                if ((ifs.if_flags & IFF_POINTOPOINT) == 0 ||
                    if_ifwithaddr(&ifs.if_dstaddr) == 0)
                        externalinterfaces++;
                if ((ifs.if_flags & IFF_POINTOPOINT) == 0 ||
                    if_ifwithaddr(&ifs.if_dstaddr) == 0)
                        externalinterfaces++;
+               if ((ifs.if_flags & IFF_LOCAL) == 0 && gateway == 0) {
+                       /*
+                        * If we have an interface to a non-local network,
+                        * we are a candidate for use as a gateway.
+                        */
+                       gateway = 1;
+                       rtdefault();
+               }
                lseek(kmem, ifs.if_name, 0);
                read(kmem, name, sizeof (name));
                name[sizeof (name) - 1] = '\0';
                lseek(kmem, ifs.if_name, 0);
                read(kmem, name, sizeof (name));
                name[sizeof (name) - 1] = '\0';
@@ -139,10 +152,14 @@ addrouteforif(ifp)
                dst = (struct sockaddr *)&net;
        }
        rt = rtlookup(dst);
                dst = (struct sockaddr *)&net;
        }
        rt = rtlookup(dst);
-       rtadd(dst, &ifp->int_addr, ifp->int_metric,
-               ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
+       if (rt && equal(&ifp->int_addr, &rt->rt_router))
+               return;
+       if (ifp->int_transitions++ > 0)
+               syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
        if (rt)
                rtdelete(rt);
        if (rt)
                rtdelete(rt);
+       rtadd(dst, &ifp->int_addr, ifp->int_metric,
+               ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
 }
 
 /*
 }
 
 /*
@@ -165,6 +182,7 @@ gwkludge()
        char *type, *dname, *gname, *qual, buf[BUFSIZ];
        struct interface *ifp;
        int metric;
        char *type, *dname, *gname, *qual, buf[BUFSIZ];
        struct interface *ifp;
        int metric;
+       struct rt_entry route;
 
        fp = fopen("/etc/gateways", "r");
        if (fp == NULL)
 
        fp = fopen("/etc/gateways", "r");
        if (fp == NULL)
@@ -175,6 +193,7 @@ gwkludge()
        type = buf + (((BUFSIZ - 64) * 2) / 3);
        bzero((char *)&dst, sizeof (dst));
        bzero((char *)&gate, sizeof (gate));
        type = buf + (((BUFSIZ - 64) * 2) / 3);
        bzero((char *)&dst, sizeof (dst));
        bzero((char *)&gate, sizeof (gate));
+       bzero((char *)&route, sizeof(route));
        /* format: {net | host} XX gateway XX metric DD [passive]\n */
 #define        readentry(fp) \
        fscanf((fp), "%s %s gateway %s metric %d %s\n", \
        /* format: {net | host} XX gateway XX metric DD [passive]\n */
 #define        readentry(fp) \
        fscanf((fp), "%s %s gateway %s metric %d %s\n", \
@@ -186,6 +205,26 @@ gwkludge()
                        continue;
                if (!gethostnameornumber(gname, &gate))
                        continue;
                        continue;
                if (!gethostnameornumber(gname, &gate))
                        continue;
+               if (strcmp(qual, "passive") == 0) {
+                       /*
+                        * Passive entries aren't placed in our tables,
+                        * only the kernel's, so we don't copy all of the
+                        * external routing information within a net.
+                        * Internal machines should use the default
+                        * route to a suitable gateway (like us).
+                        */
+                       route.rt_dst = *(struct sockaddr *) &dst;
+                       route.rt_router = *(struct sockaddr *) &gate;
+                       route.rt_flags = RTF_UP;
+                       if (strcmp(type, "host") == 0)
+                               route.rt_flags |= RTF_HOST;
+                       if (metric)
+                               route.rt_flags |= RTF_GATEWAY;
+                       (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt);
+                       continue;
+               }
+               /* assume no duplicate entries */
+               externalinterfaces++;
                ifp = (struct interface *)malloc(sizeof (*ifp));
                bzero((char *)ifp, sizeof (*ifp));
                ifp->int_flags = IFF_REMOTE;
                ifp = (struct interface *)malloc(sizeof (*ifp));
                bzero((char *)ifp, sizeof (*ifp));
                ifp->int_flags = IFF_REMOTE;
@@ -195,11 +234,6 @@ gwkludge()
                        ifp->int_flags |= IFF_POINTOPOINT;
                        ifp->int_dstaddr = *((struct sockaddr *)&dst);
                }
                        ifp->int_flags |= IFF_POINTOPOINT;
                        ifp->int_dstaddr = *((struct sockaddr *)&dst);
                }
-               if (strcmp(qual, "passive") == 0)
-                       ifp->int_flags |= IFF_PASSIVE;
-               else
-                       /* assume no duplicate entries */
-                       externalinterfaces++;
                ifp->int_addr = *((struct sockaddr *)&gate);
                ifp->int_metric = metric;
                ifp->int_next = ifnet;
                ifp->int_addr = *((struct sockaddr *)&gate);
                ifp->int_metric = metric;
                ifp->int_next = ifnet;