122001Sdist /* 222001Sdist * Copyright (c) 1983 Regents of the University of California. 322001Sdist * All rights reserved. The Berkeley software License Agreement 422001Sdist * specifies the terms and conditions for redistribution. 522001Sdist */ 622001Sdist 79022Ssam #ifndef lint 8*28906Skarels static char sccsid[] = "@(#)trace.c 5.3 (Berkeley) 05/30/86"; 922001Sdist #endif not lint 109022Ssam 119022Ssam /* 129022Ssam * Routing Table Management Daemon 139022Ssam */ 149022Ssam #define RIPCMDS 1510245Ssam #include "defs.h" 16*28906Skarels #include <sys/stat.h> 179022Ssam 189022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 199022Ssam #ifdef DEBUG 209022Ssam FILE *ftrace = stdout; 219022Ssam int tracing = 1; 229022Ssam #endif 239022Ssam 249022Ssam traceinit(ifp) 259022Ssam register struct interface *ifp; 269022Ssam { 279022Ssam 289022Ssam if (iftraceinit(ifp, &ifp->int_input) && 299022Ssam iftraceinit(ifp, &ifp->int_output)) 309022Ssam return; 319022Ssam tracing = 0; 329022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 339022Ssam } 349022Ssam 359022Ssam static 369022Ssam iftraceinit(ifp, ifd) 379022Ssam struct interface *ifp; 389022Ssam register struct ifdebug *ifd; 399022Ssam { 409022Ssam register struct iftrace *t; 419022Ssam 429022Ssam ifd->ifd_records = 439022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 449022Ssam if (ifd->ifd_records == 0) 459022Ssam return (0); 469022Ssam ifd->ifd_front = ifd->ifd_records; 4716314Skarels ifd->ifd_count = 0; 489022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 499022Ssam t->ift_size = 0; 509022Ssam t->ift_packet = 0; 519022Ssam } 529022Ssam ifd->ifd_if = ifp; 539022Ssam return (1); 549022Ssam } 559022Ssam 569022Ssam traceon(file) 579022Ssam char *file; 589022Ssam { 59*28906Skarels struct stat stbuf; 609022Ssam 619022Ssam if (ftrace != NULL) 629022Ssam return; 63*28906Skarels if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 64*28906Skarels return; 659022Ssam ftrace = fopen(file, "a"); 669022Ssam if (ftrace == NULL) 679022Ssam return; 689022Ssam dup2(fileno(ftrace), 1); 699022Ssam dup2(fileno(ftrace), 2); 709022Ssam tracing = 1; 719022Ssam } 729022Ssam 739022Ssam traceoff() 749022Ssam { 759022Ssam if (!tracing) 769022Ssam return; 779022Ssam if (ftrace != NULL) 789022Ssam fclose(ftrace); 799022Ssam ftrace = NULL; 809022Ssam tracing = 0; 819022Ssam } 829022Ssam 839022Ssam trace(ifd, who, p, len, m) 849022Ssam register struct ifdebug *ifd; 859022Ssam struct sockaddr *who; 869022Ssam char *p; 879022Ssam int len, m; 889022Ssam { 899022Ssam register struct iftrace *t; 909022Ssam 919022Ssam if (ifd->ifd_records == 0) 929022Ssam return; 939022Ssam t = ifd->ifd_front++; 949022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 959022Ssam ifd->ifd_front = ifd->ifd_records; 9616314Skarels if (ifd->ifd_count < NRECORDS) 9716314Skarels ifd->ifd_count++; 9826960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 999022Ssam free(t->ift_packet); 10026960Skarels t->ift_packet = 0; 10126960Skarels } 1029022Ssam t->ift_stamp = time(0); 1039022Ssam t->ift_who = *who; 10426960Skarels if (len > 0 && t->ift_packet == 0) { 1059022Ssam t->ift_packet = malloc(len); 10626960Skarels if (t->ift_packet == 0) 1079022Ssam len = 0; 1089022Ssam } 10926960Skarels if (len > 0) 11026960Skarels bcopy(p, t->ift_packet, len); 1119022Ssam t->ift_size = len; 1129022Ssam t->ift_metric = m; 1139022Ssam } 1149022Ssam 1159022Ssam traceaction(fd, action, rt) 1169022Ssam FILE *fd; 1179022Ssam char *action; 1189022Ssam struct rt_entry *rt; 1199022Ssam { 1209022Ssam struct sockaddr_in *dst, *gate; 1219022Ssam static struct bits { 1229022Ssam int t_bits; 1239022Ssam char *t_name; 1249022Ssam } flagbits[] = { 1259022Ssam { RTF_UP, "UP" }, 1269022Ssam { RTF_GATEWAY, "GATEWAY" }, 1279022Ssam { RTF_HOST, "HOST" }, 1289022Ssam { 0 } 1299022Ssam }, statebits[] = { 1309022Ssam { RTS_PASSIVE, "PASSIVE" }, 1319022Ssam { RTS_REMOTE, "REMOTE" }, 1329022Ssam { RTS_INTERFACE,"INTERFACE" }, 1339022Ssam { RTS_CHANGED, "CHANGED" }, 134*28906Skarels { RTS_INTERNAL, "INTERNAL" }, 135*28906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 136*28906Skarels { RTS_SUBNET, "SUBNET" }, 1379022Ssam { 0 } 1389022Ssam }; 1399022Ssam register struct bits *p; 1409022Ssam register int first; 1419022Ssam char *cp; 1429022Ssam struct interface *ifp; 1439022Ssam 1449022Ssam if (fd == NULL) 1459022Ssam return; 1469022Ssam fprintf(fd, "%s ", action); 1479022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 1489022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 14915099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 15015099Ssam fprintf(fd, "router %s, metric %d, flags", 15115099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 1529022Ssam cp = " %s"; 1539022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 1549022Ssam if ((rt->rt_flags & p->t_bits) == 0) 1559022Ssam continue; 1569022Ssam fprintf(fd, cp, p->t_name); 1579022Ssam if (first) { 1589022Ssam cp = "|%s"; 1599022Ssam first = 0; 1609022Ssam } 1619022Ssam } 1629022Ssam fprintf(fd, " state"); 1639022Ssam cp = " %s"; 1649022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 1659022Ssam if ((rt->rt_state & p->t_bits) == 0) 1669022Ssam continue; 1679022Ssam fprintf(fd, cp, p->t_name); 1689022Ssam if (first) { 1699022Ssam cp = "|%s"; 1709022Ssam first = 0; 1719022Ssam } 1729022Ssam } 1739022Ssam putc('\n', fd); 17416128Skarels if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 1759022Ssam dumpif(fd, rt->rt_ifp); 1769022Ssam fflush(fd); 1779022Ssam } 1789022Ssam 1799022Ssam dumpif(fd, ifp) 1809022Ssam register struct interface *ifp; 1819022Ssam { 18216314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 18316314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 18416314Skarels ifp->int_name); 18516314Skarels dumptrace(fd, "to", &ifp->int_output); 18616314Skarels dumptrace(fd, "from", &ifp->int_input); 18716314Skarels fprintf(fd, "*** end packet history ***\n"); 18816314Skarels } 18926960Skarels fflush(fd); 1909022Ssam } 1919022Ssam 1929022Ssam dumptrace(fd, dir, ifd) 1939022Ssam FILE *fd; 1949022Ssam char *dir; 1959022Ssam register struct ifdebug *ifd; 1969022Ssam { 1979022Ssam register struct iftrace *t; 1989022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 1999022Ssam 2009022Ssam if (ifd->ifd_front == ifd->ifd_records && 2019022Ssam ifd->ifd_front->ift_size == 0) { 2029022Ssam fprintf(fd, "%s: no packets.\n", cp); 20326960Skarels fflush(fd); 2049022Ssam return; 2059022Ssam } 2069022Ssam fprintf(fd, "%s trace:\n", cp); 20716314Skarels t = ifd->ifd_front - ifd->ifd_count; 20816314Skarels if (t < ifd->ifd_records) 20916314Skarels t += NRECORDS; 21016314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 21116314Skarels if (t >= ifd->ifd_records + NRECORDS) 21216314Skarels t = ifd->ifd_records; 2139022Ssam if (t->ift_size == 0) 2149022Ssam continue; 2159022Ssam fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 2169022Ssam t->ift_metric); 2179022Ssam dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 2189022Ssam } 2199022Ssam } 2209022Ssam 2219022Ssam dumppacket(fd, dir, who, cp, size) 2229022Ssam FILE *fd; 2239022Ssam struct sockaddr_in *who; /* should be sockaddr */ 2249022Ssam char *dir, *cp; 2259022Ssam register int size; 2269022Ssam { 2279022Ssam register struct rip *msg = (struct rip *)cp; 2289022Ssam register struct netinfo *n; 2299022Ssam 2309022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 23115099Ssam fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], 23215099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2339022Ssam else { 2349022Ssam fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd, 23515099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2369022Ssam fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 23726960Skarels fflush(fd); 2389022Ssam return; 2399022Ssam } 2409022Ssam switch (msg->rip_cmd) { 2419022Ssam 2429022Ssam case RIPCMD_REQUEST: 2439022Ssam case RIPCMD_RESPONSE: 2449022Ssam fprintf(fd, ":\n"); 2459022Ssam size -= 4 * sizeof (char); 2469022Ssam n = msg->rip_nets; 2479022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 2489022Ssam if (size < sizeof (struct netinfo)) 2499022Ssam break; 25015099Ssam fprintf(fd, "\tdst %s metric %d\n", 25115099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 25215099Ssam inet_ntoa(satosin(n->rip_dst)->sin_addr), 25315099Ssam ntohl(n->rip_metric)); 2549022Ssam } 2559022Ssam break; 2569022Ssam 2579022Ssam case RIPCMD_TRACEON: 2589022Ssam fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile); 2599022Ssam break; 2609022Ssam 2619022Ssam case RIPCMD_TRACEOFF: 2629022Ssam fprintf(fd, "\n"); 2639022Ssam break; 2649022Ssam } 26526960Skarels fflush(fd); 2669022Ssam } 267