BSD 4_4_Lite2 release
[unix-history] / usr / src / sbin / routed / trace.c
index dca8fd2..691904e 100644 (file)
@@ -1,17 +1,38 @@
 /*
 /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1983, 1988, 1993
+ *     The 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[] = "@(#)trace.c    5.4 (Berkeley) %G%";
+static char sccsid[] = "@(#)trace.c    8.2 (Berkeley) 4/28/95";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -20,21 +41,28 @@ static char sccsid[] = "@(#)trace.c 5.4 (Berkeley) %G%";
 #define        RIPCMDS
 #include "defs.h"
 #include <sys/stat.h>
 #define        RIPCMDS
 #include "defs.h"
 #include <sys/stat.h>
+#include <sys/signal.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "pathnames.h"
 
 #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    tracing = 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;
 {
+       static int iftraceinit();
 
        if (iftraceinit(ifp, &ifp->int_input) &&
            iftraceinit(ifp, &ifp->int_output))
                return;
 
        if (iftraceinit(ifp, &ifp->int_input) &&
            iftraceinit(ifp, &ifp->int_output))
                return;
-       tracing = 0;
+       tracehistory = 0;
        fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
 }
 
        fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
 }
 
@@ -68,22 +96,91 @@ 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);
        ftrace = fopen(file, "a");
        if (ftrace == NULL)
                return;
        dup2(fileno(ftrace), 1);
        dup2(fileno(ftrace), 2);
-       tracing = 1;
+       traceactions = 1;
+       fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
 }
 
 traceoff()
 {
 }
 
 traceoff()
 {
-       if (!tracing)
+       if (!traceactions)
                return;
                return;
-       if (ftrace != NULL)
+       if (ftrace != NULL) {
+               int fd = open(_PATH_DEVNULL, O_RDWR);
+
+               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);
                fclose(ftrace);
                fclose(ftrace);
-       ftrace = NULL;
-       tracing = 0;
+               ftrace = NULL;
+       }
+       traceactions = 0;
+       tracehistory = 0;
+       tracepackets = 0;
+       tracecontents = 0;
+}
+
+void
+sigtrace(s)
+       int s;
+{
+
+       if (s == SIGUSR2)
+               traceoff();
+       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++;
+               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++;
+               if (ftrace)
+                       fprintf(ftrace, "Tracing history started %s\n",
+                           ctime((time_t *)&now.tv_sec));
+       } else {
+               tracepackets++;
+               tracecontents++;
+               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)
@@ -105,7 +202,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);
@@ -113,7 +210,7 @@ trace(ifd, who, p, len, m)
                        len = 0;
        }
        if (len > 0)
                        len = 0;
        }
        if (len > 0)
-               bcopy(p, t->ift_packet, len);
+               memmove(t->ift_packet, p, len);
        t->ift_size = len;
        t->ift_metric = m;
 }
        t->ift_size = len;
        t->ift_metric = m;
 }
@@ -149,6 +246,10 @@ traceaction(fd, action, rt)
 
        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;
+       }
        fprintf(fd, "%s ", action);
        dst = (struct sockaddr_in *)&rt->rt_dst;
        gate = (struct sockaddr_in *)&rt->rt_router;
        fprintf(fd, "%s ", action);
        dst = (struct sockaddr_in *)&rt->rt_dst;
        gate = (struct sockaddr_in *)&rt->rt_router;
@@ -176,23 +277,51 @@ traceaction(fd, action, rt)
                        first = 0;
                }
        }
                        first = 0;
                }
        }
-       putc('\n', fd);
-       if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
+       fprintf(fd, " timer %d\n", rt->rt_timer);
+       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)
+       FILE *fd;
+       struct rt_entry *rt;
+       int newmetric;
+{
+       struct sockaddr_in *dst, *gate;
+
+       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);
+       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) {
                fprintf(fd, "*** Packet history for interface %s ***\n",
                        ifp->int_name);
        register struct interface *ifp;
 {
        if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
                fprintf(fd, "*** Packet history for interface %s ***\n",
                        ifp->int_name);
+#ifdef notneeded
                dumptrace(fd, "to", &ifp->int_output);
                dumptrace(fd, "to", &ifp->int_output);
+#endif
                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)
@@ -218,28 +347,36 @@ dumptrace(fd, dir, ifd)
                        t = ifd->ifd_records;
                if (t->ift_size == 0)
                        continue;
                        t = ifd->ifd_records;
                if (t->ift_size == 0)
                        continue;
-               fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
-                       t->ift_metric);
-               dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
+               dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
+                   &t->ift_stamp);
        }
 }
 
        }
 }
 
-dumppacket(fd, dir, who, cp, size)
+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;
+       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));
+               fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
+                   dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
+                   ctime((time_t *)&stamp->tv_sec));
        else {
        else {
-               fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd,
+               fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
                    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
                    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
-               fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
+               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;
        }
@@ -247,26 +384,43 @@ dumppacket(fd, dir, who, cp, size)
 
        case RIPCMD_REQUEST:
        case RIPCMD_RESPONSE:
 
        case RIPCMD_REQUEST:
        case RIPCMD_RESPONSE:
-               fprintf(fd, ":\n");
                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;
 
        case RIPCMD_TRACEON:
                }
                break;
 
        case RIPCMD_TRACEON:
-               fprintf(fd, "file=%*s\n", size, msg->rip_tracefile);
+               fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
                break;
 
        case RIPCMD_TRACEOFF:
                break;
 
        case RIPCMD_TRACEOFF:
-               fprintf(fd, "\n");
                break;
        }
        fflush(fd);
                break;
        }
        fflush(fd);
+       if (ferror(fd))
+               traceoff();
 }
 }