122001Sdist /* 234564Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333489Sbostic * All rights reserved. 433489Sbostic * 5*42712Sbostic * %sccs.include.redist.c% 622001Sdist */ 722001Sdist 89022Ssam #ifndef lint 9*42712Sbostic static char sccsid[] = "@(#)trace.c 5.10 (Berkeley) 06/01/90"; 1033489Sbostic #endif /* not lint */ 119022Ssam 129022Ssam /* 139022Ssam * Routing Table Management Daemon 149022Ssam */ 159022Ssam #define RIPCMDS 1610245Ssam #include "defs.h" 1734571Skarels #include <sys/file.h> 1828906Skarels #include <sys/stat.h> 1934564Skarels #include <sys/signal.h> 2037970Sbostic #include "pathnames.h" 219022Ssam 229022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 239022Ssam #ifdef DEBUG 249022Ssam FILE *ftrace = stdout; 2536831Skarels int traceactions = 0; 269022Ssam #endif 2736831Skarels static struct timeval lastlog; 2836831Skarels static char *savetracename; 299022Ssam 309022Ssam traceinit(ifp) 319022Ssam register struct interface *ifp; 329022Ssam { 339022Ssam 349022Ssam if (iftraceinit(ifp, &ifp->int_input) && 359022Ssam iftraceinit(ifp, &ifp->int_output)) 369022Ssam return; 3734564Skarels tracehistory = 0; 389022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 399022Ssam } 409022Ssam 419022Ssam static 429022Ssam iftraceinit(ifp, ifd) 439022Ssam struct interface *ifp; 449022Ssam register struct ifdebug *ifd; 459022Ssam { 469022Ssam register struct iftrace *t; 479022Ssam 489022Ssam ifd->ifd_records = 499022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 509022Ssam if (ifd->ifd_records == 0) 519022Ssam return (0); 529022Ssam ifd->ifd_front = ifd->ifd_records; 5316314Skarels ifd->ifd_count = 0; 549022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 559022Ssam t->ift_size = 0; 569022Ssam t->ift_packet = 0; 579022Ssam } 589022Ssam ifd->ifd_if = ifp; 599022Ssam return (1); 609022Ssam } 619022Ssam 629022Ssam traceon(file) 639022Ssam char *file; 649022Ssam { 6528906Skarels struct stat stbuf; 669022Ssam 679022Ssam if (ftrace != NULL) 689022Ssam return; 6928906Skarels if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 7028906Skarels return; 7136831Skarels savetracename = file; 7236831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 739022Ssam ftrace = fopen(file, "a"); 749022Ssam if (ftrace == NULL) 759022Ssam return; 769022Ssam dup2(fileno(ftrace), 1); 779022Ssam dup2(fileno(ftrace), 2); 7834564Skarels traceactions = 1; 7936831Skarels fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec)); 809022Ssam } 819022Ssam 829022Ssam traceoff() 839022Ssam { 8434564Skarels if (!traceactions) 859022Ssam return; 8634571Skarels if (ftrace != NULL) { 8737970Sbostic int fd = open(_PATH_DEVNULL, O_RDWR); 8834571Skarels 8936831Skarels fprintf(ftrace, "Tracing disabled %s\n", 9036831Skarels ctime((time_t *)&now.tv_sec)); 9136831Skarels fflush(ftrace); 9234571Skarels (void) dup2(fd, 1); 9334571Skarels (void) dup2(fd, 2); 9434571Skarels (void) close(fd); 959022Ssam fclose(ftrace); 9634571Skarels ftrace = NULL; 9734571Skarels } 9834564Skarels traceactions = 0; 9934564Skarels tracehistory = 0; 10036831Skarels tracepackets = 0; 10136831Skarels tracecontents = 0; 1029022Ssam } 1039022Ssam 10434564Skarels sigtrace(s) 10534564Skarels int s; 10634564Skarels { 10736831Skarels 10836831Skarels if (s == SIGUSR2) 10934564Skarels traceoff(); 11036831Skarels else if (ftrace == NULL && savetracename) 11136831Skarels traceon(savetracename); 11236831Skarels else 11336831Skarels bumploglevel(); 11436831Skarels } 11536831Skarels 11636831Skarels /* 11736831Skarels * Move to next higher level of tracing when -t option processed or 11836831Skarels * SIGUSR1 is received. Successive levels are: 11936831Skarels * traceactions 12036831Skarels * traceactions + tracepackets 12136831Skarels * traceactions + tracehistory (packets and contents after change) 12236831Skarels * traceactions + tracepackets + tracecontents 12336831Skarels */ 12436831Skarels bumploglevel() 12536831Skarels { 12636831Skarels 12736831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 12836831Skarels if (traceactions == 0) { 12934564Skarels traceactions++; 13036831Skarels if (ftrace) 13136831Skarels fprintf(ftrace, "Tracing actions started %s\n", 13236831Skarels ctime((time_t *)&now.tv_sec)); 13336831Skarels } else if (tracepackets == 0) { 13436831Skarels tracepackets++; 13536831Skarels tracehistory = 0; 13636831Skarels tracecontents = 0; 13736831Skarels if (ftrace) 13836831Skarels fprintf(ftrace, "Tracing packets started %s\n", 13936831Skarels ctime((time_t *)&now.tv_sec)); 14036831Skarels } else if (tracehistory == 0) { 14134564Skarels tracehistory++; 14236831Skarels if (ftrace) 14336831Skarels fprintf(ftrace, "Tracing history started %s\n", 14436831Skarels ctime((time_t *)&now.tv_sec)); 14536831Skarels } else { 14634564Skarels tracepackets++; 14736831Skarels tracecontents++; 14834564Skarels tracehistory = 0; 14936831Skarels if (ftrace) 15036831Skarels fprintf(ftrace, "Tracing packet contents started %s\n", 15136831Skarels ctime((time_t *)&now.tv_sec)); 15234564Skarels } 15336831Skarels if (ftrace) 15436831Skarels fflush(ftrace); 15534564Skarels } 15634564Skarels 1579022Ssam trace(ifd, who, p, len, m) 1589022Ssam register struct ifdebug *ifd; 1599022Ssam struct sockaddr *who; 1609022Ssam char *p; 1619022Ssam int len, m; 1629022Ssam { 1639022Ssam register struct iftrace *t; 1649022Ssam 1659022Ssam if (ifd->ifd_records == 0) 1669022Ssam return; 1679022Ssam t = ifd->ifd_front++; 1689022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1699022Ssam ifd->ifd_front = ifd->ifd_records; 17016314Skarels if (ifd->ifd_count < NRECORDS) 17116314Skarels ifd->ifd_count++; 17226960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1739022Ssam free(t->ift_packet); 17426960Skarels t->ift_packet = 0; 17526960Skarels } 17636831Skarels t->ift_stamp = now; 1779022Ssam t->ift_who = *who; 17826960Skarels if (len > 0 && t->ift_packet == 0) { 1799022Ssam t->ift_packet = malloc(len); 18026960Skarels if (t->ift_packet == 0) 1819022Ssam len = 0; 1829022Ssam } 18326960Skarels if (len > 0) 18426960Skarels bcopy(p, t->ift_packet, len); 1859022Ssam t->ift_size = len; 1869022Ssam t->ift_metric = m; 1879022Ssam } 1889022Ssam 1899022Ssam traceaction(fd, action, rt) 1909022Ssam FILE *fd; 1919022Ssam char *action; 1929022Ssam struct rt_entry *rt; 1939022Ssam { 1949022Ssam struct sockaddr_in *dst, *gate; 1959022Ssam static struct bits { 1969022Ssam int t_bits; 1979022Ssam char *t_name; 1989022Ssam } flagbits[] = { 1999022Ssam { RTF_UP, "UP" }, 2009022Ssam { RTF_GATEWAY, "GATEWAY" }, 2019022Ssam { RTF_HOST, "HOST" }, 2029022Ssam { 0 } 2039022Ssam }, statebits[] = { 2049022Ssam { RTS_PASSIVE, "PASSIVE" }, 2059022Ssam { RTS_REMOTE, "REMOTE" }, 2069022Ssam { RTS_INTERFACE,"INTERFACE" }, 2079022Ssam { RTS_CHANGED, "CHANGED" }, 20828906Skarels { RTS_INTERNAL, "INTERNAL" }, 20928906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 21028906Skarels { RTS_SUBNET, "SUBNET" }, 2119022Ssam { 0 } 2129022Ssam }; 2139022Ssam register struct bits *p; 2149022Ssam register int first; 2159022Ssam char *cp; 2169022Ssam struct interface *ifp; 2179022Ssam 2189022Ssam if (fd == NULL) 2199022Ssam return; 22036831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 22136831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 22236831Skarels lastlog = now; 22334564Skarels } 2249022Ssam fprintf(fd, "%s ", action); 2259022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 2269022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 22715099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 22815099Ssam fprintf(fd, "router %s, metric %d, flags", 22915099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 2309022Ssam cp = " %s"; 2319022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 2329022Ssam if ((rt->rt_flags & p->t_bits) == 0) 2339022Ssam continue; 2349022Ssam fprintf(fd, cp, p->t_name); 2359022Ssam if (first) { 2369022Ssam cp = "|%s"; 2379022Ssam first = 0; 2389022Ssam } 2399022Ssam } 2409022Ssam fprintf(fd, " state"); 2419022Ssam cp = " %s"; 2429022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 2439022Ssam if ((rt->rt_state & p->t_bits) == 0) 2449022Ssam continue; 2459022Ssam fprintf(fd, cp, p->t_name); 2469022Ssam if (first) { 2479022Ssam cp = "|%s"; 2489022Ssam first = 0; 2499022Ssam } 2509022Ssam } 25134564Skarels fprintf(fd, " timer %d\n", rt->rt_timer); 25236831Skarels if (tracehistory && !tracepackets && 25336831Skarels (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 2549022Ssam dumpif(fd, rt->rt_ifp); 2559022Ssam fflush(fd); 25636831Skarels if (ferror(fd)) 25736831Skarels traceoff(); 2589022Ssam } 2599022Ssam 26034564Skarels tracenewmetric(fd, rt, newmetric) 26134564Skarels FILE *fd; 26234564Skarels struct rt_entry *rt; 26334564Skarels int newmetric; 26434564Skarels { 26534564Skarels struct sockaddr_in *dst, *gate; 26634564Skarels 26734564Skarels if (fd == NULL) 26834564Skarels return; 26936831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 27036831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 27136831Skarels lastlog = now; 27236831Skarels } 27334564Skarels dst = (struct sockaddr_in *)&rt->rt_dst; 27434564Skarels gate = (struct sockaddr_in *)&rt->rt_router; 27534564Skarels fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 27634564Skarels fprintf(fd, "router %s, from %d to %d\n", 27734564Skarels inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 27834564Skarels fflush(fd); 27936831Skarels if (ferror(fd)) 28036831Skarels traceoff(); 28134564Skarels } 28234564Skarels 2839022Ssam dumpif(fd, ifp) 28436831Skarels FILE *fd; 2859022Ssam register struct interface *ifp; 2869022Ssam { 28716314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 28816314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 28916314Skarels ifp->int_name); 29034564Skarels #ifdef notneeded 29116314Skarels dumptrace(fd, "to", &ifp->int_output); 29234564Skarels #endif 29316314Skarels dumptrace(fd, "from", &ifp->int_input); 29416314Skarels fprintf(fd, "*** end packet history ***\n"); 29516314Skarels } 2969022Ssam } 2979022Ssam 2989022Ssam dumptrace(fd, dir, ifd) 2999022Ssam FILE *fd; 3009022Ssam char *dir; 3019022Ssam register struct ifdebug *ifd; 3029022Ssam { 3039022Ssam register struct iftrace *t; 3049022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 3059022Ssam 3069022Ssam if (ifd->ifd_front == ifd->ifd_records && 3079022Ssam ifd->ifd_front->ift_size == 0) { 3089022Ssam fprintf(fd, "%s: no packets.\n", cp); 30926960Skarels fflush(fd); 3109022Ssam return; 3119022Ssam } 3129022Ssam fprintf(fd, "%s trace:\n", cp); 31316314Skarels t = ifd->ifd_front - ifd->ifd_count; 31416314Skarels if (t < ifd->ifd_records) 31516314Skarels t += NRECORDS; 31616314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 31716314Skarels if (t >= ifd->ifd_records + NRECORDS) 31816314Skarels t = ifd->ifd_records; 3199022Ssam if (t->ift_size == 0) 3209022Ssam continue; 32134564Skarels dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 32234564Skarels &t->ift_stamp); 3239022Ssam } 3249022Ssam } 3259022Ssam 32636831Skarels dumppacket(fd, dir, who, cp, size, stamp) 3279022Ssam FILE *fd; 3289022Ssam struct sockaddr_in *who; /* should be sockaddr */ 3299022Ssam char *dir, *cp; 3309022Ssam register int size; 33136831Skarels struct timeval *stamp; 3329022Ssam { 3339022Ssam register struct rip *msg = (struct rip *)cp; 3349022Ssam register struct netinfo *n; 3359022Ssam 33636831Skarels if (fd == NULL) 33736831Skarels return; 3389022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 33936831Skarels fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd], 34036831Skarels dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 34136831Skarels ctime((time_t *)&stamp->tv_sec)); 34236831Skarels else { 34336831Skarels fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd, 34415099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 34536831Skarels fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet, 34636831Skarels ctime((time_t *)&stamp->tv_sec)); 34726960Skarels fflush(fd); 3489022Ssam return; 3499022Ssam } 35036831Skarels if (tracepackets && tracecontents == 0) { 35136831Skarels fflush(fd); 35236831Skarels return; 35336831Skarels } 3549022Ssam switch (msg->rip_cmd) { 3559022Ssam 3569022Ssam case RIPCMD_REQUEST: 3579022Ssam case RIPCMD_RESPONSE: 3589022Ssam size -= 4 * sizeof (char); 3599022Ssam n = msg->rip_nets; 3609022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 36136831Skarels if (size < sizeof (struct netinfo)) { 36236831Skarels fprintf(fd, "(truncated record, len %d)\n", 36336831Skarels size); 3649022Ssam break; 36536831Skarels } 36636831Skarels if (sizeof(n->rip_dst.sa_family) > 1) 36736831Skarels n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); 36836831Skarels 36936831Skarels switch ((int)n->rip_dst.sa_family) { 37036831Skarels 37136831Skarels case AF_INET: 37236831Skarels fprintf(fd, "\tdst %s metric %d\n", 37315099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 37436831Skarels inet_ntoa(satosin(n->rip_dst)->sin_addr), 37536831Skarels ntohl(n->rip_metric)); 37636831Skarels break; 37736831Skarels 37836831Skarels default: 37936831Skarels fprintf(fd, "\taf %d? metric %d\n", 38036831Skarels n->rip_dst.sa_family, 38136831Skarels ntohl(n->rip_metric)); 38236831Skarels break; 38336831Skarels } 3849022Ssam } 3859022Ssam break; 3869022Ssam 3879022Ssam case RIPCMD_TRACEON: 38834564Skarels fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 3899022Ssam break; 3909022Ssam 3919022Ssam case RIPCMD_TRACEOFF: 3929022Ssam break; 3939022Ssam } 39426960Skarels fflush(fd); 39536831Skarels if (ferror(fd)) 39636831Skarels traceoff(); 3979022Ssam } 398