386BSD 0.1 development
[unix-history] / usr / src / sbin / routed / tables.c
index 62dda1c..a05e023 100644 (file)
@@ -2,16 +2,37 @@
  * Copyright (c) 1983, 1988 Regents of the University of California.
  * All rights reserved.
  *
  * 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.
+ * 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[] = "@(#)tables.c   5.13 (Berkeley) %G%";
+static char sccsid[] = "@(#)tables.c   5.17 (Berkeley) 6/1/90";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -26,6 +47,12 @@ static char sccsid[] = "@(#)tables.c 5.13 (Berkeley) %G%";
 #define        DEBUG   0
 #endif
 
 #define        DEBUG   0
 #endif
 
+#ifdef RTM_ADD
+#define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);}
+#else
+#define FIXLEN(s) { }
+#endif
+
 int    install = !DEBUG;               /* if 1 call kernel */
 
 /*
 int    install = !DEBUG;               /* if 1 call kernel */
 
 /*
@@ -133,6 +160,8 @@ rtadd(dst, gate, metric, state)
        /*
         * Subnet flag isn't visible to kernel, move to state.  XXX
         */
        /*
         * Subnet flag isn't visible to kernel, move to state.  XXX
         */
+       FIXLEN(dst);
+       FIXLEN(gate);
        if (flags & RTF_SUBNET) {
                state |= RTS_SUBNET;
                flags &= ~RTF_SUBNET;
        if (flags & RTF_SUBNET) {
                state |= RTS_SUBNET;
                flags &= ~RTF_SUBNET;
@@ -153,7 +182,7 @@ rtadd(dst, gate, metric, state)
        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_ifwithdstaddr(&rt->rt_router);
+       rt->rt_ifp = if_ifwithdstaddr(&rt->rt_dst);
        if (rt->rt_ifp == 0)
                rt->rt_ifp = if_ifwithnet(&rt->rt_router);
        if ((state & RTS_INTERFACE) == 0)
        if (rt->rt_ifp == 0)
                rt->rt_ifp = if_ifwithnet(&rt->rt_router);
        if ((state & RTS_INTERFACE) == 0)
@@ -187,9 +216,17 @@ rtchange(rt, gate, metric)
        struct sockaddr *gate;
        short metric;
 {
        struct sockaddr *gate;
        short metric;
 {
-       int add = 0, delete = 0;
+       int add = 0, delete = 0, newgateway = 0;
        struct rtentry oldroute;
 
        struct rtentry oldroute;
 
+       FIXLEN(gate);
+       FIXLEN(&(rt->rt_router));
+       FIXLEN(&(rt->rt_dst));
+       if (!equal(&rt->rt_router, gate)) {
+               newgateway++;
+               TRACE_ACTION("CHANGE FROM ", rt);
+       } else if (metric != rt->rt_metric)
+               TRACE_NEWMETRIC(rt, metric);
        if ((rt->rt_state & RTS_INTERNAL) == 0) {
                /*
                 * If changing to different router, we need to add
        if ((rt->rt_state & RTS_INTERNAL) == 0) {
                /*
                 * If changing to different router, we need to add
@@ -198,7 +235,7 @@ rtchange(rt, gate, metric)
                 * the route if has become unreachable, or re-add
                 * it if it had been unreachable.
                 */
                 * the route if has become unreachable, or re-add
                 * it if it had been unreachable.
                 */
-               if (!equal(&rt->rt_router, gate)) {
+               if (newgateway) {
                        add++;
                        if (rt->rt_metric != HOPCNT_INFINITY)
                                delete++;
                        add++;
                        if (rt->rt_metric != HOPCNT_INFINITY)
                                delete++;
@@ -207,10 +244,6 @@ rtchange(rt, gate, metric)
                else if (rt->rt_metric == HOPCNT_INFINITY)
                        add++;
        }
                else if (rt->rt_metric == HOPCNT_INFINITY)
                        add++;
        }
-       if (!equal(&rt->rt_router, gate)) {
-               TRACE_ACTION("CHANGE FROM ", rt);
-       } else if (metric != rt->rt_metric)
-               TRACE_NEWMETRIC(rt, metric);
        if (delete)
                oldroute = rt->rt_rt;
        if ((rt->rt_state & RTS_INTERFACE) && delete) {
        if (delete)
                oldroute = rt->rt_rt;
        if ((rt->rt_state & RTS_INTERFACE) && delete) {
@@ -229,14 +262,24 @@ rtchange(rt, gate, metric)
        }
        rt->rt_metric = metric;
        rt->rt_state |= RTS_CHANGED;
        }
        rt->rt_metric = metric;
        rt->rt_state |= RTS_CHANGED;
-       if (add)
+       if (newgateway)
                TRACE_ACTION("CHANGE TO   ", rt);
                TRACE_ACTION("CHANGE TO   ", rt);
+#ifndef RTM_ADD
        if (add && install)
                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
                        perror("SIOCADDRT");
        if (delete && install)
                if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                        perror("SIOCDELRT");
        if (add && install)
                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
                        perror("SIOCADDRT");
        if (delete && install)
                if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
                        perror("SIOCDELRT");
+#else
+       if (delete && install)
+               if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0)
+                       perror("SIOCDELRT");
+       if (add && install) {
+               if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
+                       perror("SIOCADDRT");
+       }
+#endif
 }
 
 rtdelete(rt)
 }
 
 rtdelete(rt)
@@ -244,6 +287,8 @@ rtdelete(rt)
 {
 
        TRACE_ACTION("DELETE", rt);
 {
 
        TRACE_ACTION("DELETE", rt);
+       FIXLEN(&(rt->rt_router));
+       FIXLEN(&(rt->rt_dst));
        if (rt->rt_metric < HOPCNT_INFINITY) {
            if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
                syslog(LOG_ERR,
        if (rt->rt_metric < HOPCNT_INFINITY) {
            if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE)
                syslog(LOG_ERR,
@@ -258,8 +303,8 @@ rtdelete(rt)
        free((char *)rt);
 }
 
        free((char *)rt);
 }
 
-rtdeleteall(s)
-       int s;
+rtdeleteall(sig)
+       int sig;
 {
        register struct rthash *rh;
        register struct rt_entry *rt;
 {
        register struct rthash *rh;
        register struct rt_entry *rt;
@@ -284,7 +329,7 @@ again:
                base = nethash;
                goto again;
        }
                base = nethash;
                goto again;
        }
-       exit(s);
+       exit(sig);
 }
 
 /*
 }
 
 /*
@@ -311,3 +356,28 @@ rtinit()
        for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
                rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
 }
        for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++)
                rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
 }
+
+
+/* ffrom /sys/i386/i386/machdep.c */
+/*
+ * insert an element into a queue 
+ */
+insque(element, head)
+       register struct rthash *element, *head;
+{
+       element->rt_forw = head->rt_forw;
+       head->rt_forw = (struct rt_entry *)element;
+       element->rt_back = (struct rt_entry *)head;
+       ((struct rthash *)(element->rt_forw))->rt_back=(struct rt_entry *)element;
+}
+
+/*
+ * remove an element from a queue
+ */
+remque(element)
+       register struct rthash *element;
+{
+       ((struct rthash *)(element->rt_forw))->rt_back = element->rt_back;
+       ((struct rthash *)(element->rt_back))->rt_forw = element->rt_forw;
+       element->rt_back = (struct rt_entry *)0;
+}