rework interface metrics to invert perspective; other misc. fixes
authorMike Karels <karels@ucbvax.Berkeley.EDU>
Fri, 29 May 1987 02:26:15 +0000 (18:26 -0800)
committerMike Karels <karels@ucbvax.Berkeley.EDU>
Fri, 29 May 1987 02:26:15 +0000 (18:26 -0800)
SCCS-vsn: sbin/routed/af.c 5.5
SCCS-vsn: sbin/routed/af.h 5.4
SCCS-vsn: sbin/routed/inet.c 5.5
SCCS-vsn: sbin/routed/input.c 5.12
SCCS-vsn: sbin/routed/main.c 5.11
SCCS-vsn: sbin/routed/output.c 5.7
SCCS-vsn: sbin/routed/startup.c 5.9
SCCS-vsn: sbin/routed/table.h 5.4
SCCS-vsn: sbin/routed/tables.c 5.10

usr/src/sbin/routed/af.c
usr/src/sbin/routed/af.h
usr/src/sbin/routed/inet.c
usr/src/sbin/routed/input.c
usr/src/sbin/routed/main.c
usr/src/sbin/routed/output.c
usr/src/sbin/routed/startup.c
usr/src/sbin/routed/table.h
usr/src/sbin/routed/tables.c

index 67d273e..2fc61e0 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)af.c       5.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)af.c       5.5 (Berkeley) %G%";
 #endif not lint
 
 #include "defs.h"
 #endif not lint
 
 #include "defs.h"
@@ -15,14 +15,14 @@ static char sccsid[] = "@(#)af.c    5.4 (Berkeley) %G%";
  */
 int    inet_hash(), inet_netmatch(), inet_output(),
        inet_portmatch(), inet_portcheck(),
  */
 int    inet_hash(), inet_netmatch(), inet_output(),
        inet_portmatch(), inet_portcheck(),
-       inet_checkhost(), inet_rtflags(), inet_sendsubnet(), inet_canon();
+       inet_checkhost(), inet_rtflags(), inet_sendroute(), inet_canon();
 char   *inet_format();
 
 #define NIL    { 0 }
 #define        INET \
        { inet_hash,            inet_netmatch,          inet_output, \
          inet_portmatch,       inet_portcheck,         inet_checkhost, \
 char   *inet_format();
 
 #define NIL    { 0 }
 #define        INET \
        { inet_hash,            inet_netmatch,          inet_output, \
          inet_portmatch,       inet_portcheck,         inet_checkhost, \
-         inet_rtflags,         inet_sendsubnet,        inet_canon, \
+         inet_rtflags,         inet_sendroute,         inet_canon, \
          inet_format \
        }
 
          inet_format \
        }
 
index b9b825f..8aa9f7c 100644 (file)
@@ -3,7 +3,7 @@
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)af.h        5.3 (Berkeley) %G%
+ *     @(#)af.h        5.4 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -21,7 +21,7 @@ struct afswitch {
        int     (*af_portcheck)();      /* packet from privileged peer? */
        int     (*af_checkhost)();      /* tells if address is valid */
        int     (*af_rtflags)();        /* get flags for route (host or net) */
        int     (*af_portcheck)();      /* packet from privileged peer? */
        int     (*af_checkhost)();      /* tells if address is valid */
        int     (*af_rtflags)();        /* get flags for route (host or net) */
-       int     (*af_sendsubnet)();     /* check bounds of subnet broadcast */
+       int     (*af_sendroute)();      /* check bounds of subnet broadcast */
        int     (*af_canon)();          /* canonicalize address for compares */
        char    *(*af_format)();        /* convert address to string */
 };
        int     (*af_canon)();          /* canonicalize address for compares */
        char    *(*af_format)();        /* convert address to string */
 };
index ef7c52e..ce4c329 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)inet.c     5.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)inet.c     5.5 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -144,11 +144,11 @@ inet_rtflags(sin)
 }
 
 /*
 }
 
 /*
- * Return true if a route to subnet of route rt should be sent to dst.
- * Send it only if dst is on the same logical network,
- * or the route is the "internal" route for the net.
+ * Return true if a route to subnet/host of route rt should be sent to dst.
+ * Send it only if dst is on the same logical network if not "internal",
+ * otherwise only if the route is the "internal" route for the logical net.
  */
  */
-inet_sendsubnet(rt, dst)
+inet_sendroute(rt, dst)
        struct rt_entry *rt;
        struct sockaddr_in *dst;
 {
        struct rt_entry *rt;
        struct sockaddr_in *dst;
 {
index 7a549d2..0b067b7 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)input.c    5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)input.c    5.12 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -115,7 +115,8 @@ rip_input(from, size)
                ifp = if_ifwithaddr(from);
                if (ifp) {
                        rt = rtfind(from);
                ifp = if_ifwithaddr(from);
                if (ifp) {
                        rt = rtfind(from);
-                       if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0)
+                       if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) &&
+                           rt->rt_metric >= ifp->int_metric) 
                                addrouteforif(ifp);
                        else
                                rt->rt_timer = 0;
                                addrouteforif(ifp);
                        else
                                rt->rt_timer = 0;
@@ -129,7 +130,8 @@ rip_input(from, size)
                if ((rt = rtfind(from)) &&
                    (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
                        rt->rt_timer = 0;
                if ((rt = rtfind(from)) &&
                    (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE)))
                        rt->rt_timer = 0;
-               else if (ifp = if_ifwithdstaddr(from))
+               else if ((ifp = if_ifwithdstaddr(from)) &&
+                   (rt == 0 || rt->rt_metric >= ifp->int_metric))
                        addrouteforif(ifp);
                /*
                 * "Authenticate" router from which message originated.
                        addrouteforif(ifp);
                /*
                 * "Authenticate" router from which message originated.
@@ -177,13 +179,29 @@ rip_input(from, size)
                                   from->sa_family);
                                continue;
                        }
                                   from->sa_family);
                                continue;
                        }
+                       /*
+                        * Adjust metric according to incoming interface.
+                        */
+                       if ((unsigned)n->rip_metric < HOPCNT_INFINITY)
+                               n->rip_metric += ifp->int_metric;
                        rt = rtlookup(&n->rip_dst);
                        if (rt == 0 ||
                            (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
                            (RTS_INTERNAL|RTS_INTERFACE)) {
                        rt = rtlookup(&n->rip_dst);
                        if (rt == 0 ||
                            (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) ==
                            (RTS_INTERNAL|RTS_INTERFACE)) {
+                               /*
+                                * If we're hearing a logical network route
+                                * back from a peer to which we sent it,
+                                * ignore it.
+                                */
+                               if (rt && rt->rt_state & RTS_SUBNET &&
+                                   (*afp->af_sendroute)(rt, from))
+                                       continue;
+                               /*
+                                * Look for an equivalent route that includes
+                                * this one before adding this route.
+                                */
                                rt = rtfind(&n->rip_dst);
                                rt = rtfind(&n->rip_dst);
-                               if (rt && equal(from, &rt->rt_router) &&
-                                   rt->rt_metric <= n->rip_metric)
+                               if (rt && equal(from, &rt->rt_router))
                                        continue;
                                if (n->rip_metric < HOPCNT_INFINITY)
                                    rtadd(&n->rip_dst, from, n->rip_metric, 0);
                                        continue;
                                if (n->rip_metric < HOPCNT_INFINITY)
                                    rtadd(&n->rip_dst, from, n->rip_metric, 0);
@@ -197,14 +215,15 @@ rip_input(from, size)
                        if (equal(from, &rt->rt_router)) {
                                if (n->rip_metric != rt->rt_metric) {
                                        rtchange(rt, from, n->rip_metric);
                        if (equal(from, &rt->rt_router)) {
                                if (n->rip_metric != rt->rt_metric) {
                                        rtchange(rt, from, n->rip_metric);
-                                       if (rt->rt_metric == HOPCNT_INFINITY)
+                                       if (rt->rt_metric >= HOPCNT_INFINITY)
                                                rt->rt_timer =
                                                    GARBAGE_TIME - EXPIRE_TIME;
                                } else if (rt->rt_metric < HOPCNT_INFINITY)
                                        rt->rt_timer = 0;
                        } else if ((unsigned) (n->rip_metric) < rt->rt_metric ||
                            (rt->rt_timer > (EXPIRE_TIME/2) &&
                                                rt->rt_timer =
                                                    GARBAGE_TIME - EXPIRE_TIME;
                                } else if (rt->rt_metric < HOPCNT_INFINITY)
                                        rt->rt_timer = 0;
                        } else if ((unsigned) (n->rip_metric) < rt->rt_metric ||
                            (rt->rt_timer > (EXPIRE_TIME/2) &&
-                           rt->rt_metric == n->rip_metric)) {
+                           rt->rt_metric == n->rip_metric &&
+                           n->rip_metric < HOPCNT_INFINITY)) {
                                rtchange(rt, from, n->rip_metric);
                                rt->rt_timer = 0;
                        }
                                rtchange(rt, from, n->rip_metric);
                                rt->rt_timer = 0;
                        }
index 80007cb..666af15 100644 (file)
@@ -11,7 +11,7 @@ char copyright[] =
 #endif not lint
 
 #ifndef lint
 #endif not lint
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.10 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     5.11 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -29,9 +29,10 @@ static char sccsid[] = "@(#)main.c   5.10 (Berkeley) %G%";
 
 int    supplier = -1;          /* process should supply updates */
 int    gateway = 0;            /* 1 if we are a gateway to parts beyond */
 
 int    supplier = -1;          /* process should supply updates */
 int    gateway = 0;            /* 1 if we are a gateway to parts beyond */
+int    debug = 0;
 
 struct rip *msg = (struct rip *)packet;
 
 struct rip *msg = (struct rip *)packet;
-int    hup();
+int    hup(), rtdeleteall();
 
 main(argc, argv)
        int argc;
 
 main(argc, argv)
        int argc;
@@ -73,6 +74,7 @@ main(argc, argv)
                        continue;
                }
                if (strcmp(*argv, "-d") == 0) {
                        continue;
                }
                if (strcmp(*argv, "-d") == 0) {
+                       debug++;
                        setlogmask(LOG_DEBUG);
                        argv++, argc--;
                        continue;
                        setlogmask(LOG_DEBUG);
                        argv++, argc--;
                        continue;
@@ -86,8 +88,7 @@ main(argc, argv)
                        "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
                exit(1);
        }
                        "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
                exit(1);
        }
-#ifndef DEBUG
-       if (!tracepackets) {
+       if (tracepackets == 0 && debug == 0) {
                int t;
 
                if (fork())
                int t;
 
                if (fork())
@@ -104,7 +105,6 @@ main(argc, argv)
                        (void) close(t);
                }
        }
                        (void) close(t);
                }
        }
-#endif
        /*
         * Any extra argument is considered
         * a tracing log file.
        /*
         * Any extra argument is considered
         * a tracing log file.
@@ -135,6 +135,7 @@ main(argc, argv)
        signal(SIGALRM, timer);
        signal(SIGHUP, hup);
        signal(SIGTERM, hup);
        signal(SIGALRM, timer);
        signal(SIGHUP, hup);
        signal(SIGTERM, hup);
+       signal(SIGINT, rtdeleteall);
        timer();
 
        for (;;) {
        timer();
 
        for (;;) {
index 1db7a3a..0a963b2 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)output.c   5.6 (Berkeley) %G%";
+static char sccsid[] = "@(#)output.c   5.7 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -60,15 +60,15 @@ sendmsg(dst, flags, ifp)
 supply(dst, flags, ifp)
        struct sockaddr *dst;
        int flags;
 supply(dst, flags, ifp)
        struct sockaddr *dst;
        int flags;
-       struct interface *ifp;
+       register struct interface *ifp;
 {
        register struct rt_entry *rt;
 {
        register struct rt_entry *rt;
-       struct netinfo *n = msg->rip_nets;
+       register struct netinfo *n = msg->rip_nets;
        register struct rthash *rh;
        struct rthash *base = hosthash;
        int doinghost = 1, size;
        int (*output)() = afswitch[dst->sa_family].af_output;
        register struct rthash *rh;
        struct rthash *base = hosthash;
        int doinghost = 1, size;
        int (*output)() = afswitch[dst->sa_family].af_output;
-       int (*sendsubnet)() = afswitch[dst->sa_family].af_sendsubnet;
+       int (*sendroute)() = afswitch[dst->sa_family].af_sendroute;
        int npackets = 0;
 
        msg->rip_cmd = RIPCMD_RESPONSE;
        int npackets = 0;
 
        msg->rip_cmd = RIPCMD_RESPONSE;
@@ -77,8 +77,9 @@ again:
        for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
        for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
                /*
        for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++)
        for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
                /*
-                * Don't resend the information
-                * on the network from which it was received.
+                * Don't resend the information on the network
+                * from which it was received (unless sending
+                * in response to a query).
                 */
                if (ifp && rt->rt_ifp == ifp &&
                    (rt->rt_state & RTS_INTERFACE) == 0)
                 */
                if (ifp && rt->rt_ifp == ifp &&
                    (rt->rt_state & RTS_INTERFACE) == 0)
@@ -90,11 +91,9 @@ again:
                 * to those who are interested.
                 */
                if (doinghost == 0 && rt->rt_state & RTS_SUBNET) {
                 * to those who are interested.
                 */
                if (doinghost == 0 && rt->rt_state & RTS_SUBNET) {
-                       if (ifp && (ifp->int_flags & IFF_SUBNET) == 0)
-                               continue;
                        if (rt->rt_dst.sa_family != dst->sa_family)
                                continue;
                        if (rt->rt_dst.sa_family != dst->sa_family)
                                continue;
-                       if ((*sendsubnet)(rt, dst) == 0)
+                       if ((*sendroute)(rt, dst) == 0)
                                continue;
                }
                size = (char *)n - packet;
                                continue;
                }
                size = (char *)n - packet;
@@ -106,8 +105,7 @@ again:
                }
                n->rip_dst = rt->rt_dst;
                n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
                }
                n->rip_dst = rt->rt_dst;
                n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
-               n->rip_metric = htonl(min(rt->rt_metric + rt->rt_ifmetric,
-                   HOPCNT_INFINITY));
+               n->rip_metric = htonl(min(rt->rt_metric + 1, HOPCNT_INFINITY));
                n++;
        }
        if (doinghost) {
                n++;
        }
        if (doinghost) {
index fab77ef..61c1426 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  5.8 (Berkeley) %G%";
+static char sccsid[] = "@(#)startup.c  5.9 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -19,6 +19,8 @@ static char sccsid[] = "@(#)startup.c 5.8 (Berkeley) %G%";
 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,9 +60,6 @@ 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;
                if ((ifs.int_flags & IFF_UP) == 0 ||
                    ifr->ifr_addr.sa_family == AF_UNSPEC) {
                        lookforinterfaces = 1;
@@ -72,6 +71,13 @@ ifinit()
                /* 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_LOOPBACK) {
+                       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)");
@@ -120,8 +126,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 +141,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 +153,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 +162,12 @@ bad:
  * INTERNET SPECIFIC.
  */
 addrouteforif(ifp)
  * INTERNET SPECIFIC.
  */
 addrouteforif(ifp)
-       struct interface *ifp;
+       register struct interface *ifp;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
        int state, metric;
 {
        struct sockaddr_in net;
        struct sockaddr *dst;
        int state, metric;
-       struct rt_entry *rt;
+       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 +189,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, 0, state);
 }
 
 /*
 }
 
 /*
@@ -214,6 +264,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()
 {
index be91e00..9f22fed 100644 (file)
@@ -3,7 +3,7 @@
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  *
- *     @(#)table.h     5.3 (Berkeley) %G%
+ *     @(#)table.h     5.4 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
index ba5706e..6b2e18c 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)tables.c   5.9 (Berkeley) %G%";
+static char sccsid[] = "@(#)tables.c   5.10 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -106,7 +106,7 @@ rtadd(dst, gate, metric, state)
        struct afhash h;
        register struct rt_entry *rt;
        struct rthash *rh;
        struct afhash h;
        register struct rt_entry *rt;
        struct rthash *rh;
-       int af = dst->sa_family, flags, ifmetric;
+       int af = dst->sa_family, flags;
        u_int hash;
 
        if (af >= af_max)
        u_int hash;
 
        if (af >= af_max)
@@ -139,23 +139,9 @@ rtadd(dst, gate, metric, state)
        rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
        if (rt->rt_ifp == 0)
                rt->rt_ifp = if_ifwithnet(&rt->rt_router);
        rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
        if (rt->rt_ifp == 0)
                rt->rt_ifp = if_ifwithnet(&rt->rt_router);
-       if (rt->rt_ifp)
-               ifmetric = rt->rt_ifp->int_metric;
-       else
-               ifmetric = 0;
        if ((state & RTS_INTERFACE) == 0)
                rt->rt_flags |= RTF_GATEWAY;
        if ((state & RTS_INTERFACE) == 0)
                rt->rt_flags |= RTF_GATEWAY;
-       /*
-        * Set rt_ifmetric to the amount by which we
-        * increment the route when sending it to others.
-        */
-       if (state & RTS_INTERFACE) {
-               rt->rt_metric = 0;
-               rt->rt_ifmetric = metric + 1;
-       } else {
-               rt->rt_metric = metric;
-               rt->rt_ifmetric = ifmetric + 1;
-       }
+       rt->rt_metric = metric;
        insque(rt, rh);
        TRACE_ACTION(ADD, rt);
        /*
        insque(rt, rh);
        TRACE_ACTION(ADD, rt);
        /*
@@ -165,8 +151,7 @@ rtadd(dst, gate, metric, state)
         */
        if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
            ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
         */
        if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
            ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) {
-               if (errno != EEXIST &&
-                   dst->sa_family < af_max && gate->sa_family < af_max)
+               if (errno != EEXIST && gate->sa_family < af_max)
                        syslog(LOG_ERR,
                        "adding route to net/host %s through gateway %s: %m\n",
                           (*afswitch[dst->sa_family].af_format)(dst),
                        syslog(LOG_ERR,
                        "adding route to net/host %s through gateway %s: %m\n",
                           (*afswitch[dst->sa_family].af_format)(dst),
@@ -185,42 +170,56 @@ rtchange(rt, gate, metric)
        struct sockaddr *gate;
        short metric;
 {
        struct sockaddr *gate;
        short metric;
 {
-       int doioctl = 0, metricchanged = 0, delete = 0;
+       int add = 0, delete = 0, metricchanged = 0;
        struct rtentry oldroute;
 
        struct rtentry oldroute;
 
-       if (!equal(&rt->rt_router, gate) && (rt->rt_state & RTS_INTERNAL) == 0)
-               doioctl++;
-       if (metric != rt->rt_metric) {
-               metricchanged++;
-               if (metric == HOPCNT_INFINITY)
+       if ((rt->rt_state & RTS_INTERNAL) == 0) {
+               /*
+                * If changing to different router, we need to add
+                * new route and delete old one if in the kernel.
+                * If the router is the same, we need to delete
+                * the route if has become unreachable, or re-add
+                * it if it had been unreachable.
+                */
+               if (!equal(&rt->rt_router, gate)) {
+                       add++;
+                       if (rt->rt_metric != HOPCNT_INFINITY)
+                               delete++;
+               } else if (metric == HOPCNT_INFINITY)
                        delete++;
                        delete++;
+               else if (rt->rt_metric == HOPCNT_INFINITY)
+                       add++;
        }
        }
-       if (doioctl || metricchanged) {
+       if (metric != rt->rt_metric)
+               metricchanged++;
+       if (delete || metricchanged)
                TRACE_ACTION(CHANGE FROM, rt);
                TRACE_ACTION(CHANGE FROM, rt);
-               if ((rt->rt_state & RTS_INTERFACE) &&
-                   metric > rt->rt_ifp->int_metric) {
-                       rt->rt_state &= ~RTS_INTERFACE;
+       if ((rt->rt_state & RTS_INTERFACE) && delete) {
+               rt->rt_state &= ~RTS_INTERFACE;
+               if (add)
                        rt->rt_flags |= RTF_GATEWAY;
                        rt->rt_flags |= RTF_GATEWAY;
+               if (metric > rt->rt_metric && delete &&
+                   (rt->rt_state & RTS_INTERNAL) == 0)
                        syslog(LOG_ERR,
                                "changing route from interface %s (timed out)",
                                rt->rt_ifp->int_name);
                        syslog(LOG_ERR,
                                "changing route from interface %s (timed out)",
                                rt->rt_ifp->int_name);
-               }
-               if (doioctl || delete)
-                       oldroute = rt->rt_rt;
-               if (doioctl) {
-                       rt->rt_router = *gate;
-                       rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
-                       if (rt->rt_ifp == 0)
-                               rt->rt_ifp = if_ifwithnet(&rt->rt_router);
-               }
-               rt->rt_metric = metric;
-               rt->rt_state |= RTS_CHANGED;
-               TRACE_ACTION(CHANGE TO, rt);
        }
        }
-       if (doioctl && install)
+       if (delete)
+               oldroute = rt->rt_rt;
+       if (add) {
+               rt->rt_router = *gate;
+               rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router);
+               if (rt->rt_ifp == 0)
+                       rt->rt_ifp = if_ifwithnet(&rt->rt_router);
+       }
+       rt->rt_metric = metric;
+       rt->rt_state |= RTS_CHANGED;
+       if (add || metricchanged)
+               TRACE_ACTION(CHANGE TO, rt);
+       if (add && install)
                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
                        perror("SIOCADDRT");
                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
                        perror("SIOCADDRT");
-       if ((doioctl || delete) && install)
+       if (delete && install)
                if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                        perror("SIOCDELRT");
 }
                if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                        perror("SIOCDELRT");
 }
@@ -229,7 +228,7 @@ rtdelete(rt)
        struct rt_entry *rt;
 {
 
        struct rt_entry *rt;
 {
 
-       if (rt->rt_state & RTS_INTERFACE)
+       if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
                syslog(LOG_ERR, "deleting route to interface %s (timed out)",
                        rt->rt_ifp->int_name);
        TRACE_ACTION(DELETE, rt);
                syslog(LOG_ERR, "deleting route to interface %s (timed out)",
                        rt->rt_ifp->int_name);
        TRACE_ACTION(DELETE, rt);
@@ -240,6 +239,34 @@ rtdelete(rt)
        free((char *)rt);
 }
 
        free((char *)rt);
 }
 
+rtdeleteall(s)
+       int s;
+{
+       register struct rthash *rh;
+       register struct rt_entry *rt;
+       struct rthash *base = hosthash;
+       int doinghost = 1;
+
+again:
+       for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
+               rt = rh->rt_forw;
+               for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
+                       if (rt->rt_state & RTS_INTERFACE)
+                               continue;
+                       TRACE_ACTION(DELETE, rt);
+                       if ((rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL)) == 0 &&
+                           ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
+                               perror("SIOCDELRT");
+               }
+       }
+       if (doinghost) {
+               doinghost = 0;
+               base = nethash;
+               goto again;
+       }
+       hup(s);
+}
+
 /*
  * If we have an interface to the wide, wide world,
  * add an entry for an Internet default route (wildcard) to the internal
 /*
  * If we have an interface to the wide, wide world,
  * add an entry for an Internet default route (wildcard) to the internal