122001Sdist /* 222001Sdist * Copyright (c) 1983 Regents of the University of California. 3*33489Sbostic * All rights reserved. 4*33489Sbostic * 5*33489Sbostic * Redistribution and use in source and binary forms are permitted 6*33489Sbostic * provided that this notice is preserved and that due credit is given 7*33489Sbostic * to the University of California at Berkeley. The name of the University 8*33489Sbostic * may not be used to endorse or promote products derived from this 9*33489Sbostic * software without specific prior written permission. This software 10*33489Sbostic * is provided ``as is'' without express or implied warranty. 1122001Sdist */ 1222001Sdist 139022Ssam #ifndef lint 14*33489Sbostic static char sccsid[] = "@(#)trace.c 5.4 (Berkeley) 02/16/88"; 15*33489Sbostic #endif /* not lint */ 169022Ssam 179022Ssam /* 189022Ssam * Routing Table Management Daemon 199022Ssam */ 209022Ssam #define RIPCMDS 2110245Ssam #include "defs.h" 2228906Skarels #include <sys/stat.h> 239022Ssam 249022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 259022Ssam #ifdef DEBUG 269022Ssam FILE *ftrace = stdout; 279022Ssam int tracing = 1; 289022Ssam #endif 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; 379022Ssam tracing = 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; 719022Ssam ftrace = fopen(file, "a"); 729022Ssam if (ftrace == NULL) 739022Ssam return; 749022Ssam dup2(fileno(ftrace), 1); 759022Ssam dup2(fileno(ftrace), 2); 769022Ssam tracing = 1; 779022Ssam } 789022Ssam 799022Ssam traceoff() 809022Ssam { 819022Ssam if (!tracing) 829022Ssam return; 839022Ssam if (ftrace != NULL) 849022Ssam fclose(ftrace); 859022Ssam ftrace = NULL; 869022Ssam tracing = 0; 879022Ssam } 889022Ssam 899022Ssam trace(ifd, who, p, len, m) 909022Ssam register struct ifdebug *ifd; 919022Ssam struct sockaddr *who; 929022Ssam char *p; 939022Ssam int len, m; 949022Ssam { 959022Ssam register struct iftrace *t; 969022Ssam 979022Ssam if (ifd->ifd_records == 0) 989022Ssam return; 999022Ssam t = ifd->ifd_front++; 1009022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1019022Ssam ifd->ifd_front = ifd->ifd_records; 10216314Skarels if (ifd->ifd_count < NRECORDS) 10316314Skarels ifd->ifd_count++; 10426960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1059022Ssam free(t->ift_packet); 10626960Skarels t->ift_packet = 0; 10726960Skarels } 1089022Ssam t->ift_stamp = time(0); 1099022Ssam t->ift_who = *who; 11026960Skarels if (len > 0 && t->ift_packet == 0) { 1119022Ssam t->ift_packet = malloc(len); 11226960Skarels if (t->ift_packet == 0) 1139022Ssam len = 0; 1149022Ssam } 11526960Skarels if (len > 0) 11626960Skarels bcopy(p, t->ift_packet, len); 1179022Ssam t->ift_size = len; 1189022Ssam t->ift_metric = m; 1199022Ssam } 1209022Ssam 1219022Ssam traceaction(fd, action, rt) 1229022Ssam FILE *fd; 1239022Ssam char *action; 1249022Ssam struct rt_entry *rt; 1259022Ssam { 1269022Ssam struct sockaddr_in *dst, *gate; 1279022Ssam static struct bits { 1289022Ssam int t_bits; 1299022Ssam char *t_name; 1309022Ssam } flagbits[] = { 1319022Ssam { RTF_UP, "UP" }, 1329022Ssam { RTF_GATEWAY, "GATEWAY" }, 1339022Ssam { RTF_HOST, "HOST" }, 1349022Ssam { 0 } 1359022Ssam }, statebits[] = { 1369022Ssam { RTS_PASSIVE, "PASSIVE" }, 1379022Ssam { RTS_REMOTE, "REMOTE" }, 1389022Ssam { RTS_INTERFACE,"INTERFACE" }, 1399022Ssam { RTS_CHANGED, "CHANGED" }, 14028906Skarels { RTS_INTERNAL, "INTERNAL" }, 14128906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 14228906Skarels { RTS_SUBNET, "SUBNET" }, 1439022Ssam { 0 } 1449022Ssam }; 1459022Ssam register struct bits *p; 1469022Ssam register int first; 1479022Ssam char *cp; 1489022Ssam struct interface *ifp; 1499022Ssam 1509022Ssam if (fd == NULL) 1519022Ssam return; 1529022Ssam fprintf(fd, "%s ", action); 1539022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 1549022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 15515099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 15615099Ssam fprintf(fd, "router %s, metric %d, flags", 15715099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 1589022Ssam cp = " %s"; 1599022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 1609022Ssam if ((rt->rt_flags & p->t_bits) == 0) 1619022Ssam continue; 1629022Ssam fprintf(fd, cp, p->t_name); 1639022Ssam if (first) { 1649022Ssam cp = "|%s"; 1659022Ssam first = 0; 1669022Ssam } 1679022Ssam } 1689022Ssam fprintf(fd, " state"); 1699022Ssam cp = " %s"; 1709022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 1719022Ssam if ((rt->rt_state & p->t_bits) == 0) 1729022Ssam continue; 1739022Ssam fprintf(fd, cp, p->t_name); 1749022Ssam if (first) { 1759022Ssam cp = "|%s"; 1769022Ssam first = 0; 1779022Ssam } 1789022Ssam } 1799022Ssam putc('\n', fd); 18016128Skarels if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 1819022Ssam dumpif(fd, rt->rt_ifp); 1829022Ssam fflush(fd); 1839022Ssam } 1849022Ssam 1859022Ssam dumpif(fd, ifp) 1869022Ssam register struct interface *ifp; 1879022Ssam { 18816314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 18916314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 19016314Skarels ifp->int_name); 19116314Skarels dumptrace(fd, "to", &ifp->int_output); 19216314Skarels dumptrace(fd, "from", &ifp->int_input); 19316314Skarels fprintf(fd, "*** end packet history ***\n"); 19416314Skarels } 19526960Skarels fflush(fd); 1969022Ssam } 1979022Ssam 1989022Ssam dumptrace(fd, dir, ifd) 1999022Ssam FILE *fd; 2009022Ssam char *dir; 2019022Ssam register struct ifdebug *ifd; 2029022Ssam { 2039022Ssam register struct iftrace *t; 2049022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 2059022Ssam 2069022Ssam if (ifd->ifd_front == ifd->ifd_records && 2079022Ssam ifd->ifd_front->ift_size == 0) { 2089022Ssam fprintf(fd, "%s: no packets.\n", cp); 20926960Skarels fflush(fd); 2109022Ssam return; 2119022Ssam } 2129022Ssam fprintf(fd, "%s trace:\n", cp); 21316314Skarels t = ifd->ifd_front - ifd->ifd_count; 21416314Skarels if (t < ifd->ifd_records) 21516314Skarels t += NRECORDS; 21616314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 21716314Skarels if (t >= ifd->ifd_records + NRECORDS) 21816314Skarels t = ifd->ifd_records; 2199022Ssam if (t->ift_size == 0) 2209022Ssam continue; 2219022Ssam fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 2229022Ssam t->ift_metric); 2239022Ssam dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 2249022Ssam } 2259022Ssam } 2269022Ssam 2279022Ssam dumppacket(fd, dir, who, cp, size) 2289022Ssam FILE *fd; 2299022Ssam struct sockaddr_in *who; /* should be sockaddr */ 2309022Ssam char *dir, *cp; 2319022Ssam register int size; 2329022Ssam { 2339022Ssam register struct rip *msg = (struct rip *)cp; 2349022Ssam register struct netinfo *n; 2359022Ssam 2369022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 23715099Ssam fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], 23815099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2399022Ssam else { 2409022Ssam fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd, 24115099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2429022Ssam fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 24326960Skarels fflush(fd); 2449022Ssam return; 2459022Ssam } 2469022Ssam switch (msg->rip_cmd) { 2479022Ssam 2489022Ssam case RIPCMD_REQUEST: 2499022Ssam case RIPCMD_RESPONSE: 2509022Ssam fprintf(fd, ":\n"); 2519022Ssam size -= 4 * sizeof (char); 2529022Ssam n = msg->rip_nets; 2539022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 2549022Ssam if (size < sizeof (struct netinfo)) 2559022Ssam break; 25615099Ssam fprintf(fd, "\tdst %s metric %d\n", 25715099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 25815099Ssam inet_ntoa(satosin(n->rip_dst)->sin_addr), 25915099Ssam ntohl(n->rip_metric)); 2609022Ssam } 2619022Ssam break; 2629022Ssam 2639022Ssam case RIPCMD_TRACEON: 2649022Ssam fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile); 2659022Ssam break; 2669022Ssam 2679022Ssam case RIPCMD_TRACEOFF: 2689022Ssam fprintf(fd, "\n"); 2699022Ssam break; 2709022Ssam } 27126960Skarels fflush(fd); 2729022Ssam } 273