122001Sdist /* 234564Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333489Sbostic * All rights reserved. 433489Sbostic * 542712Sbostic * %sccs.include.redist.c% 622001Sdist */ 722001Sdist 89022Ssam #ifndef lint 9*46784Sbostic static char sccsid[] = "@(#)trace.c 5.11 (Berkeley) 02/28/91"; 1033489Sbostic #endif /* not lint */ 119022Ssam 129022Ssam /* 139022Ssam * Routing Table Management Daemon 149022Ssam */ 159022Ssam #define RIPCMDS 1610245Ssam #include "defs.h" 1728906Skarels #include <sys/stat.h> 1834564Skarels #include <sys/signal.h> 19*46784Sbostic #include <fcntl.h> 20*46784Sbostic #include <stdlib.h> 2137970Sbostic #include "pathnames.h" 229022Ssam 239022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 249022Ssam #ifdef DEBUG 259022Ssam FILE *ftrace = stdout; 2636831Skarels int traceactions = 0; 279022Ssam #endif 2836831Skarels static struct timeval lastlog; 2936831Skarels static char *savetracename; 309022Ssam 319022Ssam traceinit(ifp) 329022Ssam register struct interface *ifp; 339022Ssam { 34*46784Sbostic static int iftraceinit(); 359022Ssam 369022Ssam if (iftraceinit(ifp, &ifp->int_input) && 379022Ssam iftraceinit(ifp, &ifp->int_output)) 389022Ssam return; 3934564Skarels tracehistory = 0; 409022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 419022Ssam } 429022Ssam 439022Ssam static 449022Ssam iftraceinit(ifp, ifd) 459022Ssam struct interface *ifp; 469022Ssam register struct ifdebug *ifd; 479022Ssam { 489022Ssam register struct iftrace *t; 499022Ssam 509022Ssam ifd->ifd_records = 519022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 529022Ssam if (ifd->ifd_records == 0) 539022Ssam return (0); 549022Ssam ifd->ifd_front = ifd->ifd_records; 5516314Skarels ifd->ifd_count = 0; 569022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 579022Ssam t->ift_size = 0; 589022Ssam t->ift_packet = 0; 599022Ssam } 609022Ssam ifd->ifd_if = ifp; 619022Ssam return (1); 629022Ssam } 639022Ssam 649022Ssam traceon(file) 659022Ssam char *file; 669022Ssam { 6728906Skarels struct stat stbuf; 689022Ssam 699022Ssam if (ftrace != NULL) 709022Ssam return; 7128906Skarels if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 7228906Skarels return; 7336831Skarels savetracename = file; 7436831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 759022Ssam ftrace = fopen(file, "a"); 769022Ssam if (ftrace == NULL) 779022Ssam return; 789022Ssam dup2(fileno(ftrace), 1); 799022Ssam dup2(fileno(ftrace), 2); 8034564Skarels traceactions = 1; 8136831Skarels fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec)); 829022Ssam } 839022Ssam 849022Ssam traceoff() 859022Ssam { 8634564Skarels if (!traceactions) 879022Ssam return; 8834571Skarels if (ftrace != NULL) { 8937970Sbostic int fd = open(_PATH_DEVNULL, O_RDWR); 9034571Skarels 9136831Skarels fprintf(ftrace, "Tracing disabled %s\n", 9236831Skarels ctime((time_t *)&now.tv_sec)); 9336831Skarels fflush(ftrace); 9434571Skarels (void) dup2(fd, 1); 9534571Skarels (void) dup2(fd, 2); 9634571Skarels (void) close(fd); 979022Ssam fclose(ftrace); 9834571Skarels ftrace = NULL; 9934571Skarels } 10034564Skarels traceactions = 0; 10134564Skarels tracehistory = 0; 10236831Skarels tracepackets = 0; 10336831Skarels tracecontents = 0; 1049022Ssam } 1059022Ssam 106*46784Sbostic void 10734564Skarels sigtrace(s) 10834564Skarels int s; 10934564Skarels { 11036831Skarels 11136831Skarels if (s == SIGUSR2) 11234564Skarels traceoff(); 11336831Skarels else if (ftrace == NULL && savetracename) 11436831Skarels traceon(savetracename); 11536831Skarels else 11636831Skarels bumploglevel(); 11736831Skarels } 11836831Skarels 11936831Skarels /* 12036831Skarels * Move to next higher level of tracing when -t option processed or 12136831Skarels * SIGUSR1 is received. Successive levels are: 12236831Skarels * traceactions 12336831Skarels * traceactions + tracepackets 12436831Skarels * traceactions + tracehistory (packets and contents after change) 12536831Skarels * traceactions + tracepackets + tracecontents 12636831Skarels */ 12736831Skarels bumploglevel() 12836831Skarels { 12936831Skarels 13036831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 13136831Skarels if (traceactions == 0) { 13234564Skarels traceactions++; 13336831Skarels if (ftrace) 13436831Skarels fprintf(ftrace, "Tracing actions started %s\n", 13536831Skarels ctime((time_t *)&now.tv_sec)); 13636831Skarels } else if (tracepackets == 0) { 13736831Skarels tracepackets++; 13836831Skarels tracehistory = 0; 13936831Skarels tracecontents = 0; 14036831Skarels if (ftrace) 14136831Skarels fprintf(ftrace, "Tracing packets started %s\n", 14236831Skarels ctime((time_t *)&now.tv_sec)); 14336831Skarels } else if (tracehistory == 0) { 14434564Skarels tracehistory++; 14536831Skarels if (ftrace) 14636831Skarels fprintf(ftrace, "Tracing history started %s\n", 14736831Skarels ctime((time_t *)&now.tv_sec)); 14836831Skarels } else { 14934564Skarels tracepackets++; 15036831Skarels tracecontents++; 15134564Skarels tracehistory = 0; 15236831Skarels if (ftrace) 15336831Skarels fprintf(ftrace, "Tracing packet contents started %s\n", 15436831Skarels ctime((time_t *)&now.tv_sec)); 15534564Skarels } 15636831Skarels if (ftrace) 15736831Skarels fflush(ftrace); 15834564Skarels } 15934564Skarels 1609022Ssam trace(ifd, who, p, len, m) 1619022Ssam register struct ifdebug *ifd; 1629022Ssam struct sockaddr *who; 1639022Ssam char *p; 1649022Ssam int len, m; 1659022Ssam { 1669022Ssam register struct iftrace *t; 1679022Ssam 1689022Ssam if (ifd->ifd_records == 0) 1699022Ssam return; 1709022Ssam t = ifd->ifd_front++; 1719022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1729022Ssam ifd->ifd_front = ifd->ifd_records; 17316314Skarels if (ifd->ifd_count < NRECORDS) 17416314Skarels ifd->ifd_count++; 17526960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1769022Ssam free(t->ift_packet); 17726960Skarels t->ift_packet = 0; 17826960Skarels } 17936831Skarels t->ift_stamp = now; 1809022Ssam t->ift_who = *who; 18126960Skarels if (len > 0 && t->ift_packet == 0) { 1829022Ssam t->ift_packet = malloc(len); 18326960Skarels if (t->ift_packet == 0) 1849022Ssam len = 0; 1859022Ssam } 18626960Skarels if (len > 0) 18726960Skarels bcopy(p, t->ift_packet, len); 1889022Ssam t->ift_size = len; 1899022Ssam t->ift_metric = m; 1909022Ssam } 1919022Ssam 1929022Ssam traceaction(fd, action, rt) 1939022Ssam FILE *fd; 1949022Ssam char *action; 1959022Ssam struct rt_entry *rt; 1969022Ssam { 1979022Ssam struct sockaddr_in *dst, *gate; 1989022Ssam static struct bits { 1999022Ssam int t_bits; 2009022Ssam char *t_name; 2019022Ssam } flagbits[] = { 2029022Ssam { RTF_UP, "UP" }, 2039022Ssam { RTF_GATEWAY, "GATEWAY" }, 2049022Ssam { RTF_HOST, "HOST" }, 2059022Ssam { 0 } 2069022Ssam }, statebits[] = { 2079022Ssam { RTS_PASSIVE, "PASSIVE" }, 2089022Ssam { RTS_REMOTE, "REMOTE" }, 2099022Ssam { RTS_INTERFACE,"INTERFACE" }, 2109022Ssam { RTS_CHANGED, "CHANGED" }, 21128906Skarels { RTS_INTERNAL, "INTERNAL" }, 21228906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 21328906Skarels { RTS_SUBNET, "SUBNET" }, 2149022Ssam { 0 } 2159022Ssam }; 2169022Ssam register struct bits *p; 2179022Ssam register int first; 2189022Ssam char *cp; 2199022Ssam struct interface *ifp; 2209022Ssam 2219022Ssam if (fd == NULL) 2229022Ssam return; 22336831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 22436831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 22536831Skarels lastlog = now; 22634564Skarels } 2279022Ssam fprintf(fd, "%s ", action); 2289022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 2299022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 23015099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 23115099Ssam fprintf(fd, "router %s, metric %d, flags", 23215099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 2339022Ssam cp = " %s"; 2349022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 2359022Ssam if ((rt->rt_flags & p->t_bits) == 0) 2369022Ssam continue; 2379022Ssam fprintf(fd, cp, p->t_name); 2389022Ssam if (first) { 2399022Ssam cp = "|%s"; 2409022Ssam first = 0; 2419022Ssam } 2429022Ssam } 2439022Ssam fprintf(fd, " state"); 2449022Ssam cp = " %s"; 2459022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 2469022Ssam if ((rt->rt_state & p->t_bits) == 0) 2479022Ssam continue; 2489022Ssam fprintf(fd, cp, p->t_name); 2499022Ssam if (first) { 2509022Ssam cp = "|%s"; 2519022Ssam first = 0; 2529022Ssam } 2539022Ssam } 25434564Skarels fprintf(fd, " timer %d\n", rt->rt_timer); 25536831Skarels if (tracehistory && !tracepackets && 25636831Skarels (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 2579022Ssam dumpif(fd, rt->rt_ifp); 2589022Ssam fflush(fd); 25936831Skarels if (ferror(fd)) 26036831Skarels traceoff(); 2619022Ssam } 2629022Ssam 26334564Skarels tracenewmetric(fd, rt, newmetric) 26434564Skarels FILE *fd; 26534564Skarels struct rt_entry *rt; 26634564Skarels int newmetric; 26734564Skarels { 26834564Skarels struct sockaddr_in *dst, *gate; 26934564Skarels 27034564Skarels if (fd == NULL) 27134564Skarels return; 27236831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 27336831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 27436831Skarels lastlog = now; 27536831Skarels } 27634564Skarels dst = (struct sockaddr_in *)&rt->rt_dst; 27734564Skarels gate = (struct sockaddr_in *)&rt->rt_router; 27834564Skarels fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 27934564Skarels fprintf(fd, "router %s, from %d to %d\n", 28034564Skarels inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 28134564Skarels fflush(fd); 28236831Skarels if (ferror(fd)) 28336831Skarels traceoff(); 28434564Skarels } 28534564Skarels 2869022Ssam dumpif(fd, ifp) 28736831Skarels FILE *fd; 2889022Ssam register struct interface *ifp; 2899022Ssam { 29016314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 29116314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 29216314Skarels ifp->int_name); 29334564Skarels #ifdef notneeded 29416314Skarels dumptrace(fd, "to", &ifp->int_output); 29534564Skarels #endif 29616314Skarels dumptrace(fd, "from", &ifp->int_input); 29716314Skarels fprintf(fd, "*** end packet history ***\n"); 29816314Skarels } 2999022Ssam } 3009022Ssam 3019022Ssam dumptrace(fd, dir, ifd) 3029022Ssam FILE *fd; 3039022Ssam char *dir; 3049022Ssam register struct ifdebug *ifd; 3059022Ssam { 3069022Ssam register struct iftrace *t; 3079022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 3089022Ssam 3099022Ssam if (ifd->ifd_front == ifd->ifd_records && 3109022Ssam ifd->ifd_front->ift_size == 0) { 3119022Ssam fprintf(fd, "%s: no packets.\n", cp); 31226960Skarels fflush(fd); 3139022Ssam return; 3149022Ssam } 3159022Ssam fprintf(fd, "%s trace:\n", cp); 31616314Skarels t = ifd->ifd_front - ifd->ifd_count; 31716314Skarels if (t < ifd->ifd_records) 31816314Skarels t += NRECORDS; 31916314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 32016314Skarels if (t >= ifd->ifd_records + NRECORDS) 32116314Skarels t = ifd->ifd_records; 3229022Ssam if (t->ift_size == 0) 3239022Ssam continue; 32434564Skarels dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 32534564Skarels &t->ift_stamp); 3269022Ssam } 3279022Ssam } 3289022Ssam 32936831Skarels dumppacket(fd, dir, who, cp, size, stamp) 3309022Ssam FILE *fd; 3319022Ssam struct sockaddr_in *who; /* should be sockaddr */ 3329022Ssam char *dir, *cp; 3339022Ssam register int size; 33436831Skarels struct timeval *stamp; 3359022Ssam { 3369022Ssam register struct rip *msg = (struct rip *)cp; 3379022Ssam register struct netinfo *n; 3389022Ssam 33936831Skarels if (fd == NULL) 34036831Skarels return; 3419022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 34236831Skarels fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd], 34336831Skarels dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 34436831Skarels ctime((time_t *)&stamp->tv_sec)); 34536831Skarels else { 34636831Skarels fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd, 34715099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 34836831Skarels fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet, 34936831Skarels ctime((time_t *)&stamp->tv_sec)); 35026960Skarels fflush(fd); 3519022Ssam return; 3529022Ssam } 35336831Skarels if (tracepackets && tracecontents == 0) { 35436831Skarels fflush(fd); 35536831Skarels return; 35636831Skarels } 3579022Ssam switch (msg->rip_cmd) { 3589022Ssam 3599022Ssam case RIPCMD_REQUEST: 3609022Ssam case RIPCMD_RESPONSE: 3619022Ssam size -= 4 * sizeof (char); 3629022Ssam n = msg->rip_nets; 3639022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 36436831Skarels if (size < sizeof (struct netinfo)) { 36536831Skarels fprintf(fd, "(truncated record, len %d)\n", 36636831Skarels size); 3679022Ssam break; 36836831Skarels } 36936831Skarels if (sizeof(n->rip_dst.sa_family) > 1) 37036831Skarels n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); 37136831Skarels 37236831Skarels switch ((int)n->rip_dst.sa_family) { 37336831Skarels 37436831Skarels case AF_INET: 37536831Skarels fprintf(fd, "\tdst %s metric %d\n", 37615099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 37736831Skarels inet_ntoa(satosin(n->rip_dst)->sin_addr), 37836831Skarels ntohl(n->rip_metric)); 37936831Skarels break; 38036831Skarels 38136831Skarels default: 38236831Skarels fprintf(fd, "\taf %d? metric %d\n", 38336831Skarels n->rip_dst.sa_family, 38436831Skarels ntohl(n->rip_metric)); 38536831Skarels break; 38636831Skarels } 3879022Ssam } 3889022Ssam break; 3899022Ssam 3909022Ssam case RIPCMD_TRACEON: 39134564Skarels fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 3929022Ssam break; 3939022Ssam 3949022Ssam case RIPCMD_TRACEOFF: 3959022Ssam break; 3969022Ssam } 39726960Skarels fflush(fd); 39836831Skarels if (ferror(fd)) 39936831Skarels traceoff(); 4009022Ssam } 401