home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / routed / trace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-23  |  10.7 KB  |  429 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[] = "from: @(#)trace.c    5.11 (Berkeley) 2/28/91";*/
  36. static char rcsid[] = "$Id: trace.c,v 1.1 1994/05/23 09:08:13 rzsfl Exp rzsfl $";
  37. #endif /* not lint */
  38.  
  39. /*
  40.  * Routing Table Management Daemon
  41.  */
  42. #define    RIPCMDS
  43. #include "defs.h"
  44. #include <sys/stat.h>
  45. #include <sys/signal.h>
  46. #include <fcntl.h>
  47. #include <stdlib.h>
  48. #include "pathnames.h"
  49.  
  50. #define    NRECORDS    50        /* size of circular trace buffer */
  51. #ifdef DEBUG
  52. FILE    *ftrace = stdout;
  53. int    traceactions = 0;
  54. #endif
  55. static    struct timeval lastlog;
  56. static    char *savetracename;
  57.  
  58. traceinit(ifp)
  59.     register struct interface *ifp;
  60. {
  61.     static int iftraceinit();
  62.  
  63.     if (iftraceinit(ifp, &ifp->int_input) &&
  64.         iftraceinit(ifp, &ifp->int_output))
  65.         return;
  66.     tracehistory = 0;
  67.     fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
  68. }
  69.  
  70. static
  71. iftraceinit(ifp, ifd)
  72.     struct interface *ifp;
  73.     register struct ifdebug *ifd;
  74. {
  75.     register struct iftrace *t;
  76.  
  77.     ifd->ifd_records =
  78.       (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
  79.     if (ifd->ifd_records == 0)
  80.         return (0);
  81.     ifd->ifd_front = ifd->ifd_records;
  82.     ifd->ifd_count = 0;
  83.     for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
  84.         t->ift_size = 0;
  85.         t->ift_packet = 0;
  86.     }
  87.     ifd->ifd_if = ifp;
  88.     return (1);
  89. }
  90.  
  91. traceon(file)
  92.     char *file;
  93. {
  94.     struct stat stbuf;
  95.  
  96.     if (ftrace != NULL)
  97.         return;
  98.     if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
  99.         return;
  100.     savetracename = file;
  101.     (void) gettimeofday(&now, (struct timezone *)NULL);
  102.     ftrace = fopen(file, "a");
  103.     if (ftrace == NULL)
  104.         return;
  105.     dup2(fileno(ftrace), 1);
  106.     dup2(fileno(ftrace), 2);
  107.     traceactions = 1;
  108.     fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
  109. }
  110.  
  111. traceoff()
  112. {
  113.     if (!traceactions)
  114.         return;
  115.     if (ftrace != NULL) {
  116.         int fd = open(_PATH_DEVNULL, O_RDWR);
  117.  
  118.         fprintf(ftrace, "Tracing disabled %s\n",
  119.             ctime((time_t *)&now.tv_sec));
  120.         fflush(ftrace);
  121.         (void) dup2(fd, 1);
  122.         (void) dup2(fd, 2);
  123.         (void) close(fd);
  124.         fclose(ftrace);
  125.         ftrace = NULL;
  126.     }
  127.     traceactions = 0;
  128.     tracehistory = 0;
  129.     tracepackets = 0;
  130.     tracecontents = 0;
  131. }
  132.  
  133. void
  134. sigtrace(s)
  135.     int s;
  136. {
  137.     (void) signal(s, sigtrace);
  138.  
  139.     if (s == SIGUSR2)
  140.         traceoff();
  141.     else if (ftrace == NULL && savetracename)
  142.         traceon(savetracename);
  143.     else
  144.         bumploglevel();
  145. }
  146.  
  147. /*
  148.  * Move to next higher level of tracing when -t option processed or
  149.  * SIGUSR1 is received.  Successive levels are:
  150.  *    traceactions
  151.  *    traceactions + tracepackets
  152.  *    traceactions + tracehistory (packets and contents after change)
  153.  *    traceactions + tracepackets + tracecontents
  154.  */
  155. bumploglevel()
  156. {
  157.  
  158.     (void) gettimeofday(&now, (struct timezone *)NULL);
  159.     if (traceactions == 0) {
  160.         traceactions++;
  161.         if (ftrace)
  162.             fprintf(ftrace, "Tracing actions started %s\n",
  163.                 ctime((time_t *)&now.tv_sec));
  164.     } else if (tracepackets == 0) {
  165.         tracepackets++;
  166.         tracehistory = 0;
  167.         tracecontents = 0;
  168.         if (ftrace)
  169.             fprintf(ftrace, "Tracing packets started %s\n",
  170.                 ctime((time_t *)&now.tv_sec));
  171.     } else if (tracehistory == 0) {
  172.         tracehistory++;
  173.         if (ftrace)
  174.             fprintf(ftrace, "Tracing history started %s\n",
  175.                 ctime((time_t *)&now.tv_sec));
  176.     } else {
  177.         tracepackets++;
  178.         tracecontents++;
  179.         tracehistory = 0;
  180.         if (ftrace)
  181.             fprintf(ftrace, "Tracing packet contents started %s\n",
  182.                 ctime((time_t *)&now.tv_sec));
  183.     }
  184.     if (ftrace)
  185.         fflush(ftrace);
  186. }
  187.  
  188. trace(ifd, who, p, len, m)
  189.     register struct ifdebug *ifd;
  190.     struct sockaddr *who;
  191.     char *p;
  192.     int len, m;
  193. {
  194.     register struct iftrace *t;
  195.  
  196.     if (ifd->ifd_records == 0)
  197.         return;
  198.     t = ifd->ifd_front++;
  199.     if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
  200.         ifd->ifd_front = ifd->ifd_records;
  201.     if (ifd->ifd_count < NRECORDS)
  202.         ifd->ifd_count++;
  203.     if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
  204.         free(t->ift_packet);
  205.         t->ift_packet = 0;
  206.     }
  207.     t->ift_stamp = now;
  208.     t->ift_who = *who;
  209.     if (len > 0 && t->ift_packet == 0) {
  210.         t->ift_packet = malloc(len);
  211.         if (t->ift_packet == 0)
  212.             len = 0;
  213.     }
  214.     if (len > 0)
  215.         bcopy(p, t->ift_packet, len);
  216.     t->ift_size = len;
  217.     t->ift_metric = m;
  218. }
  219.  
  220. traceaction(fd, action, rt)
  221.     FILE *fd;
  222.     char *action;
  223.     struct rt_entry *rt;
  224. {
  225.     struct sockaddr_in *dst, *gate;
  226.     static struct bits {
  227.         int    t_bits;
  228.         char    *t_name;
  229.     } flagbits[] = {
  230.         { RTF_UP,    "UP" },
  231.         { RTF_GATEWAY,    "GATEWAY" },
  232.         { RTF_HOST,    "HOST" },
  233.         { 0 }
  234.     }, statebits[] = {
  235.         { RTS_PASSIVE,    "PASSIVE" },
  236.         { RTS_REMOTE,    "REMOTE" },
  237.         { RTS_INTERFACE,"INTERFACE" },
  238.         { RTS_CHANGED,    "CHANGED" },
  239.         { RTS_INTERNAL,    "INTERNAL" },
  240.         { RTS_EXTERNAL,    "EXTERNAL" },
  241.         { RTS_SUBNET,    "SUBNET" },
  242.         { 0 }
  243.     };
  244.     register struct bits *p;
  245.     register int first;
  246.     char *cp;
  247.     struct interface *ifp;
  248.  
  249.     if (fd == NULL)
  250.         return;
  251.     if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
  252.         fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
  253.         lastlog = now;
  254.     }
  255.     fprintf(fd, "%s ", action);
  256.     dst = (struct sockaddr_in *)&rt->rt_dst;
  257.     gate = (struct sockaddr_in *)&rt->rt_router;
  258.     fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
  259.     fprintf(fd, "router %s, metric %d, flags",
  260.          inet_ntoa(gate->sin_addr), rt->rt_metric);
  261.     cp = " %s";
  262.     for (first = 1, p = flagbits; p->t_bits > 0; p++) {
  263.         if ((rt->rt_flags & p->t_bits) == 0)
  264.             continue;
  265.         fprintf(fd, cp, p->t_name);
  266.         if (first) {
  267.             cp = "|%s";
  268.             first = 0;
  269.         }
  270.     }
  271.     fprintf(fd, " state");
  272.     cp = " %s";
  273.     for (first = 1, p = statebits; p->t_bits > 0; p++) {
  274.         if ((rt->rt_state & p->t_bits) == 0)
  275.             continue;
  276.         fprintf(fd, cp, p->t_name);
  277.         if (first) {
  278.             cp = "|%s";
  279.             first = 0;
  280.         }
  281.     }
  282.     fprintf(fd, " timer %d\n", rt->rt_timer);
  283.     if (tracehistory && !tracepackets &&
  284.         (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
  285.         dumpif(fd, rt->rt_ifp);
  286.     fflush(fd);
  287.     if (ferror(fd))
  288.         traceoff();
  289. }
  290.  
  291. tracenewmetric(fd, rt, newmetric)
  292.     FILE *fd;
  293.     struct rt_entry *rt;
  294.     int newmetric;
  295. {
  296.     struct sockaddr_in *dst, *gate;
  297.  
  298.     if (fd == NULL)
  299.         return;
  300.     if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
  301.         fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
  302.         lastlog = now;
  303.     }
  304.     dst = (struct sockaddr_in *)&rt->rt_dst;
  305.     gate = (struct sockaddr_in *)&rt->rt_router;
  306.     fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
  307.     fprintf(fd, "router %s, from %d to %d\n",
  308.          inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
  309.     fflush(fd);
  310.     if (ferror(fd))
  311.         traceoff();
  312. }
  313.  
  314. dumpif(fd, ifp)
  315.     FILE *fd;
  316.     register struct interface *ifp;
  317. {
  318.     if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
  319.         fprintf(fd, "*** Packet history for interface %s ***\n",
  320.             ifp->int_name);
  321. #ifdef notneeded
  322.         dumptrace(fd, "to", &ifp->int_output);
  323. #endif
  324.         dumptrace(fd, "from", &ifp->int_input);
  325.         fprintf(fd, "*** end packet history ***\n");
  326.     }
  327. }
  328.  
  329. dumptrace(fd, dir, ifd)
  330.     FILE *fd;
  331.     char *dir;
  332.     register struct ifdebug *ifd;
  333. {
  334.     register struct iftrace *t;
  335.     char *cp = !strcmp(dir, "to") ? "Output" : "Input";
  336.  
  337.     if (ifd->ifd_front == ifd->ifd_records &&
  338.         ifd->ifd_front->ift_size == 0) {
  339.         fprintf(fd, "%s: no packets.\n", cp);
  340.         fflush(fd);
  341.         return;
  342.     }
  343.     fprintf(fd, "%s trace:\n", cp);
  344.     t = ifd->ifd_front - ifd->ifd_count;
  345.     if (t < ifd->ifd_records)
  346.         t += NRECORDS;
  347.     for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
  348.         if (t >= ifd->ifd_records + NRECORDS)
  349.             t = ifd->ifd_records;
  350.         if (t->ift_size == 0)
  351.             continue;
  352.         dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
  353.             &t->ift_stamp);
  354.     }
  355. }
  356.  
  357. dumppacket(fd, dir, who, cp, size, stamp)
  358.     FILE *fd;
  359.     struct sockaddr_in *who;        /* should be sockaddr */
  360.     char *dir, *cp;
  361.     register int size;
  362.     struct timeval *stamp;
  363. {
  364.     register struct rip *msg = (struct rip *)cp;
  365.     register struct netinfo *n;
  366.  
  367.     if (fd == NULL)
  368.         return;
  369.     if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
  370.         fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
  371.             dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
  372.             ctime((time_t *)&stamp->tv_sec));
  373.     else {
  374.         fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
  375.             dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
  376.         fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
  377.             ctime((time_t *)&stamp->tv_sec));
  378.         fflush(fd);
  379.         return;
  380.     }
  381.     if (tracepackets && tracecontents == 0) {
  382.         fflush(fd);
  383.         return;
  384.     }
  385.     switch (msg->rip_cmd) {
  386.  
  387.     case RIPCMD_REQUEST:
  388.     case RIPCMD_RESPONSE:
  389.         size -= 4 * sizeof (char);
  390.         n = msg->rip_nets;
  391.         for (; size > 0; n++, size -= sizeof (struct netinfo)) {
  392.             if (size < sizeof (struct netinfo)) {
  393.                 fprintf(fd, "(truncated record, len %d)\n",
  394.                     size);
  395.                 break;
  396.             }
  397.             if (sizeof(n->rip_dst.sa_family) > 1)
  398.                 n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
  399.  
  400.             switch ((int)n->rip_dst.sa_family) {
  401.  
  402.             case AF_INET:
  403.                 fprintf(fd, "\tdst %s metric %d\n",
  404. #define    satosin(sa)    ((struct sockaddr_in *)&sa)
  405.                      inet_ntoa(satosin(n->rip_dst)->sin_addr),
  406.                      ntohl(n->rip_metric));
  407.                 break;
  408.  
  409.             default:
  410.                 fprintf(fd, "\taf %d? metric %d\n",
  411.                      n->rip_dst.sa_family,
  412.                      ntohl(n->rip_metric));
  413.                 break;
  414.             }
  415.         }
  416.         break;
  417.  
  418.     case RIPCMD_TRACEON:
  419.         fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
  420.         break;
  421.  
  422.     case RIPCMD_TRACEOFF:
  423.         break;
  424.     }
  425.     fflush(fd);
  426.     if (ferror(fd))
  427.         traceoff();
  428. }
  429.