19022Ssam #ifndef lint 2*16314Skarels static char sccsid[] = "@(#)trace.c 4.6 (Berkeley) 04/09/84"; 39022Ssam #endif 49022Ssam 59022Ssam /* 69022Ssam * Routing Table Management Daemon 79022Ssam */ 89022Ssam #define RIPCMDS 910245Ssam #include "defs.h" 109022Ssam 119022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 129022Ssam #ifdef DEBUG 139022Ssam FILE *ftrace = stdout; 149022Ssam int tracing = 1; 159022Ssam #endif 169022Ssam 179022Ssam traceinit(ifp) 189022Ssam register struct interface *ifp; 199022Ssam { 209022Ssam 219022Ssam if (iftraceinit(ifp, &ifp->int_input) && 229022Ssam iftraceinit(ifp, &ifp->int_output)) 239022Ssam return; 249022Ssam tracing = 0; 259022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 269022Ssam } 279022Ssam 289022Ssam static 299022Ssam iftraceinit(ifp, ifd) 309022Ssam struct interface *ifp; 319022Ssam register struct ifdebug *ifd; 329022Ssam { 339022Ssam register struct iftrace *t; 349022Ssam 359022Ssam ifd->ifd_records = 369022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 379022Ssam if (ifd->ifd_records == 0) 389022Ssam return (0); 399022Ssam ifd->ifd_front = ifd->ifd_records; 40*16314Skarels ifd->ifd_count = 0; 419022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 429022Ssam t->ift_size = 0; 439022Ssam t->ift_packet = 0; 449022Ssam } 459022Ssam ifd->ifd_if = ifp; 469022Ssam return (1); 479022Ssam } 489022Ssam 499022Ssam traceon(file) 509022Ssam char *file; 519022Ssam { 529022Ssam 539022Ssam if (ftrace != NULL) 549022Ssam return; 559022Ssam ftrace = fopen(file, "a"); 569022Ssam if (ftrace == NULL) 579022Ssam return; 589022Ssam dup2(fileno(ftrace), 1); 599022Ssam dup2(fileno(ftrace), 2); 609022Ssam tracing = 1; 619022Ssam } 629022Ssam 639022Ssam traceoff() 649022Ssam { 659022Ssam if (!tracing) 669022Ssam return; 679022Ssam if (ftrace != NULL) 689022Ssam fclose(ftrace); 699022Ssam ftrace = NULL; 709022Ssam tracing = 0; 719022Ssam } 729022Ssam 739022Ssam trace(ifd, who, p, len, m) 749022Ssam register struct ifdebug *ifd; 759022Ssam struct sockaddr *who; 769022Ssam char *p; 779022Ssam int len, m; 789022Ssam { 799022Ssam register struct iftrace *t; 809022Ssam 819022Ssam if (ifd->ifd_records == 0) 829022Ssam return; 839022Ssam t = ifd->ifd_front++; 849022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 859022Ssam ifd->ifd_front = ifd->ifd_records; 86*16314Skarels if (ifd->ifd_count < NRECORDS) 87*16314Skarels ifd->ifd_count++; 889022Ssam if (t->ift_size > 0 && t->ift_packet) 899022Ssam free(t->ift_packet); 909022Ssam t->ift_packet = 0; 919022Ssam t->ift_stamp = time(0); 929022Ssam t->ift_who = *who; 939022Ssam if (len > 0) { 949022Ssam t->ift_packet = malloc(len); 959022Ssam if (t->ift_packet) 969022Ssam bcopy(p, t->ift_packet, len); 979022Ssam else 989022Ssam len = 0; 999022Ssam } 1009022Ssam t->ift_size = len; 1019022Ssam t->ift_metric = m; 1029022Ssam } 1039022Ssam 1049022Ssam traceaction(fd, action, rt) 1059022Ssam FILE *fd; 1069022Ssam char *action; 1079022Ssam struct rt_entry *rt; 1089022Ssam { 1099022Ssam struct sockaddr_in *dst, *gate; 1109022Ssam static struct bits { 1119022Ssam int t_bits; 1129022Ssam char *t_name; 1139022Ssam } flagbits[] = { 1149022Ssam { RTF_UP, "UP" }, 1159022Ssam { RTF_GATEWAY, "GATEWAY" }, 1169022Ssam { RTF_HOST, "HOST" }, 1179022Ssam { 0 } 1189022Ssam }, statebits[] = { 1199022Ssam { RTS_PASSIVE, "PASSIVE" }, 1209022Ssam { RTS_REMOTE, "REMOTE" }, 1219022Ssam { RTS_INTERFACE,"INTERFACE" }, 1229022Ssam { RTS_CHANGED, "CHANGED" }, 1239022Ssam { 0 } 1249022Ssam }; 1259022Ssam register struct bits *p; 1269022Ssam register int first; 1279022Ssam char *cp; 1289022Ssam struct interface *ifp; 1299022Ssam 1309022Ssam if (fd == NULL) 1319022Ssam return; 1329022Ssam fprintf(fd, "%s ", action); 1339022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 1349022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 13515099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 13615099Ssam fprintf(fd, "router %s, metric %d, flags", 13715099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 1389022Ssam cp = " %s"; 1399022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 1409022Ssam if ((rt->rt_flags & p->t_bits) == 0) 1419022Ssam continue; 1429022Ssam fprintf(fd, cp, p->t_name); 1439022Ssam if (first) { 1449022Ssam cp = "|%s"; 1459022Ssam first = 0; 1469022Ssam } 1479022Ssam } 1489022Ssam fprintf(fd, " state"); 1499022Ssam cp = " %s"; 1509022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 1519022Ssam if ((rt->rt_state & p->t_bits) == 0) 1529022Ssam continue; 1539022Ssam fprintf(fd, cp, p->t_name); 1549022Ssam if (first) { 1559022Ssam cp = "|%s"; 1569022Ssam first = 0; 1579022Ssam } 1589022Ssam } 1599022Ssam putc('\n', fd); 16016128Skarels if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 1619022Ssam dumpif(fd, rt->rt_ifp); 1629022Ssam fflush(fd); 1639022Ssam } 1649022Ssam 1659022Ssam dumpif(fd, ifp) 1669022Ssam register struct interface *ifp; 1679022Ssam { 168*16314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 169*16314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 170*16314Skarels ifp->int_name); 171*16314Skarels dumptrace(fd, "to", &ifp->int_output); 172*16314Skarels dumptrace(fd, "from", &ifp->int_input); 173*16314Skarels fprintf(fd, "*** end packet history ***\n"); 174*16314Skarels } 1759022Ssam } 1769022Ssam 1779022Ssam dumptrace(fd, dir, ifd) 1789022Ssam FILE *fd; 1799022Ssam char *dir; 1809022Ssam register struct ifdebug *ifd; 1819022Ssam { 1829022Ssam register struct iftrace *t; 1839022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 1849022Ssam 1859022Ssam if (ifd->ifd_front == ifd->ifd_records && 1869022Ssam ifd->ifd_front->ift_size == 0) { 1879022Ssam fprintf(fd, "%s: no packets.\n", cp); 1889022Ssam return; 1899022Ssam } 1909022Ssam fprintf(fd, "%s trace:\n", cp); 191*16314Skarels t = ifd->ifd_front - ifd->ifd_count; 192*16314Skarels if (t < ifd->ifd_records) 193*16314Skarels t += NRECORDS; 194*16314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 195*16314Skarels if (t >= ifd->ifd_records + NRECORDS) 196*16314Skarels t = ifd->ifd_records; 1979022Ssam if (t->ift_size == 0) 1989022Ssam continue; 1999022Ssam fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 2009022Ssam t->ift_metric); 2019022Ssam dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 2029022Ssam } 2039022Ssam } 2049022Ssam 2059022Ssam dumppacket(fd, dir, who, cp, size) 2069022Ssam FILE *fd; 2079022Ssam struct sockaddr_in *who; /* should be sockaddr */ 2089022Ssam char *dir, *cp; 2099022Ssam register int size; 2109022Ssam { 2119022Ssam register struct rip *msg = (struct rip *)cp; 2129022Ssam register struct netinfo *n; 2139022Ssam 2149022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 21515099Ssam fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], 21615099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2179022Ssam else { 2189022Ssam fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd, 21915099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2209022Ssam fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 2219022Ssam return; 2229022Ssam } 2239022Ssam switch (msg->rip_cmd) { 2249022Ssam 2259022Ssam case RIPCMD_REQUEST: 2269022Ssam case RIPCMD_RESPONSE: 2279022Ssam fprintf(fd, ":\n"); 2289022Ssam size -= 4 * sizeof (char); 2299022Ssam n = msg->rip_nets; 2309022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 2319022Ssam if (size < sizeof (struct netinfo)) 2329022Ssam break; 23315099Ssam fprintf(fd, "\tdst %s metric %d\n", 23415099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 23515099Ssam inet_ntoa(satosin(n->rip_dst)->sin_addr), 23615099Ssam ntohl(n->rip_metric)); 2379022Ssam } 2389022Ssam break; 2399022Ssam 2409022Ssam case RIPCMD_TRACEON: 2419022Ssam fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile); 2429022Ssam break; 2439022Ssam 2449022Ssam case RIPCMD_TRACEOFF: 2459022Ssam fprintf(fd, "\n"); 2469022Ssam break; 2479022Ssam } 2489022Ssam } 249