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 633489Sbostic * provided that this notice is preserved and that due credit is given 733489Sbostic * to the University of California at Berkeley. The name of the University 833489Sbostic * may not be used to endorse or promote products derived from this 933489Sbostic * software without specific prior written permission. This software 1033489Sbostic * is provided ``as is'' without express or implied warranty. 1122001Sdist */ 1222001Sdist 139022Ssam #ifndef lint 14*34571Skarels static char sccsid[] = "@(#)trace.c 5.6 (Berkeley) 05/31/88"; 1533489Sbostic #endif /* not lint */ 169022Ssam 179022Ssam /* 189022Ssam * Routing Table Management Daemon 199022Ssam */ 209022Ssam #define RIPCMDS 2110245Ssam #include "defs.h" 22*34571Skarels #include <sys/file.h> 2328906Skarels #include <sys/stat.h> 2434564Skarels #include <sys/signal.h> 259022Ssam 269022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 279022Ssam #ifdef DEBUG 289022Ssam FILE *ftrace = stdout; 2934564Skarels int traceactions = 1; 309022Ssam #endif 319022Ssam 329022Ssam traceinit(ifp) 339022Ssam register struct interface *ifp; 349022Ssam { 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; 739022Ssam ftrace = fopen(file, "a"); 749022Ssam if (ftrace == NULL) 759022Ssam return; 769022Ssam dup2(fileno(ftrace), 1); 779022Ssam dup2(fileno(ftrace), 2); 7834564Skarels traceactions = 1; 799022Ssam } 809022Ssam 819022Ssam traceoff() 829022Ssam { 8334564Skarels if (!traceactions) 849022Ssam return; 85*34571Skarels if (ftrace != NULL) { 86*34571Skarels int fd = open("/dev/null", O_RDWR); 87*34571Skarels 88*34571Skarels fprintf(ftrace, "Tracing disabled\n"); 89*34571Skarels (void) dup2(fd, 1); 90*34571Skarels (void) dup2(fd, 2); 91*34571Skarels (void) close(fd); 929022Ssam fclose(ftrace); 93*34571Skarels ftrace = NULL; 94*34571Skarels } 9534564Skarels traceactions = 0; 9634564Skarels tracehistory = 0; 979022Ssam } 989022Ssam 9934564Skarels sigtrace(s) 10034564Skarels int s; 10134564Skarels { 10234564Skarels if (s == SIGUSR2) { 10334564Skarels traceoff(); 10434564Skarels tracepackets = 0; 10534564Skarels } else if (traceactions == 0) 10634564Skarels traceactions++; 10734564Skarels else if (tracehistory == 0) 10834564Skarels tracehistory++; 10934564Skarels else { 11034564Skarels tracepackets++; 11134564Skarels tracehistory = 0; 11234564Skarels } 11334564Skarels } 11434564Skarels 1159022Ssam trace(ifd, who, p, len, m) 1169022Ssam register struct ifdebug *ifd; 1179022Ssam struct sockaddr *who; 1189022Ssam char *p; 1199022Ssam int len, m; 1209022Ssam { 1219022Ssam register struct iftrace *t; 1229022Ssam 1239022Ssam if (ifd->ifd_records == 0) 1249022Ssam return; 1259022Ssam t = ifd->ifd_front++; 1269022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1279022Ssam ifd->ifd_front = ifd->ifd_records; 12816314Skarels if (ifd->ifd_count < NRECORDS) 12916314Skarels ifd->ifd_count++; 13026960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1319022Ssam free(t->ift_packet); 13226960Skarels t->ift_packet = 0; 13326960Skarels } 1349022Ssam t->ift_stamp = time(0); 1359022Ssam t->ift_who = *who; 13626960Skarels if (len > 0 && t->ift_packet == 0) { 1379022Ssam t->ift_packet = malloc(len); 13826960Skarels if (t->ift_packet == 0) 1399022Ssam len = 0; 1409022Ssam } 14126960Skarels if (len > 0) 14226960Skarels bcopy(p, t->ift_packet, len); 1439022Ssam t->ift_size = len; 1449022Ssam t->ift_metric = m; 1459022Ssam } 1469022Ssam 1479022Ssam traceaction(fd, action, rt) 1489022Ssam FILE *fd; 1499022Ssam char *action; 1509022Ssam struct rt_entry *rt; 1519022Ssam { 1529022Ssam struct sockaddr_in *dst, *gate; 1539022Ssam static struct bits { 1549022Ssam int t_bits; 1559022Ssam char *t_name; 1569022Ssam } flagbits[] = { 1579022Ssam { RTF_UP, "UP" }, 1589022Ssam { RTF_GATEWAY, "GATEWAY" }, 1599022Ssam { RTF_HOST, "HOST" }, 1609022Ssam { 0 } 1619022Ssam }, statebits[] = { 1629022Ssam { RTS_PASSIVE, "PASSIVE" }, 1639022Ssam { RTS_REMOTE, "REMOTE" }, 1649022Ssam { RTS_INTERFACE,"INTERFACE" }, 1659022Ssam { RTS_CHANGED, "CHANGED" }, 16628906Skarels { RTS_INTERNAL, "INTERNAL" }, 16728906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 16828906Skarels { RTS_SUBNET, "SUBNET" }, 1699022Ssam { 0 } 1709022Ssam }; 1719022Ssam register struct bits *p; 1729022Ssam register int first; 1739022Ssam char *cp; 1749022Ssam struct interface *ifp; 1759022Ssam 1769022Ssam if (fd == NULL) 1779022Ssam return; 17834564Skarels if (curtime) { 17934564Skarels fprintf(fd, "\n%s", curtime); 18034564Skarels curtime = NULL; 18134564Skarels } 1829022Ssam fprintf(fd, "%s ", action); 1839022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 1849022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 18515099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 18615099Ssam fprintf(fd, "router %s, metric %d, flags", 18715099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 1889022Ssam cp = " %s"; 1899022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 1909022Ssam if ((rt->rt_flags & p->t_bits) == 0) 1919022Ssam continue; 1929022Ssam fprintf(fd, cp, p->t_name); 1939022Ssam if (first) { 1949022Ssam cp = "|%s"; 1959022Ssam first = 0; 1969022Ssam } 1979022Ssam } 1989022Ssam fprintf(fd, " state"); 1999022Ssam cp = " %s"; 2009022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 2019022Ssam if ((rt->rt_state & p->t_bits) == 0) 2029022Ssam continue; 2039022Ssam fprintf(fd, cp, p->t_name); 2049022Ssam if (first) { 2059022Ssam cp = "|%s"; 2069022Ssam first = 0; 2079022Ssam } 2089022Ssam } 20934564Skarels fprintf(fd, " timer %d\n", rt->rt_timer); 21016128Skarels if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 2119022Ssam dumpif(fd, rt->rt_ifp); 2129022Ssam fflush(fd); 2139022Ssam } 2149022Ssam 21534564Skarels tracenewmetric(fd, rt, newmetric) 21634564Skarels FILE *fd; 21734564Skarels struct rt_entry *rt; 21834564Skarels int newmetric; 21934564Skarels { 22034564Skarels struct sockaddr_in *dst, *gate; 22134564Skarels 22234564Skarels if (fd == NULL) 22334564Skarels return; 22434564Skarels dst = (struct sockaddr_in *)&rt->rt_dst; 22534564Skarels gate = (struct sockaddr_in *)&rt->rt_router; 22634564Skarels fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 22734564Skarels fprintf(fd, "router %s, from %d to %d\n", 22834564Skarels inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 22934564Skarels fflush(fd); 23034564Skarels } 23134564Skarels 2329022Ssam dumpif(fd, ifp) 2339022Ssam register struct interface *ifp; 2349022Ssam { 23516314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 23616314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 23716314Skarels ifp->int_name); 23834564Skarels #ifdef notneeded 23916314Skarels dumptrace(fd, "to", &ifp->int_output); 24034564Skarels #endif 24116314Skarels dumptrace(fd, "from", &ifp->int_input); 24216314Skarels fprintf(fd, "*** end packet history ***\n"); 24316314Skarels } 24426960Skarels fflush(fd); 2459022Ssam } 2469022Ssam 2479022Ssam dumptrace(fd, dir, ifd) 2489022Ssam FILE *fd; 2499022Ssam char *dir; 2509022Ssam register struct ifdebug *ifd; 2519022Ssam { 2529022Ssam register struct iftrace *t; 2539022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 2549022Ssam 2559022Ssam if (ifd->ifd_front == ifd->ifd_records && 2569022Ssam ifd->ifd_front->ift_size == 0) { 2579022Ssam fprintf(fd, "%s: no packets.\n", cp); 25826960Skarels fflush(fd); 2599022Ssam return; 2609022Ssam } 2619022Ssam fprintf(fd, "%s trace:\n", cp); 26216314Skarels t = ifd->ifd_front - ifd->ifd_count; 26316314Skarels if (t < ifd->ifd_records) 26416314Skarels t += NRECORDS; 26516314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 26616314Skarels if (t >= ifd->ifd_records + NRECORDS) 26716314Skarels t = ifd->ifd_records; 2689022Ssam if (t->ift_size == 0) 2699022Ssam continue; 27034564Skarels dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 27134564Skarels &t->ift_stamp); 2729022Ssam } 2739022Ssam } 2749022Ssam 27534564Skarels dumppacket(fd, dir, who, cp, size, tstamp) 2769022Ssam FILE *fd; 2779022Ssam struct sockaddr_in *who; /* should be sockaddr */ 2789022Ssam char *dir, *cp; 2799022Ssam register int size; 28034564Skarels time_t *tstamp; 2819022Ssam { 2829022Ssam register struct rip *msg = (struct rip *)cp; 2839022Ssam register struct netinfo *n; 2849022Ssam 2859022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 28615099Ssam fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], 28715099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2889022Ssam else { 28934564Skarels fprintf(fd, "Bad cmd 0x%x %s %x.%d %.24s\n", msg->rip_cmd, 29034564Skarels dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 29134564Skarels ctime(tstamp)); 2929022Ssam fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 29326960Skarels fflush(fd); 2949022Ssam return; 2959022Ssam } 29634564Skarels fprintf(fd, " %.24s:\n", ctime(tstamp)); 2979022Ssam switch (msg->rip_cmd) { 2989022Ssam 2999022Ssam case RIPCMD_REQUEST: 3009022Ssam case RIPCMD_RESPONSE: 3019022Ssam size -= 4 * sizeof (char); 3029022Ssam n = msg->rip_nets; 3039022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 3049022Ssam if (size < sizeof (struct netinfo)) 3059022Ssam break; 30615099Ssam fprintf(fd, "\tdst %s metric %d\n", 30715099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 30815099Ssam inet_ntoa(satosin(n->rip_dst)->sin_addr), 30915099Ssam ntohl(n->rip_metric)); 3109022Ssam } 3119022Ssam break; 3129022Ssam 3139022Ssam case RIPCMD_TRACEON: 31434564Skarels fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 3159022Ssam break; 3169022Ssam 3179022Ssam case RIPCMD_TRACEOFF: 3189022Ssam break; 3199022Ssam } 32026960Skarels fflush(fd); 3219022Ssam } 322