BSD 4_3_Tahoe release
[unix-history] / usr / src / etc / routed / startup.c
index e00a4a0..729e9cf 100644 (file)
@@ -1,12 +1,18 @@
 /*
 /*
- * 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 are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  5.7 (Berkeley) 6/3/86";
-#endif not lint
+static char sccsid[] = "@(#)startup.c  5.13 (Berkeley) 6/6/88";
+#endif /* not lint */
 
 /*
  * Routing Table Management Daemon
 
 /*
  * Routing Table Management Daemon
@@ -19,6 +25,8 @@ static char sccsid[] = "@(#)startup.c 5.7 (Berkeley) 6/3/86";
 struct interface *ifnet;
 int    lookforinterfaces = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 struct interface *ifnet;
 int    lookforinterfaces = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
+int    foundloopback;                  /* valid flag for loopaddr */
+struct sockaddr loopaddr;              /* our address on loopback */
 
 /*
  * Find the network interfaces which have configured themselves.
 
 /*
  * Find the network interfaces which have configured themselves.
@@ -58,20 +66,34 @@ ifinit()
                         continue;
                 }
                ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
                         continue;
                 }
                ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
-               /* no one cares about software loopback interfaces */
-               if (ifs.int_flags & IFF_LOOPBACK)
-                       continue;
                if ((ifs.int_flags & IFF_UP) == 0 ||
                    ifr->ifr_addr.sa_family == AF_UNSPEC) {
                        lookforinterfaces = 1;
                        continue;
                }
                if ((ifs.int_flags & IFF_UP) == 0 ||
                    ifr->ifr_addr.sa_family == AF_UNSPEC) {
                        lookforinterfaces = 1;
                        continue;
                }
-               /* already known to us? */
-               if (if_ifwithaddr(&ifs.int_addr))
+               /*
+                * 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;
                /* argh, this'll have to change sometime */
                if (ifs.int_addr.sa_family != AF_INET)
                        continue;
                        continue;
                /* argh, this'll have to change sometime */
                if (ifs.int_addr.sa_family != AF_INET)
                        continue;
+               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);
+               }
                 if (ifs.int_flags & IFF_POINTOPOINT) {
                         if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
                                 syslog(LOG_ERR, "ioctl (get dstaddr)");
                 if (ifs.int_flags & IFF_POINTOPOINT) {
                         if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
                                 syslog(LOG_ERR, "ioctl (get dstaddr)");
@@ -90,6 +112,12 @@ ifinit()
                        syslog(LOG_ERR, "ioctl (get metric)");
                else
                        ifs.int_metric = ifreq.ifr_metric;
                        syslog(LOG_ERR, "ioctl (get metric)");
                else
                        ifs.int_metric = ifreq.ifr_metric;
+               /*
+                * 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) {
                        syslog(LOG_ERR, "ioctl (get netmask)");
                        continue;
                if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
                        syslog(LOG_ERR, "ioctl (get netmask)");
                        continue;
@@ -120,8 +148,9 @@ ifinit()
                 * back to ourself.  This is used below to
                 * decide if we should be a routing ``supplier''.
                 */
                 * back to ourself.  This is used below to
                 * decide if we should be a routing ``supplier''.
                 */
-               if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
-                   if_ifwithaddr(&ifs.int_dstaddr) == 0)
+               if ((ifs.int_flags & IFF_LOOPBACK) == 0 &&
+                   ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
+                   if_ifwithaddr(&ifs.int_dstaddr) == 0))
                        externalinterfaces++;
                /*
                 * If we have a point-to-point link, we want to act
                        externalinterfaces++;
                /*
                 * If we have a point-to-point link, we want to act
@@ -134,7 +163,8 @@ ifinit()
                ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
                ifp->int_name = malloc(strlen(ifr->ifr_name) + 1);
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
-                       goto bad;               /* ??? */
+                       syslog(LOG_ERR, "routed: ifinit: out of memory\n");
+                       return;
                }
                strcpy(ifp->int_name, ifr->ifr_name);
                ifp->int_next = ifnet;
                }
                strcpy(ifp->int_name, ifr->ifr_name);
                ifp->int_next = ifnet;
@@ -145,12 +175,6 @@ ifinit()
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
        close(s);
        if (externalinterfaces > 1 && supplier < 0)
                supplier = 1;
        close(s);
-       return;
-bad:
-       sleep(60);
-       close(kmem), close(s);
-       execv("/etc/routed", argv0);
-       _exit(0177);
 }
 
 /*
 }
 
 /*
@@ -160,12 +184,12 @@ bad:
  * INTERNET SPECIFIC.
  */
 addrouteforif(ifp)
  * INTERNET SPECIFIC.
  */
 addrouteforif(ifp)
-       struct interface *ifp;
+       register struct interface *ifp;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
-       int state, metric;
-       struct rt_entry *rt;
+       int state;
+       register struct rt_entry *rt;
 
        if (ifp->int_flags & IFF_POINTOPOINT)
                dst = &ifp->int_dstaddr;
 
        if (ifp->int_flags & IFF_POINTOPOINT)
                dst = &ifp->int_dstaddr;
@@ -187,19 +211,67 @@ addrouteforif(ifp)
         * This is meant for external viewers.
         */
        if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
         * This is meant for external viewers.
         */
        if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
+               struct in_addr subnet;
+
+               subnet = net.sin_addr;
                net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
                rt = rtfind(dst);
                if (rt == 0)
                        rtadd(dst, &ifp->int_addr, ifp->int_metric,
                            ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
                net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
                rt = rtfind(dst);
                if (rt == 0)
                        rtadd(dst, &ifp->int_addr, ifp->int_metric,
                            ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
-                               RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
-               net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
+                           RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
+               else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == 
+                   (RTS_INTERNAL|RTS_SUBNET) &&
+                   ifp->int_metric < rt->rt_metric)
+                       rtchange(rt, &rt->rt_router, ifp->int_metric);
+               net.sin_addr = subnet;
        }
        if (ifp->int_transitions++ > 0)
                syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
        }
        if (ifp->int_transitions++ > 0)
                syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
-       rtadd(dst, &ifp->int_addr, ifp->int_metric,
-           ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE|IFF_SUBNET));
+       state = ifp->int_flags &
+           (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
+       if (ifp->int_flags & IFF_POINTOPOINT &&
+           (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
+           ifp->int_netmask) != ifp->int_net)
+               state &= ~RTS_SUBNET;
+       if (ifp->int_flags & IFF_LOOPBACK)
+               state |= RTS_EXTERNAL;
+       rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
+       if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
+               add_ptopt_localrt(ifp);
+}
 
 
+/*
+ * Add route to local end of point-to-point using loopback.
+ * If a route to this network is being sent to neighbors on other nets,
+ * mark this route as subnet so we don't have to propagate it too.
+ */
+add_ptopt_localrt(ifp)
+       register struct interface *ifp;
+{
+       struct rt_entry *rt;
+       struct sockaddr *dst;
+       struct sockaddr_in net;
+       int state;
+
+       state = RTS_INTERFACE | RTS_PASSIVE;
+
+       /* look for route to logical network */
+       bzero((char *)&net, sizeof (net));
+       net.sin_family = AF_INET;
+       net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
+       dst = (struct sockaddr *)&net;
+       rt = rtfind(dst);
+       if (rt && rt->rt_state & RTS_INTERNAL)
+               state |= RTS_SUBNET;
+
+       dst = &ifp->int_addr;
+       if (rt = rtfind(dst)) {
+               if (rt && rt->rt_state & RTS_INTERFACE)
+                       return;
+               rtdelete(rt);
+       }
+       rtadd(dst, &loopaddr, 1, state);
 }
 
 /*
 }
 
 /*
@@ -214,6 +286,8 @@ addrouteforif(ifp)
  * not marked passive are treated as if they were directly
  * connected -- they're added into the interface list so we'll
  * send them routing updates.
  * not marked passive are treated as if they were directly
  * connected -- they're added into the interface list so we'll
  * send them routing updates.
+ *
+ * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP.
  */
 gwkludge()
 {
  */
 gwkludge()
 {
@@ -234,7 +308,7 @@ gwkludge()
        bzero((char *)&dst, sizeof (dst));
        bzero((char *)&gate, sizeof (gate));
        bzero((char *)&route, sizeof(route));
        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 */
+/* format: {net | host} XX gateway XX metric DD [passive | external]\n */
 #define        readentry(fp) \
        fscanf((fp), "%s %s gateway %s metric %d %s\n", \
                type, dname, gname, &metric, qual)
 #define        readentry(fp) \
        fscanf((fp), "%s %s gateway %s metric %d %s\n", \
                type, dname, gname, &metric, qual)
@@ -245,6 +319,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,