minor fixes
[unix-history] / usr / src / sbin / routed / tables.c
index a4c6b11..ba5706e 100644 (file)
@@ -1,6 +1,12 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)tables.c   4.10 (Berkeley) %G%";
-#endif
+static char sccsid[] = "@(#)tables.c   5.9 (Berkeley) %G%";
+#endif not lint
 
 /*
  * Routing Table Management Daemon
 
 /*
  * Routing Table Management Daemon
@@ -29,7 +35,7 @@ rtlookup(dst)
        struct afhash h;
        int doinghost = 1;
 
        struct afhash h;
        int doinghost = 1;
 
-       if (dst->sa_family >= AF_MAX)
+       if (dst->sa_family >= af_max)
                return (0);
        (*afswitch[dst->sa_family].af_hash)(dst, &h);
        hash = h.afh_hosthash;
                return (0);
        (*afswitch[dst->sa_family].af_hash)(dst, &h);
        hash = h.afh_hosthash;
@@ -64,7 +70,7 @@ rtfind(dst)
        int af = dst->sa_family;
        int doinghost = 1, (*match)();
 
        int af = dst->sa_family;
        int doinghost = 1, (*match)();
 
-       if (af >= AF_MAX)
+       if (af >= af_max)
                return (0);
        (*afswitch[af].af_hash)(dst, &h);
        hash = h.afh_hosthash;
                return (0);
        (*afswitch[af].af_hash)(dst, &h);
        hash = h.afh_hosthash;
@@ -100,13 +106,20 @@ 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;
+       int af = dst->sa_family, flags, ifmetric;
        u_int hash;
 
        u_int hash;
 
-       if (af >= AF_MAX)
+       if (af >= af_max)
                return;
        (*afswitch[af].af_hash)(dst, &h);
                return;
        (*afswitch[af].af_hash)(dst, &h);
-       flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
+       flags = (*afswitch[af].af_rtflags)(dst);
+       /*
+        * Subnet flag isn't visible to kernel, move to state.  XXX
+        */
+       if (flags & RTF_SUBNET) {
+               state |= RTS_SUBNET;
+               flags &= ~RTF_SUBNET;
+       }
        if (flags & RTF_HOST) {
                hash = h.afh_hosthash;
                rh = &hosthash[hash & ROUTEHASHMASK];
        if (flags & RTF_HOST) {
                hash = h.afh_hosthash;
                rh = &hosthash[hash & ROUTEHASHMASK];
@@ -120,13 +133,29 @@ rtadd(dst, gate, metric, state)
        rt->rt_hash = hash;
        rt->rt_dst = *dst;
        rt->rt_router = *gate;
        rt->rt_hash = hash;
        rt->rt_dst = *dst;
        rt->rt_router = *gate;
-       rt->rt_metric = metric;
        rt->rt_timer = 0;
        rt->rt_flags = RTF_UP | flags;
        rt->rt_state = state | RTS_CHANGED;
        rt->rt_timer = 0;
        rt->rt_flags = RTF_UP | flags;
        rt->rt_state = state | RTS_CHANGED;
-       rt->rt_ifp = if_ifwithnet(&rt->rt_router);
-       if (metric)
+       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;
                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;
+       }
        insque(rt, rh);
        TRACE_ACTION(ADD, rt);
        /*
        insque(rt, rh);
        TRACE_ACTION(ADD, rt);
        /*
@@ -134,7 +163,14 @@ rtadd(dst, gate, metric, state)
         * from this host, discard the entry.  This should only
         * occur because of an incorrect entry in /etc/gateways.
         */
         * from this host, discard the entry.  This should only
         * occur because of an incorrect entry in /etc/gateways.
         */
-       if (install && 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)
+                       syslog(LOG_ERR,
+                       "adding route to net/host %s through gateway %s: %m\n",
+                          (*afswitch[dst->sa_family].af_format)(dst),
+                          (*afswitch[gate->sa_family].af_format)(gate));
                perror("SIOCADDRT");
                if (errno == ENETUNREACH) {
                        TRACE_ACTION(DELETE, rt);
                perror("SIOCADDRT");
                if (errno == ENETUNREACH) {
                        TRACE_ACTION(DELETE, rt);
@@ -149,37 +185,44 @@ rtchange(rt, gate, metric)
        struct sockaddr *gate;
        short metric;
 {
        struct sockaddr *gate;
        short metric;
 {
-       int doioctl = 0, metricchanged = 0;
+       int doioctl = 0, metricchanged = 0, delete = 0;
        struct rtentry oldroute;
 
        struct rtentry oldroute;
 
-       if (!equal(&rt->rt_router, gate))
+       if (!equal(&rt->rt_router, gate) && (rt->rt_state & RTS_INTERNAL) == 0)
                doioctl++;
                doioctl++;
-       if (metric != rt->rt_metric)
+       if (metric != rt->rt_metric) {
                metricchanged++;
                metricchanged++;
+               if (metric == HOPCNT_INFINITY)
+                       delete++;
+       }
        if (doioctl || metricchanged) {
                TRACE_ACTION(CHANGE FROM, rt);
        if (doioctl || metricchanged) {
                TRACE_ACTION(CHANGE FROM, rt);
-               if (doioctl) {
-                       oldroute = rt->rt_rt;
-                       rt->rt_router = *gate;
-               }
-               rt->rt_metric = metric;
-               if ((rt->rt_state & RTS_INTERFACE) && metric) {
+               if ((rt->rt_state & RTS_INTERFACE) &&
+                   metric > rt->rt_ifp->int_metric) {
                        rt->rt_state &= ~RTS_INTERFACE;
                        rt->rt_state &= ~RTS_INTERFACE;
+                       rt->rt_flags |= RTF_GATEWAY;
                        syslog(LOG_ERR,
                        syslog(LOG_ERR,
-                               "deleting route to interface %s (timed out)",
+                               "changing route from interface %s (timed out)",
                                rt->rt_ifp->int_name);
                }
                                rt->rt_ifp->int_name);
                }
-               if (metric)
-                       rt->rt_state |= RTF_GATEWAY;
+               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);
        }
                rt->rt_state |= RTS_CHANGED;
                TRACE_ACTION(CHANGE TO, rt);
        }
-       if (doioctl && install) {
+       if (doioctl && 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 (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                        perror("SIOCDELRT");
                if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                        perror("SIOCDELRT");
-       }
 }
 
 rtdelete(rt)
 }
 
 rtdelete(rt)
@@ -190,7 +233,8 @@ rtdelete(rt)
                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);
-       if (install && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
+       if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 &&
+           ioctl(s, SIOCDELRT, (char *)&rt->rt_rt))
                perror("SIOCDELRT");
        remque(rt);
        free((char *)rt);
                perror("SIOCDELRT");
        remque(rt);
        free((char *)rt);
@@ -205,26 +249,10 @@ rtdelete(rt)
  */
 rtdefault()
 {
  */
 rtdefault()
 {
-       struct afhash h;
-       register struct rt_entry *rt;
-       struct rthash *rh;
        extern struct sockaddr inet_default;
 
        extern struct sockaddr inet_default;
 
-       rt = (struct rt_entry *)malloc(sizeof (*rt));
-       if (rt == 0)
-               return;
-       rt->rt_dst = inet_default;
-       rt->rt_router = rt->rt_dst;
-       (*afswitch[AF_INET].af_hash)(&rt->rt_dst, &h);
-       rh = &nethash[h.afh_nethash & ROUTEHASHMASK];
-       rt->rt_hash = h.afh_nethash;
-       rt->rt_metric = 0;
-       rt->rt_timer = 0;
-       rt->rt_flags = RTF_UP | RTF_GATEWAY;
-       rt->rt_state = RTS_CHANGED | RTS_PASSIVE;
-       rt->rt_ifp = 0;
-       insque(rt, rh);
-       TRACE_ACTION(ADD, rt);
+       rtadd(&inet_default, &inet_default, 0,
+               RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL);
 }
 
 rtinit()
 }
 
 rtinit()