home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / routed / trace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-16  |  10.5 KB  |  427 lines

  1. /*
  2.  * Copyright (c) 1983, 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)trace.c    5.11 (Berkeley) 2/28/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * Routing Table Management Daemon
  40.  */
  41. #define    RIPCMDS
  42. #include "defs.h"
  43. #include <sys/stat.h>
  44. #include <sys/signal.h>
  45. #include <fcntl.h>
  46. #include <stdlib.h>
  47. #include "pathnames.h"
  48.  
  49. #define    NRECORDS    50        /* size of circular trace buffer */
  50. #ifdef DEBUG
  51. FILE    *ftrace = stdout;
  52. int    traceactions = 0;
  53. #endif
  54. static    struct timeval lastlog;
  55. static    char *savetracename;
  56.  
  57. traceinit(ifp)
  58.     register struct interface *ifp;
  59. {
  60.     static int iftraceinit();
  61.  
  62.     if (iftraceinit(ifp, &ifp->int_input) &&
  63.         iftraceinit(ifp, &ifp->int_output))
  64.         return;
  65.     tracehistory = 0;
  66.     fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
  67. }
  68.  
  69. static
  70. iftraceinit(ifp, ifd)
  71.     struct interface *ifp;
  72.     register struct ifdebug *ifd;
  73. {
  74.     register struct iftrace *t;
  75.  
  76.     ifd->ifd_records =
  77.       (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
  78.     if (ifd->ifd_records == 0)
  79.         return (0);
  80.     ifd->ifd_front = ifd->ifd_records;
  81.     ifd->ifd_count = 0;
  82.     for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
  83.         t->ift_size = 0;
  84.         t->ift_packet = 0;
  85.     }
  86.     ifd->ifd_if = ifp;
  87.     return (1);
  88. }
  89.  
  90. traceon(file)
  91.     char *file;
  92. {
  93.     struct stat stbuf;
  94.  
  95.     if (ftrace != NULL)
  96.         return;
  97.     if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
  98.         return;
  99.     savetracename = file;
  100.     (void) gettimeofday(&now, (struct timezone *)NULL);
  101.     ftrace = fopen(file, "a");
  102.     if (ftrace == NULL)
  103.         return;
  104.     dup2(fileno(ftrace), 1);
  105.     dup2(fileno(ftrace), 2);
  106.     traceactions = 1;
  107.     fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
  108. }
  109.  
  110. traceoff()
  111. {
  112.     if (!traceactions)
  113.         return;
  114.     if (ftrace != NULL) {
  115.         int fd = open(_PATH_DEVNULL, O_RDWR);
  116.  
  117.         fprintf(ftrace, "Tracing disabled %s\n",
  118.             ctime((time_t *)&now.tv_sec));
  119.         fflush(ftrace);
  120.         (void) dup2(fd, 1);
  121.         (void) dup2(fd, 2);
  122.         (void) close(fd);
  123.         fclose(ftrace);
  124.         ftrace = NULL;
  125.     }
  126.     traceactions = 0;
  127.     tracehistory = 0;
  128.     tracepackets = 0;
  129.     tracecontents = 0;
  130. }
  131.  
  132. void
  133. sigtrace(s)
  134.     int s;
  135. {
  136.  
  137.     if (s == SIGUSR2)
  138.         traceoff();
  139.     else if (ftrace == NULL && savetracename)
  140.         traceon(savetracename);
  141.     else
  142.         bumploglevel();
  143. }
  144.  
  145. /*
  146.  * Move to next higher level of tracing when -t option processed or
  147.  * SIGUSR1 is received.  Successive levels are:
  148.  *    traceactions
  149.  *    traceactions + tracepackets
  150.  *    traceactions + tracehistory (packets and contents after change)
  151.  *    traceactions + tracepackets + tracecontents
  152.  */
  153. bumploglevel()
  154. {
  155.  
  156.     (void) gettimeofday(&now, (struct timezone *)NULL);
  157.     if (traceactions == 0) {
  158.         traceactions++;
  159.         if (ftrace)
  160.             fprintf(ftrace, "Tracing actions started %s\n",
  161.                 ctime((time_t *)&now.tv_sec));
  162.     } else if (tracepackets == 0) {
  163.         tracepackets++;
  164.         tracehistory = 0;
  165.         tracecontents = 0;
  166.         if (ftrace)
  167.             fprintf(ftrace, "Tracing packets started %s\n",
  168.                 ctime((time_t *)&now.tv_sec));
  169.     } else if (tracehistory == 0) {
  170.         tracehistory++;
  171.         if (ftrace)
  172.             fprintf(ftrace, "Tracing history started %s\n",
  173.                 ctime((time_t *)&now.tv_sec));
  174.     } else {
  175.         tracepackets++;
  176.         tracecontents++;
  177.         tracehistory = 0;
  178.         if (ftrace)
  179.             fprintf(ftrace, "Tracing packet contents started %s\n",
  180.                 ctime((time_t *)&now.tv_sec));
  181.     }
  182.     if (ftrace)
  183.         fflush(ftrace);
  184. }
  185.  
  186. trace(ifd, who, p, len, m)
  187.     register struct ifdebug *ifd;
  188.     struct sockaddr *who;
  189.     char *p;
  190.     int len, m;
  191. {
  192.     register struct iftrace *t;
  193.  
  194.     if (ifd->ifd_records == 0)
  195.         return;
  196.     t = ifd->ifd_front++;
  197.     if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
  198.         ifd->ifd_front = ifd->ifd_records;
  199.     if (ifd->ifd_count < NRECORDS)
  200.         ifd->ifd_count++;
  201.     if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
  202.         free(t->ift_packet);
  203.         t->ift_packet = 0;
  204.     }
  205.     t->ift_stamp = now;
  206.     t->ift_who = *who;
  207.     if (len > 0 && t->ift_packet == 0) {
  208.         t->ift_packet = malloc(len);
  209.         if (t->ift_packet == 0)
  210.             len = 0;
  211.     }
  212.     if (len > 0)
  213.         bcopy(p, t->ift_packet, len);
  214.     t->ift_size = len;
  215.     t->ift_metric = m;
  216. }
  217.  
  218. traceaction(fd, action, rt)
  219.     FILE *fd;
  220.     char *action;
  221.     struct rt_entry *rt;
  222. {
  223.     struct sockaddr_in *dst, *gate;
  224.     static struct bits {
  225.         int    t_bits;
  226.         char    *t_name;
  227.     } flagbits[] = {
  228.         { RTF_UP,    "UP" },
  229.         { RTF_GATEWAY,    "GATEWAY" },
  230.         { RTF_HOST,    "HOST" },
  231.         { 0 }
  232.     }, statebits[] = {
  233.         { RTS_PASSIVE,    "PASSIVE" },
  234.         { RTS_REMOTE,    "REMOTE" },
  235.         { RTS_INTERFACE,"INTERFACE" },
  236.         { RTS_CHANGED,    "CHANGED" },
  237.         { RTS_INTERNAL,    "INTERNAL" },
  238.         { RTS_EXTERNAL,    "EXTERNAL" },
  239.         { RTS_SUBNET,    "SUBNET" },
  240.         { 0 }
  241.     };
  242.     register struct bits *p;
  243.     register int first;
  244.     char *cp;
  245.     struct interface *ifp;
  246.  
  247.     if (fd == NULL)
  248.         return;
  249.     if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
  250.         fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
  251.         lastlog = now;
  252.     }
  253.     fprintf(fd, "%s ", action);
  254.     dst = (struct sockaddr_in *)&rt->rt_dst;
  255.     gate = (struct sockaddr_in *)&rt->rt_router;
  256.     fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
  257.     fprintf(fd, "router %s, metric %d, flags",
  258.          inet_ntoa(gate->sin_addr), rt->rt_metric);
  259.     cp = " %s";
  260.     for (first = 1, p = flagbits; p->t_bits > 0; p++) {
  261.         if ((rt->rt_flags & p->t_bits) == 0)
  262.             continue;
  263.         fprintf(fd, cp, p->t_name);
  264.         if (first) {
  265.             cp = "|%s";
  266.             first = 0;
  267.         }
  268.     }
  269.     fprintf(fd, " state");
  270.     cp = " %s";
  271.     for (first = 1, p = statebits; p->t_bits > 0; p++) {
  272.         if ((rt->rt_state & p->t_bits) == 0)
  273.             continue;
  274.         fprintf(fd, cp, p->t_name);
  275.         if (first) {
  276.             cp = "|%s";
  277.             first = 0;
  278.         }
  279.     }
  280.     fprintf(fd, " timer %d\n", rt->rt_timer);
  281.     if (tracehistory && !tracepackets &&
  282.         (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
  283.         dumpif(fd, rt->rt_ifp);
  284.     fflush(fd);
  285.     if (ferror(fd))
  286.         traceoff();
  287. }
  288.  
  289. tracenewmetric(fd, rt, newmetric)
  290.     FILE *fd;
  291.     struct rt_entry *rt;
  292.     int newmetric;
  293. {
  294.     struct sockaddr_in *dst, *gate;
  295.  
  296.     if (fd == NULL)
  297.         return;
  298.     if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
  299.         fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
  300.         lastlog = now;
  301.     }
  302.     dst = (struct sockaddr_in *)&rt->rt_dst;
  303.     gate = (struct sockaddr_in *)&rt->rt_router;
  304.     fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
  305.     fprintf(fd, "router %s, from %d to %d\n",
  306.          inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
  307.     fflush(fd);
  308.     if (ferror(fd))
  309.         traceoff();
  310. }
  311.  
  312. dumpif(fd, ifp)
  313.     FILE *fd;
  314.     register struct interface *ifp;
  315. {
  316.     if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
  317.         fprintf(fd, "*** Packet history for interface %s ***\n",
  318.             ifp->int_name);
  319. #ifdef notneeded
  320.         dumptrace(fd, "to", &ifp->int_output);
  321. #endif
  322.         dumptrace(fd, "from", &ifp->int_input);
  323.         fprintf(fd, "*** end packet history ***\n");
  324.     }
  325. }
  326.  
  327. dumptrace(fd, dir, ifd)
  328.     FILE *fd;
  329.     char *dir;
  330.     register struct ifdebug *ifd;
  331. {
  332.     register struct iftrace *t;
  333.     char *cp = !strcmp(dir, "to") ? "Output" : "Input";
  334.  
  335.     if (ifd->ifd_front == ifd->ifd_records &&
  336.         ifd->ifd_front->ift_size == 0) {
  337.         fprintf(fd, "%s: no packets.\n", cp);
  338.         fflush(fd);
  339.         return;
  340.     }
  341.     fprintf(fd, "%s trace:\n", cp);
  342.     t = ifd->ifd_front - ifd->ifd_count;
  343.     if (t < ifd->ifd_records)
  344.         t += NRECORDS;
  345.     for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
  346.         if (t >= ifd->ifd_records + NRECORDS)
  347.             t = ifd->ifd_records;
  348.         if (t->ift_size == 0)
  349.             continue;
  350.         dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
  351.             &t->ift_stamp);
  352.     }
  353. }
  354.  
  355. dumppacket(fd, dir, who, cp, size, stamp)
  356.     FILE *fd;
  357.     struct sockaddr_in *who;        /* should be sockaddr */
  358.     char *dir, *cp;
  359.     register int size;
  360.     struct timeval *stamp;
  361. {
  362.     register struct rip *msg = (struct rip *)cp;
  363.     register struct netinfo *n;
  364.  
  365.     if (fd == NULL)
  366.         return;
  367.     if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
  368.         fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
  369.             dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
  370.             ctime((time_t *)&stamp->tv_sec));
  371.     else {
  372.         fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
  373.             dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
  374.         fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
  375.             ctime((time_t *)&stamp->tv_sec));
  376.         fflush(fd);
  377.         return;
  378.     }
  379.     if (tracepackets && tracecontents == 0) {
  380.         fflush(fd);
  381.         return;
  382.     }
  383.     switch (msg->rip_cmd) {
  384.  
  385.     case RIPCMD_REQUEST:
  386.     case RIPCMD_RESPONSE:
  387.         size -= 4 * sizeof (char);
  388.         n = msg->rip_nets;
  389.         for (; size > 0; n++, size -= sizeof (struct netinfo)) {
  390.             if (size < sizeof (struct netinfo)) {
  391.                 fprintf(fd, "(truncated record, len %d)\n",
  392.                     size);
  393.                 break;
  394.             }
  395.             if (sizeof(n->rip_dst.sa_family) > 1)
  396.                 n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
  397.  
  398.             switch ((int)n->rip_dst.sa_family) {
  399.  
  400.             case AF_INET:
  401.                 fprintf(fd, "\tdst %s metric %d\n",
  402. #define    satosin(sa)    ((struct sockaddr_in *)&sa)
  403.                      inet_ntoa(satosin(n->rip_dst)->sin_addr),
  404.                      ntohl(n->rip_metric));
  405.                 break;
  406.  
  407.             default:
  408.                 fprintf(fd, "\taf %d? metric %d\n",
  409.                      n->rip_dst.sa_family,
  410.                      ntohl(n->rip_metric));
  411.                 break;
  412.             }
  413.         }
  414.         break;
  415.  
  416.     case RIPCMD_TRACEON:
  417.         fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
  418.         break;
  419.  
  420.     case RIPCMD_TRACEOFF:
  421.         break;
  422.     }
  423.     fflush(fd);
  424.     if (ferror(fd))
  425.         traceoff();
  426. }
  427.