122001Sdist /* 2*34564Skarels * 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*34564Skarels static char sccsid[] = "@(#)trace.c 5.5 (Berkeley) 05/31/88"; 1533489Sbostic #endif /* not lint */ 169022Ssam 179022Ssam /* 189022Ssam * Routing Table Management Daemon 199022Ssam */ 209022Ssam #define RIPCMDS 2110245Ssam #include "defs.h" 2228906Skarels #include <sys/stat.h> 23*34564Skarels #include <sys/signal.h> 249022Ssam 259022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 269022Ssam #ifdef DEBUG 279022Ssam FILE *ftrace = stdout; 28*34564Skarels int traceactions = 1; 299022Ssam #endif 309022Ssam 319022Ssam traceinit(ifp) 329022Ssam register struct interface *ifp; 339022Ssam { 349022Ssam 359022Ssam if (iftraceinit(ifp, &ifp->int_input) && 369022Ssam iftraceinit(ifp, &ifp->int_output)) 379022Ssam return; 38*34564Skarels tracehistory = 0; 399022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 409022Ssam } 419022Ssam 429022Ssam static 439022Ssam iftraceinit(ifp, ifd) 449022Ssam struct interface *ifp; 459022Ssam register struct ifdebug *ifd; 469022Ssam { 479022Ssam register struct iftrace *t; 489022Ssam 499022Ssam ifd->ifd_records = 509022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 519022Ssam if (ifd->ifd_records == 0) 529022Ssam return (0); 539022Ssam ifd->ifd_front = ifd->ifd_records; 5416314Skarels ifd->ifd_count = 0; 559022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 569022Ssam t->ift_size = 0; 579022Ssam t->ift_packet = 0; 589022Ssam } 599022Ssam ifd->ifd_if = ifp; 609022Ssam return (1); 619022Ssam } 629022Ssam 639022Ssam traceon(file) 649022Ssam char *file; 659022Ssam { 6628906Skarels struct stat stbuf; 679022Ssam 689022Ssam if (ftrace != NULL) 699022Ssam return; 7028906Skarels if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 7128906Skarels return; 729022Ssam ftrace = fopen(file, "a"); 739022Ssam if (ftrace == NULL) 749022Ssam return; 759022Ssam dup2(fileno(ftrace), 1); 769022Ssam dup2(fileno(ftrace), 2); 77*34564Skarels traceactions = 1; 789022Ssam } 799022Ssam 809022Ssam traceoff() 819022Ssam { 82*34564Skarels if (!traceactions) 839022Ssam return; 849022Ssam if (ftrace != NULL) 859022Ssam fclose(ftrace); 869022Ssam ftrace = NULL; 87*34564Skarels traceactions = 0; 88*34564Skarels tracehistory = 0; 899022Ssam } 909022Ssam 91*34564Skarels sigtrace(s) 92*34564Skarels int s; 93*34564Skarels { 94*34564Skarels if (s == SIGUSR2) { 95*34564Skarels traceoff(); 96*34564Skarels tracepackets = 0; 97*34564Skarels } else if (traceactions == 0) 98*34564Skarels traceactions++; 99*34564Skarels else if (tracehistory == 0) 100*34564Skarels tracehistory++; 101*34564Skarels else { 102*34564Skarels tracepackets++; 103*34564Skarels tracehistory = 0; 104*34564Skarels } 105*34564Skarels } 106*34564Skarels 1079022Ssam trace(ifd, who, p, len, m) 1089022Ssam register struct ifdebug *ifd; 1099022Ssam struct sockaddr *who; 1109022Ssam char *p; 1119022Ssam int len, m; 1129022Ssam { 1139022Ssam register struct iftrace *t; 1149022Ssam 1159022Ssam if (ifd->ifd_records == 0) 1169022Ssam return; 1179022Ssam t = ifd->ifd_front++; 1189022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1199022Ssam ifd->ifd_front = ifd->ifd_records; 12016314Skarels if (ifd->ifd_count < NRECORDS) 12116314Skarels ifd->ifd_count++; 12226960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1239022Ssam free(t->ift_packet); 12426960Skarels t->ift_packet = 0; 12526960Skarels } 1269022Ssam t->ift_stamp = time(0); 1279022Ssam t->ift_who = *who; 12826960Skarels if (len > 0 && t->ift_packet == 0) { 1299022Ssam t->ift_packet = malloc(len); 13026960Skarels if (t->ift_packet == 0) 1319022Ssam len = 0; 1329022Ssam } 13326960Skarels if (len > 0) 13426960Skarels bcopy(p, t->ift_packet, len); 1359022Ssam t->ift_size = len; 1369022Ssam t->ift_metric = m; 1379022Ssam } 1389022Ssam 1399022Ssam traceaction(fd, action, rt) 1409022Ssam FILE *fd; 1419022Ssam char *action; 1429022Ssam struct rt_entry *rt; 1439022Ssam { 1449022Ssam struct sockaddr_in *dst, *gate; 1459022Ssam static struct bits { 1469022Ssam int t_bits; 1479022Ssam char *t_name; 1489022Ssam } flagbits[] = { 1499022Ssam { RTF_UP, "UP" }, 1509022Ssam { RTF_GATEWAY, "GATEWAY" }, 1519022Ssam { RTF_HOST, "HOST" }, 1529022Ssam { 0 } 1539022Ssam }, statebits[] = { 1549022Ssam { RTS_PASSIVE, "PASSIVE" }, 1559022Ssam { RTS_REMOTE, "REMOTE" }, 1569022Ssam { RTS_INTERFACE,"INTERFACE" }, 1579022Ssam { RTS_CHANGED, "CHANGED" }, 15828906Skarels { RTS_INTERNAL, "INTERNAL" }, 15928906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 16028906Skarels { RTS_SUBNET, "SUBNET" }, 1619022Ssam { 0 } 1629022Ssam }; 1639022Ssam register struct bits *p; 1649022Ssam register int first; 1659022Ssam char *cp; 1669022Ssam struct interface *ifp; 1679022Ssam 1689022Ssam if (fd == NULL) 1699022Ssam return; 170*34564Skarels if (curtime) { 171*34564Skarels fprintf(fd, "\n%s", curtime); 172*34564Skarels curtime = NULL; 173*34564Skarels } 1749022Ssam fprintf(fd, "%s ", action); 1759022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 1769022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 17715099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 17815099Ssam fprintf(fd, "router %s, metric %d, flags", 17915099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 1809022Ssam cp = " %s"; 1819022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 1829022Ssam if ((rt->rt_flags & p->t_bits) == 0) 1839022Ssam continue; 1849022Ssam fprintf(fd, cp, p->t_name); 1859022Ssam if (first) { 1869022Ssam cp = "|%s"; 1879022Ssam first = 0; 1889022Ssam } 1899022Ssam } 1909022Ssam fprintf(fd, " state"); 1919022Ssam cp = " %s"; 1929022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 1939022Ssam if ((rt->rt_state & p->t_bits) == 0) 1949022Ssam continue; 1959022Ssam fprintf(fd, cp, p->t_name); 1969022Ssam if (first) { 1979022Ssam cp = "|%s"; 1989022Ssam first = 0; 1999022Ssam } 2009022Ssam } 201*34564Skarels fprintf(fd, " timer %d\n", rt->rt_timer); 20216128Skarels if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 2039022Ssam dumpif(fd, rt->rt_ifp); 2049022Ssam fflush(fd); 2059022Ssam } 2069022Ssam 207*34564Skarels tracenewmetric(fd, rt, newmetric) 208*34564Skarels FILE *fd; 209*34564Skarels struct rt_entry *rt; 210*34564Skarels int newmetric; 211*34564Skarels { 212*34564Skarels struct sockaddr_in *dst, *gate; 213*34564Skarels 214*34564Skarels if (fd == NULL) 215*34564Skarels return; 216*34564Skarels dst = (struct sockaddr_in *)&rt->rt_dst; 217*34564Skarels gate = (struct sockaddr_in *)&rt->rt_router; 218*34564Skarels fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 219*34564Skarels fprintf(fd, "router %s, from %d to %d\n", 220*34564Skarels inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 221*34564Skarels fflush(fd); 222*34564Skarels } 223*34564Skarels 2249022Ssam dumpif(fd, ifp) 2259022Ssam register struct interface *ifp; 2269022Ssam { 22716314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 22816314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 22916314Skarels ifp->int_name); 230*34564Skarels #ifdef notneeded 23116314Skarels dumptrace(fd, "to", &ifp->int_output); 232*34564Skarels #endif 23316314Skarels dumptrace(fd, "from", &ifp->int_input); 23416314Skarels fprintf(fd, "*** end packet history ***\n"); 23516314Skarels } 23626960Skarels fflush(fd); 2379022Ssam } 2389022Ssam 2399022Ssam dumptrace(fd, dir, ifd) 2409022Ssam FILE *fd; 2419022Ssam char *dir; 2429022Ssam register struct ifdebug *ifd; 2439022Ssam { 2449022Ssam register struct iftrace *t; 2459022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 2469022Ssam 2479022Ssam if (ifd->ifd_front == ifd->ifd_records && 2489022Ssam ifd->ifd_front->ift_size == 0) { 2499022Ssam fprintf(fd, "%s: no packets.\n", cp); 25026960Skarels fflush(fd); 2519022Ssam return; 2529022Ssam } 2539022Ssam fprintf(fd, "%s trace:\n", cp); 25416314Skarels t = ifd->ifd_front - ifd->ifd_count; 25516314Skarels if (t < ifd->ifd_records) 25616314Skarels t += NRECORDS; 25716314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 25816314Skarels if (t >= ifd->ifd_records + NRECORDS) 25916314Skarels t = ifd->ifd_records; 2609022Ssam if (t->ift_size == 0) 2619022Ssam continue; 262*34564Skarels dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 263*34564Skarels &t->ift_stamp); 2649022Ssam } 2659022Ssam } 2669022Ssam 267*34564Skarels dumppacket(fd, dir, who, cp, size, tstamp) 2689022Ssam FILE *fd; 2699022Ssam struct sockaddr_in *who; /* should be sockaddr */ 2709022Ssam char *dir, *cp; 2719022Ssam register int size; 272*34564Skarels time_t *tstamp; 2739022Ssam { 2749022Ssam register struct rip *msg = (struct rip *)cp; 2759022Ssam register struct netinfo *n; 2769022Ssam 2779022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 27815099Ssam fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], 27915099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 2809022Ssam else { 281*34564Skarels fprintf(fd, "Bad cmd 0x%x %s %x.%d %.24s\n", msg->rip_cmd, 282*34564Skarels dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 283*34564Skarels ctime(tstamp)); 2849022Ssam fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 28526960Skarels fflush(fd); 2869022Ssam return; 2879022Ssam } 288*34564Skarels fprintf(fd, " %.24s:\n", ctime(tstamp)); 2899022Ssam switch (msg->rip_cmd) { 2909022Ssam 2919022Ssam case RIPCMD_REQUEST: 2929022Ssam case RIPCMD_RESPONSE: 2939022Ssam size -= 4 * sizeof (char); 2949022Ssam n = msg->rip_nets; 2959022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 2969022Ssam if (size < sizeof (struct netinfo)) 2979022Ssam break; 29815099Ssam fprintf(fd, "\tdst %s metric %d\n", 29915099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 30015099Ssam inet_ntoa(satosin(n->rip_dst)->sin_addr), 30115099Ssam ntohl(n->rip_metric)); 3029022Ssam } 3039022Ssam break; 3049022Ssam 3059022Ssam case RIPCMD_TRACEON: 306*34564Skarels fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 3079022Ssam break; 3089022Ssam 3099022Ssam case RIPCMD_TRACEOFF: 3109022Ssam break; 3119022Ssam } 31226960Skarels fflush(fd); 3139022Ssam } 314