working with dynamic updates, auto-loading timer; tracing additions and fixes
authorMike Karels <karels@ucbvax.Berkeley.EDU>
Sun, 19 Feb 1989 03:28:43 +0000 (19:28 -0800)
committerMike Karels <karels@ucbvax.Berkeley.EDU>
Sun, 19 Feb 1989 03:28:43 +0000 (19:28 -0800)
SCCS-vsn: sbin/routed/trace.c 5.8
SCCS-vsn: sbin/routed/trace.h 5.6
SCCS-vsn: sbin/routed/main.c 5.16
SCCS-vsn: sbin/routed/timer.c 5.8
SCCS-vsn: sbin/routed/output.c 5.12
SCCS-vsn: sbin/routed/tables.c 5.15
SCCS-vsn: sbin/routed/input.c 5.19
SCCS-vsn: sbin/routed/defs.h 5.7
SCCS-vsn: sbin/routed/startup.c 5.15

usr/src/sbin/routed/defs.h
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/tables.c
usr/src/sbin/routed/timer.c
usr/src/sbin/routed/trace.c
usr/src/sbin/routed/trace.h

index 4938f34..f7f8b46 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)defs.h      5.6 (Berkeley) %G%
+ *     @(#)defs.h      5.7 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -23,8 +23,9 @@
  * protocol specs with mods relevant to more
  * general addressing scheme.
  */
  * protocol specs with mods relevant to more
  * general addressing scheme.
  */
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/socket.h>
 #include <sys/socket.h>
+#include <sys/time.h>
 
 #include <net/route.h>
 #include <netinet/in.h>
 
 #include <net/route.h>
 #include <netinet/in.h>
@@ -47,7 +48,6 @@
 
 #define equal(a1, a2) \
        (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0)
 
 #define equal(a1, a2) \
        (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0)
-#define        min(a,b)        ((a)>(b)?(b):(a))
 
 struct sockaddr_in addr;       /* address of daemon's socket */
 
 
 struct sockaddr_in addr;       /* address of daemon's socket */
 
@@ -58,7 +58,11 @@ int  install;                /* if 1 call kernel */
 int    lookforinterfaces;      /* if 1 probe kernel for new up interfaces */
 int    performnlist;           /* if 1 check if /vmunix has changed */
 int    externalinterfaces;     /* # of remote and local interfaces */
 int    lookforinterfaces;      /* if 1 probe kernel for new up interfaces */
 int    performnlist;           /* if 1 check if /vmunix has changed */
 int    externalinterfaces;     /* # of remote and local interfaces */
-int    timeval;                /* local idea of time */
+struct timeval now;            /* current idea of time */
+struct timeval lastbcast;      /* last time all/changes broadcast */
+struct timeval lastfullupdate; /* last time full table broadcast */
+struct timeval nextbcast;      /* time to wait before changes broadcast */
+int    needupdate;             /* true if we need update at nextbcast */
 
 char   packet[MAXPACKETSIZE+1];
 struct rip *msg;
 
 char   packet[MAXPACKETSIZE+1];
 struct rip *msg;
index 013fd15..16d94c7 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)input.c    5.18 (Berkeley) %G%";
+static char sccsid[] = "@(#)input.c    5.19 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -36,7 +36,7 @@ rip_input(from, size)
        register struct netinfo *n;
        register struct interface *ifp;
        struct interface *if_ifwithdstaddr();
        register struct netinfo *n;
        register struct interface *ifp;
        struct interface *if_ifwithdstaddr();
-       int newsize;
+       int count, changes = 0;
        register struct afswitch *afp;
        static struct sockaddr badfrom, badfrom2;
 
        register struct afswitch *afp;
        static struct sockaddr badfrom, badfrom2;
 
@@ -49,22 +49,30 @@ rip_input(from, size)
                    from->sa_family, msg->rip_cmd);
                return;
        }
                    from->sa_family, msg->rip_cmd);
                return;
        }
+       if (msg->rip_vers == 0) {
+               syslog(LOG_ERR,
+                   "RIP version 0 packet received from %s! (cmd %d)",
+                   (*afswitch[from->sa_family].af_format)(from), msg->rip_cmd);
+               return;
+       }
        switch (msg->rip_cmd) {
 
        case RIPCMD_REQUEST:
        switch (msg->rip_cmd) {
 
        case RIPCMD_REQUEST:
-               newsize = 0;
-               size -= 4 * sizeof (char);
                n = msg->rip_nets;
                n = msg->rip_nets;
-               while (size > 0) {
-                       if (size < sizeof (struct netinfo))
+               count = size - ((char *)n - (char *)msg);
+               if (count < sizeof (struct netinfo))
+                       return;
+               for (; count > 0; n++) {
+                       if (count < sizeof (struct netinfo))
                                break;
                                break;
-                       size -= sizeof (struct netinfo);
+                       count -= sizeof (struct netinfo);
 
 
-                       if (msg->rip_vers > 0) {
+#if BSD < 198810
+                       if (sizeof(n->rip_dst.sa_family) > 1)/* XXX */
                                n->rip_dst.sa_family =
                                        ntohs(n->rip_dst.sa_family);
                                n->rip_dst.sa_family =
                                        ntohs(n->rip_dst.sa_family);
-                               n->rip_metric = ntohl(n->rip_metric);
-                       }
+#endif
+                       n->rip_metric = ntohl(n->rip_metric);
                        /* 
                         * A single entry with sa_family == AF_UNSPEC and
                         * metric ``infinity'' means ``all routes''.
                        /* 
                         * A single entry with sa_family == AF_UNSPEC and
                         * metric ``infinity'' means ``all routes''.
@@ -73,9 +81,9 @@ rip_input(from, size)
                         * (eg, query).
                         */
                        if (n->rip_dst.sa_family == AF_UNSPEC &&
                         * (eg, query).
                         */
                        if (n->rip_dst.sa_family == AF_UNSPEC &&
-                           n->rip_metric == HOPCNT_INFINITY && size == 0) {
+                           n->rip_metric == HOPCNT_INFINITY && count == 0) {
                                if (supplier || (*afp->af_portmatch)(from) == 0)
                                if (supplier || (*afp->af_portmatch)(from) == 0)
-                                       supply(from, 0, 0);
+                                       supply(from, 0, 0, 0);
                                return;
                        }
                        if (n->rip_dst.sa_family < af_max &&
                                return;
                        }
                        if (n->rip_dst.sa_family < af_max &&
@@ -85,18 +93,14 @@ rip_input(from, size)
                                rt = 0;
                        n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
                                min(rt->rt_metric + 1, HOPCNT_INFINITY);
                                rt = 0;
                        n->rip_metric = rt == 0 ? HOPCNT_INFINITY :
                                min(rt->rt_metric + 1, HOPCNT_INFINITY);
-                       if (msg->rip_vers > 0) {
-                               n->rip_dst.sa_family =
-                                       htons(n->rip_dst.sa_family);
-                               n->rip_metric = htonl(n->rip_metric);
-                       }
-                       n++, newsize += sizeof (struct netinfo);
-               }
-               if (newsize > 0) {
-                       msg->rip_cmd = RIPCMD_RESPONSE;
-                       newsize += sizeof (int);
-                       (*afp->af_output)(s, 0, from, newsize);
+#if BSD < 198810
+                       if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
+                           n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
+#endif
+                       n->rip_metric = htonl(n->rip_metric);
                }
                }
+               msg->rip_cmd = RIPCMD_RESPONSE;
+               (*afp->af_output)(s, 0, from, size);
                return;
 
        case RIPCMD_TRACEON:
                return;
 
        case RIPCMD_TRACEON:
@@ -174,11 +178,12 @@ rip_input(from, size)
                for (; size > 0; size -= sizeof (struct netinfo), n++) {
                        if (size < sizeof (struct netinfo))
                                break;
                for (; size > 0; size -= sizeof (struct netinfo), n++) {
                        if (size < sizeof (struct netinfo))
                                break;
-                       if (msg->rip_vers > 0) {
+#if BSD < 198810
+                       if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
                                n->rip_dst.sa_family =
                                        ntohs(n->rip_dst.sa_family);
                                n->rip_dst.sa_family =
                                        ntohs(n->rip_dst.sa_family);
-                               n->rip_metric = ntohl(n->rip_metric);
-                       }
+#endif
+                       n->rip_metric = ntohl(n->rip_metric);
                        if (n->rip_dst.sa_family >= af_max ||
                            (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
                            (int (*)())0) {
                        if (n->rip_dst.sa_family >= af_max ||
                            (afp = &afswitch[n->rip_dst.sa_family])->af_hash ==
                            (int (*)())0) {
@@ -237,6 +242,7 @@ rip_input(from, size)
                                    if (rt && equal(from, &rt->rt_router))
                                            continue;
                                    rtadd(&n->rip_dst, from, n->rip_metric, 0);
                                    if (rt && equal(from, &rt->rt_router))
                                            continue;
                                    rtadd(&n->rip_dst, from, n->rip_metric, 0);
+                                   changes++;
                                }
                                continue;
                        }
                                }
                                continue;
                        }
@@ -249,6 +255,7 @@ 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);
+                                       changes++;
                                        rt->rt_timer = 0;
                                        if (rt->rt_metric >= HOPCNT_INFINITY)
                                                rt->rt_timer =
                                        rt->rt_timer = 0;
                                        if (rt->rt_metric >= HOPCNT_INFINITY)
                                                rt->rt_timer =
@@ -260,9 +267,66 @@ rip_input(from, size)
                            rt->rt_timer > (EXPIRE_TIME/2) &&
                            (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
                                rtchange(rt, from, n->rip_metric);
                            rt->rt_timer > (EXPIRE_TIME/2) &&
                            (unsigned) n->rip_metric < HOPCNT_INFINITY)) {
                                rtchange(rt, from, n->rip_metric);
+                               changes++;
                                rt->rt_timer = 0;
                        }
                }
                                rt->rt_timer = 0;
                        }
                }
-               return;
+               break;
+       }
+
+       /*
+        * If changes have occurred, and if we have not sent a broadcast
+        * recently, send a dynamic update.  This update is sent only
+        * on interfaces other than the one on which we received notice
+        * of the change.  If we are within MIN_WAITTIME of a full update,
+        * don't bother sending; if we just sent a dynamic update
+        * and set a timer (nextbcast), delay until that time.
+        * If we just sent a full update, delay the dynamic update.
+        * Set a timer for a randomized value to suppress additional
+        * dynamic updates until it expires; if we delayed sending
+        * the current changes, set needupdate.
+        */
+       if (changes && supplier &&
+          now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) {
+               u_long delay;
+               extern long random();
+
+               if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME &&
+                   timercmp(&nextbcast, &now, <)) {
+                       if (traceactions)
+                               fprintf(ftrace, "send dynamic update\n");
+                       toall(supply, RTS_CHANGED, ifp);
+                       lastbcast = now;
+                       needupdate = 0;
+                       nextbcast.tv_sec = 0;
+               } else {
+                       needupdate++;
+                       if (traceactions)
+                               fprintf(ftrace, "delay dynamic update\n");
+               }
+#define RANDOMDELAY()  (MIN_WAITTIME * 1000000 + \
+               (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000))
+
+               if (nextbcast.tv_sec == 0) {
+                       delay = RANDOMDELAY();
+                       if (traceactions)
+                               fprintf(ftrace,
+                                   "inhibit dynamic update for %d usec\n",
+                                   delay);
+                       nextbcast.tv_sec = delay / 1000000;
+                       nextbcast.tv_usec = delay % 1000000;
+                       timevaladd(&nextbcast, &now);
+                       /*
+                        * If the next possibly dynamic update
+                        * is within MIN_WAITTIME of the next full update,
+                        * force the delay past the full update,
+                        * or we might send a dynamic update just before
+                        * the full update.
+                        */
+                       if (nextbcast.tv_sec > lastfullupdate.tv_sec +
+                           SUPPLY_INTERVAL - MIN_WAITTIME)
+                               nextbcast.tv_sec = lastfullupdate.tv_sec +
+                                   SUPPLY_INTERVAL + 1;
+               }
        }
 }
        }
 }
index 98e7934..a69b887 100644 (file)
@@ -22,7 +22,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)main.c     5.15 (Berkeley) %G%";
+static char sccsid[] = "@(#)main.c     5.16 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -30,7 +30,7 @@ static char sccsid[] = "@(#)main.c    5.15 (Berkeley) %G%";
  */
 #include "defs.h"
 #include <sys/ioctl.h>
  */
 #include "defs.h"
 #include <sys/ioctl.h>
-#include <sys/time.h>
+#include <sys/file.h>
 
 #include <net/if.h>
 
 
 #include <net/if.h>
 
@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)main.c    5.15 (Berkeley) %G%";
 int    supplier = -1;          /* process should supply updates */
 int    gateway = 0;            /* 1 if we are a gateway to parts beyond */
 int    debug = 0;
 int    supplier = -1;          /* process should supply updates */
 int    gateway = 0;            /* 1 if we are a gateway to parts beyond */
 int    debug = 0;
+int    bufspace = 127*1024;    /* max. input buffer size to request */
 
 struct rip *msg = (struct rip *)packet;
 int    hup(), rtdeleteall(), sigtrace();
 
 struct rip *msg = (struct rip *)packet;
 int    hup(), rtdeleteall(), sigtrace();
@@ -49,8 +50,11 @@ main(argc, argv)
        int argc;
        char *argv[];
 {
        int argc;
        char *argv[];
 {
-       int cc;
+       int n, cc, nfd, omask, tflags = 0;
        struct sockaddr from;
        struct sockaddr from;
+       struct timeval *tvp, waittime;
+       struct itimerval itval;
+       fd_set ibits;
        u_char retry;
        
        argv0 = argv;
        u_char retry;
        
        argv0 = argv;
@@ -80,12 +84,7 @@ main(argc, argv)
                        continue;
                }
                if (strcmp(*argv, "-t") == 0) {
                        continue;
                }
                if (strcmp(*argv, "-t") == 0) {
-                       if (tracehistory == 0)
-                               tracehistory++;
-                       else {
-                               tracehistory = 0;
-                               tracepackets++;
-                       }
+                       tflags++;
                        setlogmask(LOG_DEBUG);
                        argv++, argc--;
                        continue;
                        setlogmask(LOG_DEBUG);
                        argv++, argc--;
                        continue;
@@ -105,7 +104,8 @@ main(argc, argv)
                        "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
                exit(1);
        }
                        "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n");
                exit(1);
        }
-       if (tracepackets == 0 && debug == 0) {
+
+       if (debug == 0) {
                int t;
 
                if (fork())
                int t;
 
                if (fork())
@@ -128,6 +128,10 @@ main(argc, argv)
         */
        if (argc > 0)
                traceon(*argv);
         */
        if (argc > 0)
                traceon(*argv);
+       while (tflags-- > 0)
+               bumploglevel();
+
+       (void) gettimeofday(&now, (struct timezone *)NULL);
        /*
         * Collect an initial view of the world by
         * checking the interface configuration and the gateway kludge
        /*
         * Collect an initial view of the world by
         * checking the interface configuration and the gateway kludge
@@ -144,10 +148,11 @@ main(argc, argv)
                supplier = 0;
        msg->rip_cmd = RIPCMD_REQUEST;
        msg->rip_vers = RIPVERSION;
                supplier = 0;
        msg->rip_cmd = RIPCMD_REQUEST;
        msg->rip_vers = RIPVERSION;
-       msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
-       msg->rip_nets[0].rip_metric = HOPCNT_INFINITY;
-       msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC);
-       msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY);
+       if (sizeof(msg->rip_nets[0].rip_dst.sa_family) > 1)     /* XXX */
+               msg->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC);
+       else
+               msg->rip_nets[0].rip_dst.sa_family = AF_UNSPEC;
+       msg->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY);
        toall(sendmsg);
        signal(SIGALRM, timer);
        signal(SIGHUP, hup);
        toall(sendmsg);
        signal(SIGALRM, timer);
        signal(SIGHUP, hup);
@@ -155,74 +160,172 @@ main(argc, argv)
        signal(SIGINT, rtdeleteall);
        signal(SIGUSR1, sigtrace);
        signal(SIGUSR2, sigtrace);
        signal(SIGINT, rtdeleteall);
        signal(SIGUSR1, sigtrace);
        signal(SIGUSR2, sigtrace);
-       timer();
+       itval.it_interval.tv_sec = TIMER_RATE;
+       itval.it_value.tv_sec = TIMER_RATE;
+       itval.it_interval.tv_usec = 0;
+       itval.it_value.tv_usec = 0;
+       srandom(getpid());
+       if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0)
+               syslog(LOG_ERR, "setitimer: %m\n");
 
 
+       FD_ZERO(&ibits);
+       nfd = s + 1;                    /* 1 + max(fd's) */
        for (;;) {
        for (;;) {
-               int ibits;
-               register int n;
-
-               ibits = 1 << s;
-               n = select(20, &ibits, 0, 0, 0);
-               if (n < 0)
+               FD_SET(s, &ibits);
+               /*
+                * If we need a dynamic update that was held off,
+                * needupdate will be set, and nextbcast is the time
+                * by which we want select to return.  Compute time
+                * until dynamic update should be sent, and select only
+                * until then.  If we have already passed nextbcast,
+                * just poll.
+                */
+               if (needupdate) {
+                       waittime = nextbcast;
+                       timevalsub(&waittime, &now);
+                       if (waittime.tv_sec < 0) {
+                               waittime.tv_sec = 0;
+                               waittime.tv_usec = 0;
+                       }
+                       if (traceactions)
+                               fprintf(ftrace,
+                                "select until dynamic update %d/%d sec/usec\n",
+                                   waittime.tv_sec, waittime.tv_usec);
+                       tvp = &waittime;
+               } else
+                       tvp = (struct timeval *)NULL;
+               n = select(nfd, &ibits, 0, 0, tvp);
+               if (n <= 0) {
+                       /*
+                        * Need delayed dynamic update if select returned
+                        * nothing and we timed out.  Otherwise, ignore
+                        * errors (e.g. EINTR).
+                        */
+                       if (n < 0) {
+                               if (errno == EINTR)
+                                       continue;
+                               syslog(LOG_ERR, "select: %m");
+                       }
+                       omask = sigblock(sigmask(SIGALRM));
+                       if (n == 0 && needupdate) {
+                               if (traceactions)
+                                       fprintf(ftrace,
+                                           "send delayed dynamic update\n");
+                               (void) gettimeofday(&now,
+                                           (struct timezone *)NULL);
+                               toall(supply, RTS_CHANGED,
+                                   (struct interface *)NULL);
+                               lastbcast = now;
+                               needupdate = 0;
+                               nextbcast.tv_sec = 0;
+                       }
+                       sigsetmask(omask);
                        continue;
                        continue;
-               if (ibits & (1 << s))
+               }
+               (void) gettimeofday(&now, (struct timezone *)NULL);
+#ifdef doesntwork
+/*
+printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n",
+       s,
+       ibits.fds_bits[0],
+       (s)/(sizeof(fd_mask) * 8),
+       ((s) % (sizeof(fd_mask) * 8)),
+       (1 << ((s) % (sizeof(fd_mask) * 8))),
+       ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))),
+       &ibits
+       );
+*/
+               if (FD_ISSET(s, &ibits))
+#else
+               if (ibits.fds_bits[s/32] & (1 << s))
+#endif
                        process(s);
                /* handle ICMP redirects */
        }
 }
 
                        process(s);
                /* handle ICMP redirects */
        }
 }
 
+timevaladd(t1, t2)
+       struct timeval *t1, *t2;
+{
+
+       t1->tv_sec += t2->tv_sec;
+       if ((t1->tv_usec += t2->tv_usec) > 1000000) {
+               t1->tv_sec++;
+               t1->tv_usec -= 1000000;
+       }
+}
+
+timevalsub(t1, t2)
+       struct timeval *t1, *t2;
+{
+
+       t1->tv_sec -= t2->tv_sec;
+       if ((t1->tv_usec -= t2->tv_usec) < 0) {
+               t1->tv_sec--;
+               t1->tv_usec += 1000000;
+       }
+}
+
 process(fd)
        int fd;
 {
        struct sockaddr from;
 process(fd)
        int fd;
 {
        struct sockaddr from;
-       int fromlen = sizeof (from), cc, omask;
-       time_t now;
-
-       cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
-       if (cc <= 0) {
-               if (cc < 0 && errno != EINTR)
-                       perror("recvfrom");
-               return;
-       }
-       if (fromlen != sizeof (struct sockaddr_in))
-               return;
-       if (traceactions && !tracepackets) {
-               (void) time(&now);
-               curtime = ctime(&now);
+       int fromlen, cc, omask;
+
+       for (;;) {
+               fromlen = sizeof (from);
+               cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
+               if (cc <= 0) {
+                       if (cc < 0 && errno != EWOULDBLOCK)
+                               perror("recvfrom");
+                       break;
+               }
+               if (fromlen != sizeof (struct sockaddr_in))
+                       break;
+               omask = sigblock(sigmask(SIGALRM));
+               rip_input(&from, cc);
+               sigsetmask(omask);
        }
        }
-       omask = sigblock(sigmask(SIGALRM));
-       rip_input(&from, cc);
-       sigsetmask(omask);
 }
 
 getsocket(domain, type, sin)
        int domain, type;
        struct sockaddr_in *sin;
 {
 }
 
 getsocket(domain, type, sin)
        int domain, type;
        struct sockaddr_in *sin;
 {
-       int s, on = 1;
+       int sock, on = 1;
 
 
-       if ((s = socket(domain, type, 0)) < 0) {
+       if ((sock = socket(domain, type, 0)) < 0) {
                perror("socket");
                syslog(LOG_ERR, "socket: %m");
                return (-1);
        }
 #ifdef SO_BROADCAST
                perror("socket");
                syslog(LOG_ERR, "socket: %m");
                return (-1);
        }
 #ifdef SO_BROADCAST
-       if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
+       if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
                syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
                syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
-               close(s);
+               close(sock);
                return (-1);
        }
 #endif
 #ifdef SO_RCVBUF
                return (-1);
        }
 #endif
 #ifdef SO_RCVBUF
-       on = 48*1024;
-       if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &on, sizeof (on)) < 0)
-               syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+       for (on = bufspace; ; on -= 1024) {
+               if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
+                   &on, sizeof (on)) == 0)
+                       break;
+               if (on <= 8*1024) {
+                       syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m");
+                       break;
+               }
+       }
+       if (traceactions)
+               fprintf(ftrace, "recv buf %d\n", on);
 #endif
 #endif
-       if (bind(s, sin, sizeof (*sin), 0) < 0) {
+       if (bind(sock, sin, sizeof (*sin), 0) < 0) {
                perror("bind");
                syslog(LOG_ERR, "bind: %m");
                perror("bind");
                syslog(LOG_ERR, "bind: %m");
-               close(s);
+               close(sock);
                return (-1);
        }
                return (-1);
        }
-       return (s);
+       if (fcntl(sock, F_SETFL, FNDELAY) == -1)
+               syslog(LOG_ERR, "fcntl FNDELAY: %m\n");
+       return (sock);
 }
 }
index d51b611..a42b243 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)output.c   5.11 (Berkeley) %G%";
+static char sccsid[] = "@(#)output.c   5.12 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -30,8 +30,10 @@ static char sccsid[] = "@(#)output.c 5.11 (Berkeley) %G%";
  * use of broadcasting use it, otherwise address
  * the output to the known router.
  */
  * use of broadcasting use it, otherwise address
  * the output to the known router.
  */
-toall(f)
+toall(f, rtstate, skipif)
        int (*f)();
        int (*f)();
+       int rtstate;
+       struct interface *skipif;
 {
        register struct interface *ifp;
        register struct sockaddr *dst;
 {
        register struct interface *ifp;
        register struct sockaddr *dst;
@@ -39,13 +41,13 @@ toall(f)
        extern struct interface *ifnet;
 
        for (ifp = ifnet; ifp; ifp = ifp->int_next) {
        extern struct interface *ifnet;
 
        for (ifp = ifnet; ifp; ifp = ifp->int_next) {
-               if (ifp->int_flags & IFF_PASSIVE)
+               if (ifp->int_flags & IFF_PASSIVE || ifp == skipif)
                        continue;
                dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
                      ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
                      &ifp->int_addr;
                flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
                        continue;
                dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
                      ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
                      &ifp->int_addr;
                flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
-               (*f)(dst, flags, ifp);
+               (*f)(dst, flags, ifp, rtstate);
        }
 }
 
        }
 }
 
@@ -53,10 +55,11 @@ toall(f)
  * Output a preformed packet.
  */
 /*ARGSUSED*/
  * Output a preformed packet.
  */
 /*ARGSUSED*/
-sendmsg(dst, flags, ifp)
+sendmsg(dst, flags, ifp, rtstate)
        struct sockaddr *dst;
        int flags;
        struct interface *ifp;
        struct sockaddr *dst;
        int flags;
        struct interface *ifp;
+       int rtstate;
 {
 
        (*afswitch[dst->sa_family].af_output)(s, flags,
 {
 
        (*afswitch[dst->sa_family].af_output)(s, flags,
@@ -68,10 +71,11 @@ sendmsg(dst, flags, ifp)
  * Supply dst with the contents of the routing tables.
  * If this won't fit in one packet, chop it up into several.
  */
  * Supply dst with the contents of the routing tables.
  * If this won't fit in one packet, chop it up into several.
  */
-supply(dst, flags, ifp)
+supply(dst, flags, ifp, rtstate)
        struct sockaddr *dst;
        int flags;
        register struct interface *ifp;
        struct sockaddr *dst;
        int flags;
        register struct interface *ifp;
+       int rtstate;
 {
        register struct rt_entry *rt;
        register struct netinfo *n = msg->rip_nets;
 {
        register struct rt_entry *rt;
        register struct netinfo *n = msg->rip_nets;
@@ -98,6 +102,12 @@ again:
                        continue;
                if (rt->rt_state & RTS_EXTERNAL)
                        continue;
                        continue;
                if (rt->rt_state & RTS_EXTERNAL)
                        continue;
+               /*
+                * For dynamic updates, limit update to routes
+                * with the specified state.
+                */
+               if (rtstate && (rt->rt_state & rtstate) == 0)
+                       continue;
                /*
                 * Limit the spread of subnet information
                 * to those who are interested.
                /*
                 * Limit the spread of subnet information
                 * to those who are interested.
@@ -110,20 +120,23 @@ again:
                }
                size = (char *)n - packet;
                if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
                }
                size = (char *)n - packet;
                if (size > MAXPACKETSIZE - sizeof (struct netinfo)) {
-                       (*output)(s, flags, dst, size);
                        TRACE_OUTPUT(ifp, dst, size);
                        TRACE_OUTPUT(ifp, dst, size);
+                       (*output)(s, flags, dst, size);
                        /*
                         * If only sending to ourselves,
                         * one packet is enough to monitor interface.
                         */
                        /*
                         * If only sending to ourselves,
                         * one packet is enough to monitor interface.
                         */
-                       if ((ifp->int_flags &
+                       if (ifp && (ifp->int_flags &
                           (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0)
                                return;
                        n = msg->rip_nets;
                        npackets++;
                }
                n->rip_dst = rt->rt_dst;
                           (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0)
                                return;
                        n = msg->rip_nets;
                        npackets++;
                }
                n->rip_dst = rt->rt_dst;
+#if BSD < 198810
+               if (sizeof(n->rip_dst.sa_family) > 1)   /* XXX */
                n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
                n->rip_dst.sa_family = htons(n->rip_dst.sa_family);
+#endif
                n->rip_metric = htonl(rt->rt_metric);
                n++;
        }
                n->rip_metric = htonl(rt->rt_metric);
                n++;
        }
@@ -132,9 +145,9 @@ again:
                base = nethash;
                goto again;
        }
                base = nethash;
                goto again;
        }
-       if (n != msg->rip_nets || npackets == 0) {
+       if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) {
                size = (char *)n - packet;
                size = (char *)n - packet;
-               (*output)(s, flags, dst, size);
                TRACE_OUTPUT(ifp, dst, size);
                TRACE_OUTPUT(ifp, dst, size);
+               (*output)(s, flags, dst, size);
        }
 }
        }
 }
index d12fc3f..788bbee 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)startup.c  5.14 (Berkeley) %G%";
+static char sccsid[] = "@(#)startup.c  5.15 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -28,6 +28,7 @@ static char sccsid[] = "@(#)startup.c 5.14 (Berkeley) %G%";
 #include <syslog.h>
 
 struct interface *ifnet;
 #include <syslog.h>
 
 struct interface *ifnet;
+struct interface **ifnext = &ifnet;
 int    lookforinterfaces = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 int    foundloopback;                  /* valid flag for loopaddr */
 int    lookforinterfaces = 1;
 int    externalinterfaces = 0;         /* # of remote and local interfaces */
 int    foundloopback;                  /* valid flag for loopaddr */
@@ -51,14 +52,15 @@ ifinit()
 
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                syslog(LOG_ERR, "socket: %m");
 
        if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                syslog(LOG_ERR, "socket: %m");
-               exit(1);
+               close(s);
+                return;
        }
         ifc.ifc_len = sizeof (buf);
         ifc.ifc_buf = buf;
         if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
                 syslog(LOG_ERR, "ioctl (get interface configuration)");
                close(s);
        }
         ifc.ifc_len = sizeof (buf);
         ifc.ifc_buf = buf;
         if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
                 syslog(LOG_ERR, "ioctl (get interface configuration)");
                close(s);
-                return (0);
+                return;
         }
         ifr = ifc.ifc_req;
        lookforinterfaces = 0;
         }
         ifr = ifc.ifc_req;
        lookforinterfaces = 0;
@@ -67,7 +69,8 @@ ifinit()
                ifs.int_addr = ifr->ifr_addr;
                ifreq = *ifr;
                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
                ifs.int_addr = ifr->ifr_addr;
                ifreq = *ifr;
                 if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
-                        syslog(LOG_ERR, "ioctl (get interface flags)");
+                        syslog(LOG_ERR, "%s: ioctl (get interface flags)",
+                           ifr->ifr_name);
                         continue;
                 }
                ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
                         continue;
                 }
                ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE;
@@ -76,6 +79,21 @@ ifinit()
                        lookforinterfaces = 1;
                        continue;
                }
                        lookforinterfaces = 1;
                        continue;
                }
+               /* argh, this'll have to change sometime */
+               if (ifs.int_addr.sa_family != AF_INET)
+                       continue;
+                if (ifs.int_flags & IFF_POINTOPOINT) {
+                        if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) {
+                                syslog(LOG_ERR, "%s: ioctl (get dstaddr)",
+                                   ifr->ifr_name);
+                                continue;
+                       }
+                       if (ifr->ifr_addr.sa_family == AF_UNSPEC) {
+                               lookforinterfaces = 1;
+                               continue;
+                       }
+                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
+               }
                /*
                 * already known to us?
                 * This allows multiple point-to-point links
                /*
                 * already known to us?
                 * This allows multiple point-to-point links
@@ -88,9 +106,6 @@ ifinit()
                                continue;
                } else if (if_ifwithaddr(&ifs.int_addr))
                        continue;
                                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;
                if (ifs.int_flags & IFF_LOOPBACK) {
                        ifs.int_flags |= IFF_PASSIVE;
                        foundloopback = 1;
                if (ifs.int_flags & IFF_LOOPBACK) {
                        ifs.int_flags |= IFF_PASSIVE;
                        foundloopback = 1;
@@ -99,24 +114,28 @@ ifinit()
                            if (ifp->int_flags & IFF_POINTOPOINT)
                                add_ptopt_localrt(ifp);
                }
                            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)");
-                                continue;
-                       }
-                       ifs.int_dstaddr = ifreq.ifr_dstaddr;
-               }
                 if (ifs.int_flags & IFF_BROADCAST) {
                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
                 if (ifs.int_flags & IFF_BROADCAST) {
                         if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
-                                syslog(LOG_ERR, "ioctl (get broadaddr)");
+                                syslog(LOG_ERR, "%s: ioctl (get broadaddr)",
+                                   ifr->ifr_name);
                                 continue;
                         }
                                 continue;
                         }
+#ifndef sun
                        ifs.int_broadaddr = ifreq.ifr_broadaddr;
                        ifs.int_broadaddr = ifreq.ifr_broadaddr;
+#else
+                       ifs.int_broadaddr = ifreq.ifr_addr;
+#endif
                }
                }
-               if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0)
-                       syslog(LOG_ERR, "ioctl (get metric)");
-               else
+#ifdef SIOCGIFMETRIC
+               if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) {
+                       syslog(LOG_ERR, "%s: ioctl (get metric)",
+                           ifr->ifr_name);
+                       ifs.int_metric = 0;
+               } else
                        ifs.int_metric = ifreq.ifr_metric;
                        ifs.int_metric = ifreq.ifr_metric;
+#else
+               ifs.int_metric = 0;
+#endif
                /*
                 * Use a minimum metric of one;
                 * treat the interface metric (default 0)
                /*
                 * Use a minimum metric of one;
                 * treat the interface metric (default 0)
@@ -124,7 +143,8 @@ ifinit()
                 */
                ifs.int_metric++;
                if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
                 */
                ifs.int_metric++;
                if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
-                       syslog(LOG_ERR, "ioctl (get netmask)");
+                       syslog(LOG_ERR, "%s: ioctl (get netmask)",
+                           ifr->ifr_name);
                        continue;
                }
                sin = (struct sockaddr_in *)&ifreq.ifr_addr;
                        continue;
                }
                sin = (struct sockaddr_in *)&ifreq.ifr_addr;
@@ -169,11 +189,12 @@ ifinit()
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
                        syslog(LOG_ERR, "routed: ifinit: out of memory\n");
                if (ifp->int_name == 0) {
                        fprintf(stderr, "routed: ifinit: out of memory\n");
                        syslog(LOG_ERR, "routed: ifinit: out of memory\n");
+                       close(s);
                        return;
                }
                strcpy(ifp->int_name, ifr->ifr_name);
                        return;
                }
                strcpy(ifp->int_name, ifr->ifr_name);
-               ifp->int_next = ifnet;
-               ifnet = ifp;
+               *ifnext = ifp;
+               ifnext = &ifp->int_next;
                traceinit(ifp);
                addrouteforif(ifp);
        }
                traceinit(ifp);
                addrouteforif(ifp);
        }
index d5d1e88..aace380 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)tables.c   5.14 (Berkeley) %G%";
+static char sccsid[] = "@(#)tables.c   5.15 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -192,9 +192,14 @@ 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;
 
+       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
@@ -203,7 +208,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++;
@@ -212,10 +217,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) {
@@ -234,7 +235,7 @@ 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);
        if (add && install)
                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
                TRACE_ACTION("CHANGE TO   ", rt);
        if (add && install)
                if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0)
@@ -263,8 +264,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;
@@ -289,7 +290,7 @@ again:
                base = nethash;
                goto again;
        }
                base = nethash;
                goto again;
        }
-       exit(s);
+       exit(sig);
 }
 
 /*
 }
 
 /*
index 569e26a..9f9e43f 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)timer.c    5.7 (Berkeley) %G%";
+static char sccsid[] = "@(#)timer.c    5.8 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -24,25 +24,27 @@ static char sccsid[] = "@(#)timer.c 5.7 (Berkeley) %G%";
  */
 #include "defs.h"
 
  */
 #include "defs.h"
 
-int    timeval = -TIMER_RATE;
+int    faketime;
 
 /*
  * Timer routine.  Performs routing information supply
  * duties and manages timers on routing table entries.
 
 /*
  * Timer routine.  Performs routing information supply
  * duties and manages timers on routing table entries.
+ * Management of the RTS_CHANGED bit assumes that we broadcast
+ * each time called.
  */
 timer()
 {
        register struct rthash *rh;
        register struct rt_entry *rt;
        struct rthash *base = hosthash;
  */
 timer()
 {
        register struct rthash *rh;
        register struct rt_entry *rt;
        struct rthash *base = hosthash;
-       int doinghost = 1, timetobroadcast, changes = 0;
+       int doinghost = 1, timetobroadcast;
        extern int externalinterfaces;
        extern int externalinterfaces;
-       time_t now;
 
 
-       timeval += TIMER_RATE;
-       if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0)
+       (void) gettimeofday(&now, (struct timezone *)NULL);
+       faketime += TIMER_RATE;
+       if (lookforinterfaces && (faketime % CHECK_INTERVAL) == 0)
                ifinit();
                ifinit();
-       timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0;
+       timetobroadcast = supplier && (faketime % SUPPLY_INTERVAL) == 0;
 again:
        for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
                rt = rh->rt_forw;
 again:
        for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) {
                rt = rh->rt_forw;
@@ -60,27 +62,10 @@ again:
                                rtdelete(rt->rt_forw);
                                continue;
                        }
                                rtdelete(rt->rt_forw);
                                continue;
                        }
-                       if (rt->rt_timer >= EXPIRE_TIME) {
-                               if (traceactions && changes++ == 0) {
-                                       (void) time(&now);
-                                       curtime = ctime(&now);
-                               }
+                       if (rt->rt_timer >= EXPIRE_TIME &&
+                           rt->rt_metric < HOPCNT_INFINITY)
                                rtchange(rt, &rt->rt_router, HOPCNT_INFINITY);
                                rtchange(rt, &rt->rt_router, HOPCNT_INFINITY);
-                       }
-                       if (rt->rt_state & RTS_CHANGED) {
-                               rt->rt_state &= ~RTS_CHANGED;
-                               /* don't send extraneous packets */
-                               if (!supplier || timetobroadcast)
-                                       continue;
-                               msg->rip_cmd = RIPCMD_RESPONSE;
-                               msg->rip_vers = RIPVERSION;
-                               msg->rip_nets[0].rip_dst = rt->rt_dst;
-                               msg->rip_nets[0].rip_dst.sa_family =
-                                  htons(msg->rip_nets[0].rip_dst.sa_family);
-                               msg->rip_nets[0].rip_metric =
-                                  htonl(min(rt->rt_metric, HOPCNT_INFINITY));
-                               toall(sendmsg);
-                       }
+                       rt->rt_state &= ~RTS_CHANGED;
                }
        }
        if (doinghost) {
                }
        }
        if (doinghost) {
@@ -88,9 +73,13 @@ again:
                base = nethash;
                goto again;
        }
                base = nethash;
                goto again;
        }
-       if (timetobroadcast)
-               toall(supply);
-       alarm(TIMER_RATE);
+       if (timetobroadcast) {
+               toall(supply, 0, (struct interface *)NULL);
+               lastbcast = now;
+               lastfullupdate = now;
+               needupdate = 0;         /* cancel any pending dynamic update */
+               nextbcast.tv_sec = 0;
+       }
 }
 
 /*
 }
 
 /*
@@ -115,7 +104,7 @@ again:
                        base = nethash;
                        goto again;
                }
                        base = nethash;
                        goto again;
                }
-               toall(supply);
+               toall(supply, 0, (struct interface *)NULL);
        }
        exit(1);
 }
        }
        exit(1);
 }
index 98f4748..79bbfc8 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)trace.c    5.7 (Berkeley) %G%";
+static char sccsid[] = "@(#)trace.c    5.8 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -31,8 +31,10 @@ static char sccsid[] = "@(#)trace.c  5.7 (Berkeley) %G%";
 #define        NRECORDS        50              /* size of circular trace buffer */
 #ifdef DEBUG
 FILE   *ftrace = stdout;
 #define        NRECORDS        50              /* size of circular trace buffer */
 #ifdef DEBUG
 FILE   *ftrace = stdout;
-int    traceactions = 1;
+int    traceactions = 0;
 #endif
 #endif
+static struct timeval lastlog;
+static char *savetracename;
 
 traceinit(ifp)
        register struct interface *ifp;
 
 traceinit(ifp)
        register struct interface *ifp;
@@ -75,12 +77,15 @@ traceon(file)
                return;
        if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
                return;
                return;
        if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
                return;
+       savetracename = file;
+       (void) gettimeofday(&now, (struct timezone *)NULL);
        ftrace = fopen(file, "a");
        if (ftrace == NULL)
                return;
        dup2(fileno(ftrace), 1);
        dup2(fileno(ftrace), 2);
        traceactions = 1;
        ftrace = fopen(file, "a");
        if (ftrace == NULL)
                return;
        dup2(fileno(ftrace), 1);
        dup2(fileno(ftrace), 2);
        traceactions = 1;
+       fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
 }
 
 traceoff()
 }
 
 traceoff()
@@ -90,7 +95,9 @@ traceoff()
        if (ftrace != NULL) {
                int fd = open("/dev/null", O_RDWR);
 
        if (ftrace != NULL) {
                int fd = open("/dev/null", O_RDWR);
 
-               fprintf(ftrace, "Tracing disabled\n");
+               fprintf(ftrace, "Tracing disabled %s\n",
+                   ctime((time_t *)&now.tv_sec));
+               fflush(ftrace);
                (void) dup2(fd, 1);
                (void) dup2(fd, 2);
                (void) close(fd);
                (void) dup2(fd, 1);
                (void) dup2(fd, 2);
                (void) close(fd);
@@ -99,22 +106,61 @@ traceoff()
        }
        traceactions = 0;
        tracehistory = 0;
        }
        traceactions = 0;
        tracehistory = 0;
+       tracepackets = 0;
+       tracecontents = 0;
 }
 
 sigtrace(s)
        int s;
 {
 }
 
 sigtrace(s)
        int s;
 {
-       if (s == SIGUSR2) {
+
+       if (s == SIGUSR2)
                traceoff();
                traceoff();
-               tracepackets = 0;
-       } else if (traceactions == 0)
+       else if (ftrace == NULL && savetracename)
+               traceon(savetracename);
+       else
+               bumploglevel();
+}
+
+/*
+ * Move to next higher level of tracing when -t option processed or
+ * SIGUSR1 is received.  Successive levels are:
+ *     traceactions
+ *     traceactions + tracepackets
+ *     traceactions + tracehistory (packets and contents after change)
+ *     traceactions + tracepackets + tracecontents
+ */
+bumploglevel()
+{
+
+       (void) gettimeofday(&now, (struct timezone *)NULL);
+       if (traceactions == 0) {
                traceactions++;
                traceactions++;
-       else if (tracehistory == 0)
+               if (ftrace)
+                       fprintf(ftrace, "Tracing actions started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else if (tracepackets == 0) {
+               tracepackets++;
+               tracehistory = 0;
+               tracecontents = 0;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing packets started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else if (tracehistory == 0) {
                tracehistory++;
                tracehistory++;
-       else {
+               if (ftrace)
+                       fprintf(ftrace, "Tracing history started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else {
                tracepackets++;
                tracepackets++;
+               tracecontents++;
                tracehistory = 0;
                tracehistory = 0;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing packet contents started %s\n",
+                           ctime((time_t *)&now.tv_sec));
        }
        }
+       if (ftrace)
+               fflush(ftrace);
 }
 
 trace(ifd, who, p, len, m)
 }
 
 trace(ifd, who, p, len, m)
@@ -136,7 +182,7 @@ trace(ifd, who, p, len, m)
                free(t->ift_packet);
                t->ift_packet = 0;
        }
                free(t->ift_packet);
                t->ift_packet = 0;
        }
-       t->ift_stamp = time(0);
+       t->ift_stamp = now;
        t->ift_who = *who;
        if (len > 0 && t->ift_packet == 0) {
                t->ift_packet = malloc(len);
        t->ift_who = *who;
        if (len > 0 && t->ift_packet == 0) {
                t->ift_packet = malloc(len);
@@ -180,9 +226,9 @@ traceaction(fd, action, rt)
 
        if (fd == NULL)
                return;
 
        if (fd == NULL)
                return;
-       if (curtime) {
-               fprintf(fd, "\n%s", curtime);
-               curtime = NULL;
+       if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
+               fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
+               lastlog = now;
        }
        fprintf(fd, "%s ", action);
        dst = (struct sockaddr_in *)&rt->rt_dst;
        }
        fprintf(fd, "%s ", action);
        dst = (struct sockaddr_in *)&rt->rt_dst;
@@ -212,9 +258,12 @@ traceaction(fd, action, rt)
                }
        }
        fprintf(fd, " timer %d\n", rt->rt_timer);
                }
        }
        fprintf(fd, " timer %d\n", rt->rt_timer);
-       if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
+       if (tracehistory && !tracepackets &&
+           (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
                dumpif(fd, rt->rt_ifp);
        fflush(fd);
                dumpif(fd, rt->rt_ifp);
        fflush(fd);
+       if (ferror(fd))
+               traceoff();
 }
 
 tracenewmetric(fd, rt, newmetric)
 }
 
 tracenewmetric(fd, rt, newmetric)
@@ -226,15 +275,22 @@ tracenewmetric(fd, rt, newmetric)
 
        if (fd == NULL)
                return;
 
        if (fd == NULL)
                return;
+       if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
+               fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
+               lastlog = now;
+       }
        dst = (struct sockaddr_in *)&rt->rt_dst;
        gate = (struct sockaddr_in *)&rt->rt_router;
        fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
        fprintf(fd, "router %s, from %d to %d\n",
             inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
        fflush(fd);
        dst = (struct sockaddr_in *)&rt->rt_dst;
        gate = (struct sockaddr_in *)&rt->rt_router;
        fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
        fprintf(fd, "router %s, from %d to %d\n",
             inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
        fflush(fd);
+       if (ferror(fd))
+               traceoff();
 }
 
 dumpif(fd, ifp)
 }
 
 dumpif(fd, ifp)
+       FILE *fd;
        register struct interface *ifp;
 {
        if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
        register struct interface *ifp;
 {
        if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
@@ -246,7 +302,6 @@ dumpif(fd, ifp)
                dumptrace(fd, "from", &ifp->int_input);
                fprintf(fd, "*** end packet history ***\n");
        }
                dumptrace(fd, "from", &ifp->int_input);
                fprintf(fd, "*** end packet history ***\n");
        }
-       fflush(fd);
 }
 
 dumptrace(fd, dir, ifd)
 }
 
 dumptrace(fd, dir, ifd)
@@ -277,28 +332,34 @@ dumptrace(fd, dir, ifd)
        }
 }
 
        }
 }
 
-dumppacket(fd, dir, who, cp, size, tstamp)
+dumppacket(fd, dir, who, cp, size, stamp)
        FILE *fd;
        struct sockaddr_in *who;                /* should be sockaddr */
        char *dir, *cp;
        register int size;
        FILE *fd;
        struct sockaddr_in *who;                /* should be sockaddr */
        char *dir, *cp;
        register int size;
-       time_t *tstamp;
+       struct timeval *stamp;
 {
        register struct rip *msg = (struct rip *)cp;
        register struct netinfo *n;
 
 {
        register struct rip *msg = (struct rip *)cp;
        register struct netinfo *n;
 
+       if (fd == NULL)
+               return;
        if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
        if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
-               fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd],
-                   dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
-       else {
-               fprintf(fd, "Bad cmd 0x%x %s %x.%d %.24s\n", msg->rip_cmd,
+               fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
                    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
                    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
-                   ctime(tstamp));
-               fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
+                   ctime((time_t *)&stamp->tv_sec));
+       else {
+               fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
+                   dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
+               fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
+                   ctime((time_t *)&stamp->tv_sec));
+               fflush(fd);
+               return;
+       }
+       if (tracepackets && tracecontents == 0) {
                fflush(fd);
                return;
        }
                fflush(fd);
                return;
        }
-       fprintf(fd, " %.24s:\n", ctime(tstamp));
        switch (msg->rip_cmd) {
 
        case RIPCMD_REQUEST:
        switch (msg->rip_cmd) {
 
        case RIPCMD_REQUEST:
@@ -306,12 +367,29 @@ dumppacket(fd, dir, who, cp, size, tstamp)
                size -= 4 * sizeof (char);
                n = msg->rip_nets;
                for (; size > 0; n++, size -= sizeof (struct netinfo)) {
                size -= 4 * sizeof (char);
                n = msg->rip_nets;
                for (; size > 0; n++, size -= sizeof (struct netinfo)) {
-                       if (size < sizeof (struct netinfo))
+                       if (size < sizeof (struct netinfo)) {
+                               fprintf(fd, "(truncated record, len %d)\n",
+                                   size);
                                break;
                                break;
-                       fprintf(fd, "\tdst %s metric %d\n",
+                       }
+                       if (sizeof(n->rip_dst.sa_family) > 1)
+                           n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
+
+                       switch ((int)n->rip_dst.sa_family) {
+
+                       case AF_INET:
+                               fprintf(fd, "\tdst %s metric %d\n",
 #define        satosin(sa)     ((struct sockaddr_in *)&sa)
 #define        satosin(sa)     ((struct sockaddr_in *)&sa)
-                            inet_ntoa(satosin(n->rip_dst)->sin_addr),
-                            ntohl(n->rip_metric));
+                                    inet_ntoa(satosin(n->rip_dst)->sin_addr),
+                                    ntohl(n->rip_metric));
+                               break;
+
+                       default:
+                               fprintf(fd, "\taf %d? metric %d\n",
+                                    n->rip_dst.sa_family,
+                                    ntohl(n->rip_metric));
+                               break;
+                       }
                }
                break;
 
                }
                break;
 
@@ -323,4 +401,6 @@ dumppacket(fd, dir, who, cp, size, tstamp)
                break;
        }
        fflush(fd);
                break;
        }
        fflush(fd);
+       if (ferror(fd))
+               traceoff();
 }
 }
index 28d2526..cbf0478 100644 (file)
@@ -14,7 +14,7 @@
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
- *     @(#)trace.h     5.5 (Berkeley) %G%
+ *     @(#)trace.h     5.6 (Berkeley) %G%
  */
 
 /*
  */
 
 /*
@@ -25,7 +25,7 @@
  * Trace record format.
  */
 struct iftrace {
  * Trace record format.
  */
 struct iftrace {
-       time_t  ift_stamp;              /* time stamp */
+       struct  timeval ift_stamp;      /* time stamp */
        struct  sockaddr ift_who;       /* from/to */
        char    *ift_packet;            /* pointer to packet */
        short   ift_size;               /* size of packet */
        struct  sockaddr ift_who;       /* from/to */
        char    *ift_packet;            /* pointer to packet */
        short   ift_size;               /* size of packet */
@@ -49,10 +49,10 @@ struct      ifdebug {
  * Packet tracing stuff.
  */
 int    tracepackets;           /* watch packets as they go by */
  * Packet tracing stuff.
  */
 int    tracepackets;           /* watch packets as they go by */
+int    tracecontents;          /* watch packet contents as they go by */
 int    traceactions;           /* on/off */
 int    tracehistory;           /* on/off */
 FILE   *ftrace;                /* output trace file */
 int    traceactions;           /* on/off */
 int    tracehistory;           /* on/off */
 FILE   *ftrace;                /* output trace file */
-char   *curtime;               /* current timestamp string */
 
 #define        TRACE_ACTION(action, route) { \
          if (traceactions) \
 
 #define        TRACE_ACTION(action, route) { \
          if (traceactions) \
@@ -69,18 +69,12 @@ char        *curtime;               /* current timestamp string */
                        trace(&ifp->int_input, src, packet, size, \
                                ntohl(ifp->int_metric)); \
          } \
                        trace(&ifp->int_input, src, packet, size, \
                                ntohl(ifp->int_metric)); \
          } \
-         if (tracepackets) { \
-               time_t t; \
-               t = time(0); \
-               dumppacket(stdout, "from", src, packet, size, &t); \
-         } \
+         if (tracepackets) \
+               dumppacket(ftrace, "from", src, packet, size, &now); \
        }
 #define        TRACE_OUTPUT(ifp, dst, size) { \
          if (tracehistory && ifp) \
                trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \
        }
 #define        TRACE_OUTPUT(ifp, dst, size) { \
          if (tracehistory && ifp) \
                trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \
-         if (tracepackets) { \
-               time_t t; \
-               t = time(0); \
-               dumppacket(stdout, "to", dst, packet, size, &t); \
-         } \
+         if (tracepackets) \
+               dumppacket(ftrace, "to", dst, packet, size, &now); \
        }
        }