122001Sdist /* 234564Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333489Sbostic * All rights reserved. 433489Sbostic * 533489Sbostic * Redistribution and use in source and binary forms are permitted 634771Sbostic * provided that the above copyright notice and this paragraph are 734771Sbostic * duplicated in all such forms and that any documentation, 834771Sbostic * advertising materials, and other materials related to such 934771Sbostic * distribution and use acknowledge that the software was developed 1034771Sbostic * by the University of California, Berkeley. The name of the 1134771Sbostic * University may not be used to endorse or promote products derived 1234771Sbostic * from this software without specific prior written permission. 1334771Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434771Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534771Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622001Sdist */ 1722001Sdist 189022Ssam #ifndef lint 19*37970Sbostic static char sccsid[] = "@(#)trace.c 5.9 (Berkeley) 05/11/89"; 2033489Sbostic #endif /* not lint */ 219022Ssam 229022Ssam /* 239022Ssam * Routing Table Management Daemon 249022Ssam */ 259022Ssam #define RIPCMDS 2610245Ssam #include "defs.h" 2734571Skarels #include <sys/file.h> 2828906Skarels #include <sys/stat.h> 2934564Skarels #include <sys/signal.h> 30*37970Sbostic #include "pathnames.h" 319022Ssam 329022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 339022Ssam #ifdef DEBUG 349022Ssam FILE *ftrace = stdout; 3536831Skarels int traceactions = 0; 369022Ssam #endif 3736831Skarels static struct timeval lastlog; 3836831Skarels static char *savetracename; 399022Ssam 409022Ssam traceinit(ifp) 419022Ssam register struct interface *ifp; 429022Ssam { 439022Ssam 449022Ssam if (iftraceinit(ifp, &ifp->int_input) && 459022Ssam iftraceinit(ifp, &ifp->int_output)) 469022Ssam return; 4734564Skarels tracehistory = 0; 489022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 499022Ssam } 509022Ssam 519022Ssam static 529022Ssam iftraceinit(ifp, ifd) 539022Ssam struct interface *ifp; 549022Ssam register struct ifdebug *ifd; 559022Ssam { 569022Ssam register struct iftrace *t; 579022Ssam 589022Ssam ifd->ifd_records = 599022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 609022Ssam if (ifd->ifd_records == 0) 619022Ssam return (0); 629022Ssam ifd->ifd_front = ifd->ifd_records; 6316314Skarels ifd->ifd_count = 0; 649022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 659022Ssam t->ift_size = 0; 669022Ssam t->ift_packet = 0; 679022Ssam } 689022Ssam ifd->ifd_if = ifp; 699022Ssam return (1); 709022Ssam } 719022Ssam 729022Ssam traceon(file) 739022Ssam char *file; 749022Ssam { 7528906Skarels struct stat stbuf; 769022Ssam 779022Ssam if (ftrace != NULL) 789022Ssam return; 7928906Skarels if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 8028906Skarels return; 8136831Skarels savetracename = file; 8236831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 839022Ssam ftrace = fopen(file, "a"); 849022Ssam if (ftrace == NULL) 859022Ssam return; 869022Ssam dup2(fileno(ftrace), 1); 879022Ssam dup2(fileno(ftrace), 2); 8834564Skarels traceactions = 1; 8936831Skarels fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec)); 909022Ssam } 919022Ssam 929022Ssam traceoff() 939022Ssam { 9434564Skarels if (!traceactions) 959022Ssam return; 9634571Skarels if (ftrace != NULL) { 97*37970Sbostic int fd = open(_PATH_DEVNULL, O_RDWR); 9834571Skarels 9936831Skarels fprintf(ftrace, "Tracing disabled %s\n", 10036831Skarels ctime((time_t *)&now.tv_sec)); 10136831Skarels fflush(ftrace); 10234571Skarels (void) dup2(fd, 1); 10334571Skarels (void) dup2(fd, 2); 10434571Skarels (void) close(fd); 1059022Ssam fclose(ftrace); 10634571Skarels ftrace = NULL; 10734571Skarels } 10834564Skarels traceactions = 0; 10934564Skarels tracehistory = 0; 11036831Skarels tracepackets = 0; 11136831Skarels tracecontents = 0; 1129022Ssam } 1139022Ssam 11434564Skarels sigtrace(s) 11534564Skarels int s; 11634564Skarels { 11736831Skarels 11836831Skarels if (s == SIGUSR2) 11934564Skarels traceoff(); 12036831Skarels else if (ftrace == NULL && savetracename) 12136831Skarels traceon(savetracename); 12236831Skarels else 12336831Skarels bumploglevel(); 12436831Skarels } 12536831Skarels 12636831Skarels /* 12736831Skarels * Move to next higher level of tracing when -t option processed or 12836831Skarels * SIGUSR1 is received. Successive levels are: 12936831Skarels * traceactions 13036831Skarels * traceactions + tracepackets 13136831Skarels * traceactions + tracehistory (packets and contents after change) 13236831Skarels * traceactions + tracepackets + tracecontents 13336831Skarels */ 13436831Skarels bumploglevel() 13536831Skarels { 13636831Skarels 13736831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 13836831Skarels if (traceactions == 0) { 13934564Skarels traceactions++; 14036831Skarels if (ftrace) 14136831Skarels fprintf(ftrace, "Tracing actions started %s\n", 14236831Skarels ctime((time_t *)&now.tv_sec)); 14336831Skarels } else if (tracepackets == 0) { 14436831Skarels tracepackets++; 14536831Skarels tracehistory = 0; 14636831Skarels tracecontents = 0; 14736831Skarels if (ftrace) 14836831Skarels fprintf(ftrace, "Tracing packets started %s\n", 14936831Skarels ctime((time_t *)&now.tv_sec)); 15036831Skarels } else if (tracehistory == 0) { 15134564Skarels tracehistory++; 15236831Skarels if (ftrace) 15336831Skarels fprintf(ftrace, "Tracing history started %s\n", 15436831Skarels ctime((time_t *)&now.tv_sec)); 15536831Skarels } else { 15634564Skarels tracepackets++; 15736831Skarels tracecontents++; 15834564Skarels tracehistory = 0; 15936831Skarels if (ftrace) 16036831Skarels fprintf(ftrace, "Tracing packet contents started %s\n", 16136831Skarels ctime((time_t *)&now.tv_sec)); 16234564Skarels } 16336831Skarels if (ftrace) 16436831Skarels fflush(ftrace); 16534564Skarels } 16634564Skarels 1679022Ssam trace(ifd, who, p, len, m) 1689022Ssam register struct ifdebug *ifd; 1699022Ssam struct sockaddr *who; 1709022Ssam char *p; 1719022Ssam int len, m; 1729022Ssam { 1739022Ssam register struct iftrace *t; 1749022Ssam 1759022Ssam if (ifd->ifd_records == 0) 1769022Ssam return; 1779022Ssam t = ifd->ifd_front++; 1789022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1799022Ssam ifd->ifd_front = ifd->ifd_records; 18016314Skarels if (ifd->ifd_count < NRECORDS) 18116314Skarels ifd->ifd_count++; 18226960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1839022Ssam free(t->ift_packet); 18426960Skarels t->ift_packet = 0; 18526960Skarels } 18636831Skarels t->ift_stamp = now; 1879022Ssam t->ift_who = *who; 18826960Skarels if (len > 0 && t->ift_packet == 0) { 1899022Ssam t->ift_packet = malloc(len); 19026960Skarels if (t->ift_packet == 0) 1919022Ssam len = 0; 1929022Ssam } 19326960Skarels if (len > 0) 19426960Skarels bcopy(p, t->ift_packet, len); 1959022Ssam t->ift_size = len; 1969022Ssam t->ift_metric = m; 1979022Ssam } 1989022Ssam 1999022Ssam traceaction(fd, action, rt) 2009022Ssam FILE *fd; 2019022Ssam char *action; 2029022Ssam struct rt_entry *rt; 2039022Ssam { 2049022Ssam struct sockaddr_in *dst, *gate; 2059022Ssam static struct bits { 2069022Ssam int t_bits; 2079022Ssam char *t_name; 2089022Ssam } flagbits[] = { 2099022Ssam { RTF_UP, "UP" }, 2109022Ssam { RTF_GATEWAY, "GATEWAY" }, 2119022Ssam { RTF_HOST, "HOST" }, 2129022Ssam { 0 } 2139022Ssam }, statebits[] = { 2149022Ssam { RTS_PASSIVE, "PASSIVE" }, 2159022Ssam { RTS_REMOTE, "REMOTE" }, 2169022Ssam { RTS_INTERFACE,"INTERFACE" }, 2179022Ssam { RTS_CHANGED, "CHANGED" }, 21828906Skarels { RTS_INTERNAL, "INTERNAL" }, 21928906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 22028906Skarels { RTS_SUBNET, "SUBNET" }, 2219022Ssam { 0 } 2229022Ssam }; 2239022Ssam register struct bits *p; 2249022Ssam register int first; 2259022Ssam char *cp; 2269022Ssam struct interface *ifp; 2279022Ssam 2289022Ssam if (fd == NULL) 2299022Ssam return; 23036831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 23136831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 23236831Skarels lastlog = now; 23334564Skarels } 2349022Ssam fprintf(fd, "%s ", action); 2359022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 2369022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 23715099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 23815099Ssam fprintf(fd, "router %s, metric %d, flags", 23915099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 2409022Ssam cp = " %s"; 2419022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 2429022Ssam if ((rt->rt_flags & p->t_bits) == 0) 2439022Ssam continue; 2449022Ssam fprintf(fd, cp, p->t_name); 2459022Ssam if (first) { 2469022Ssam cp = "|%s"; 2479022Ssam first = 0; 2489022Ssam } 2499022Ssam } 2509022Ssam fprintf(fd, " state"); 2519022Ssam cp = " %s"; 2529022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 2539022Ssam if ((rt->rt_state & p->t_bits) == 0) 2549022Ssam continue; 2559022Ssam fprintf(fd, cp, p->t_name); 2569022Ssam if (first) { 2579022Ssam cp = "|%s"; 2589022Ssam first = 0; 2599022Ssam } 2609022Ssam } 26134564Skarels fprintf(fd, " timer %d\n", rt->rt_timer); 26236831Skarels if (tracehistory && !tracepackets && 26336831Skarels (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 2649022Ssam dumpif(fd, rt->rt_ifp); 2659022Ssam fflush(fd); 26636831Skarels if (ferror(fd)) 26736831Skarels traceoff(); 2689022Ssam } 2699022Ssam 27034564Skarels tracenewmetric(fd, rt, newmetric) 27134564Skarels FILE *fd; 27234564Skarels struct rt_entry *rt; 27334564Skarels int newmetric; 27434564Skarels { 27534564Skarels struct sockaddr_in *dst, *gate; 27634564Skarels 27734564Skarels if (fd == NULL) 27834564Skarels return; 27936831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 28036831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 28136831Skarels lastlog = now; 28236831Skarels } 28334564Skarels dst = (struct sockaddr_in *)&rt->rt_dst; 28434564Skarels gate = (struct sockaddr_in *)&rt->rt_router; 28534564Skarels fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 28634564Skarels fprintf(fd, "router %s, from %d to %d\n", 28734564Skarels inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 28834564Skarels fflush(fd); 28936831Skarels if (ferror(fd)) 29036831Skarels traceoff(); 29134564Skarels } 29234564Skarels 2939022Ssam dumpif(fd, ifp) 29436831Skarels FILE *fd; 2959022Ssam register struct interface *ifp; 2969022Ssam { 29716314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 29816314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 29916314Skarels ifp->int_name); 30034564Skarels #ifdef notneeded 30116314Skarels dumptrace(fd, "to", &ifp->int_output); 30234564Skarels #endif 30316314Skarels dumptrace(fd, "from", &ifp->int_input); 30416314Skarels fprintf(fd, "*** end packet history ***\n"); 30516314Skarels } 3069022Ssam } 3079022Ssam 3089022Ssam dumptrace(fd, dir, ifd) 3099022Ssam FILE *fd; 3109022Ssam char *dir; 3119022Ssam register struct ifdebug *ifd; 3129022Ssam { 3139022Ssam register struct iftrace *t; 3149022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 3159022Ssam 3169022Ssam if (ifd->ifd_front == ifd->ifd_records && 3179022Ssam ifd->ifd_front->ift_size == 0) { 3189022Ssam fprintf(fd, "%s: no packets.\n", cp); 31926960Skarels fflush(fd); 3209022Ssam return; 3219022Ssam } 3229022Ssam fprintf(fd, "%s trace:\n", cp); 32316314Skarels t = ifd->ifd_front - ifd->ifd_count; 32416314Skarels if (t < ifd->ifd_records) 32516314Skarels t += NRECORDS; 32616314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 32716314Skarels if (t >= ifd->ifd_records + NRECORDS) 32816314Skarels t = ifd->ifd_records; 3299022Ssam if (t->ift_size == 0) 3309022Ssam continue; 33134564Skarels dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 33234564Skarels &t->ift_stamp); 3339022Ssam } 3349022Ssam } 3359022Ssam 33636831Skarels dumppacket(fd, dir, who, cp, size, stamp) 3379022Ssam FILE *fd; 3389022Ssam struct sockaddr_in *who; /* should be sockaddr */ 3399022Ssam char *dir, *cp; 3409022Ssam register int size; 34136831Skarels struct timeval *stamp; 3429022Ssam { 3439022Ssam register struct rip *msg = (struct rip *)cp; 3449022Ssam register struct netinfo *n; 3459022Ssam 34636831Skarels if (fd == NULL) 34736831Skarels return; 3489022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 34936831Skarels fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd], 35036831Skarels dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 35136831Skarels ctime((time_t *)&stamp->tv_sec)); 35236831Skarels else { 35336831Skarels fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd, 35415099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 35536831Skarels fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet, 35636831Skarels ctime((time_t *)&stamp->tv_sec)); 35726960Skarels fflush(fd); 3589022Ssam return; 3599022Ssam } 36036831Skarels if (tracepackets && tracecontents == 0) { 36136831Skarels fflush(fd); 36236831Skarels return; 36336831Skarels } 3649022Ssam switch (msg->rip_cmd) { 3659022Ssam 3669022Ssam case RIPCMD_REQUEST: 3679022Ssam case RIPCMD_RESPONSE: 3689022Ssam size -= 4 * sizeof (char); 3699022Ssam n = msg->rip_nets; 3709022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 37136831Skarels if (size < sizeof (struct netinfo)) { 37236831Skarels fprintf(fd, "(truncated record, len %d)\n", 37336831Skarels size); 3749022Ssam break; 37536831Skarels } 37636831Skarels if (sizeof(n->rip_dst.sa_family) > 1) 37736831Skarels n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); 37836831Skarels 37936831Skarels switch ((int)n->rip_dst.sa_family) { 38036831Skarels 38136831Skarels case AF_INET: 38236831Skarels fprintf(fd, "\tdst %s metric %d\n", 38315099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 38436831Skarels inet_ntoa(satosin(n->rip_dst)->sin_addr), 38536831Skarels ntohl(n->rip_metric)); 38636831Skarels break; 38736831Skarels 38836831Skarels default: 38936831Skarels fprintf(fd, "\taf %d? metric %d\n", 39036831Skarels n->rip_dst.sa_family, 39136831Skarels ntohl(n->rip_metric)); 39236831Skarels break; 39336831Skarels } 3949022Ssam } 3959022Ssam break; 3969022Ssam 3979022Ssam case RIPCMD_TRACEON: 39834564Skarels fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 3999022Ssam break; 4009022Ssam 4019022Ssam case RIPCMD_TRACEOFF: 4029022Ssam break; 4039022Ssam } 40426960Skarels fflush(fd); 40536831Skarels if (ferror(fd)) 40636831Skarels traceoff(); 4079022Ssam } 408