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 634771Sbostic * provided that the above copyright notice and this paragraph are 734771Sbostic * duplicated in all such forms and that any documentation, 834771Sbostic * advertising materials, and other materials related to such 934771Sbostic * distribution and use acknowledge that the software was developed 1034771Sbostic * by the University of California, Berkeley. The name of the 1134771Sbostic * University may not be used to endorse or promote products derived 1234771Sbostic * from this software without specific prior written permission. 1334771Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434771Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534771Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1622001Sdist */ 1722001Sdist 189022Ssam #ifndef lint 19*36831Skarels static char sccsid[] = "@(#)trace.c 5.8 (Berkeley) 02/18/89"; 2033489Sbostic #endif /* not lint */ 219022Ssam 229022Ssam /* 239022Ssam * Routing Table Management Daemon 249022Ssam */ 259022Ssam #define RIPCMDS 2610245Ssam #include "defs.h" 2734571Skarels #include <sys/file.h> 2828906Skarels #include <sys/stat.h> 2934564Skarels #include <sys/signal.h> 309022Ssam 319022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 329022Ssam #ifdef DEBUG 339022Ssam FILE *ftrace = stdout; 34*36831Skarels int traceactions = 0; 359022Ssam #endif 36*36831Skarels static struct timeval lastlog; 37*36831Skarels static char *savetracename; 389022Ssam 399022Ssam traceinit(ifp) 409022Ssam register struct interface *ifp; 419022Ssam { 429022Ssam 439022Ssam if (iftraceinit(ifp, &ifp->int_input) && 449022Ssam iftraceinit(ifp, &ifp->int_output)) 459022Ssam return; 4634564Skarels tracehistory = 0; 479022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 489022Ssam } 499022Ssam 509022Ssam static 519022Ssam iftraceinit(ifp, ifd) 529022Ssam struct interface *ifp; 539022Ssam register struct ifdebug *ifd; 549022Ssam { 559022Ssam register struct iftrace *t; 569022Ssam 579022Ssam ifd->ifd_records = 589022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 599022Ssam if (ifd->ifd_records == 0) 609022Ssam return (0); 619022Ssam ifd->ifd_front = ifd->ifd_records; 6216314Skarels ifd->ifd_count = 0; 639022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 649022Ssam t->ift_size = 0; 659022Ssam t->ift_packet = 0; 669022Ssam } 679022Ssam ifd->ifd_if = ifp; 689022Ssam return (1); 699022Ssam } 709022Ssam 719022Ssam traceon(file) 729022Ssam char *file; 739022Ssam { 7428906Skarels struct stat stbuf; 759022Ssam 769022Ssam if (ftrace != NULL) 779022Ssam return; 7828906Skarels if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 7928906Skarels return; 80*36831Skarels savetracename = file; 81*36831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 829022Ssam ftrace = fopen(file, "a"); 839022Ssam if (ftrace == NULL) 849022Ssam return; 859022Ssam dup2(fileno(ftrace), 1); 869022Ssam dup2(fileno(ftrace), 2); 8734564Skarels traceactions = 1; 88*36831Skarels fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec)); 899022Ssam } 909022Ssam 919022Ssam traceoff() 929022Ssam { 9334564Skarels if (!traceactions) 949022Ssam return; 9534571Skarels if (ftrace != NULL) { 9634571Skarels int fd = open("/dev/null", O_RDWR); 9734571Skarels 98*36831Skarels fprintf(ftrace, "Tracing disabled %s\n", 99*36831Skarels ctime((time_t *)&now.tv_sec)); 100*36831Skarels fflush(ftrace); 10134571Skarels (void) dup2(fd, 1); 10234571Skarels (void) dup2(fd, 2); 10334571Skarels (void) close(fd); 1049022Ssam fclose(ftrace); 10534571Skarels ftrace = NULL; 10634571Skarels } 10734564Skarels traceactions = 0; 10834564Skarels tracehistory = 0; 109*36831Skarels tracepackets = 0; 110*36831Skarels tracecontents = 0; 1119022Ssam } 1129022Ssam 11334564Skarels sigtrace(s) 11434564Skarels int s; 11534564Skarels { 116*36831Skarels 117*36831Skarels if (s == SIGUSR2) 11834564Skarels traceoff(); 119*36831Skarels else if (ftrace == NULL && savetracename) 120*36831Skarels traceon(savetracename); 121*36831Skarels else 122*36831Skarels bumploglevel(); 123*36831Skarels } 124*36831Skarels 125*36831Skarels /* 126*36831Skarels * Move to next higher level of tracing when -t option processed or 127*36831Skarels * SIGUSR1 is received. Successive levels are: 128*36831Skarels * traceactions 129*36831Skarels * traceactions + tracepackets 130*36831Skarels * traceactions + tracehistory (packets and contents after change) 131*36831Skarels * traceactions + tracepackets + tracecontents 132*36831Skarels */ 133*36831Skarels bumploglevel() 134*36831Skarels { 135*36831Skarels 136*36831Skarels (void) gettimeofday(&now, (struct timezone *)NULL); 137*36831Skarels if (traceactions == 0) { 13834564Skarels traceactions++; 139*36831Skarels if (ftrace) 140*36831Skarels fprintf(ftrace, "Tracing actions started %s\n", 141*36831Skarels ctime((time_t *)&now.tv_sec)); 142*36831Skarels } else if (tracepackets == 0) { 143*36831Skarels tracepackets++; 144*36831Skarels tracehistory = 0; 145*36831Skarels tracecontents = 0; 146*36831Skarels if (ftrace) 147*36831Skarels fprintf(ftrace, "Tracing packets started %s\n", 148*36831Skarels ctime((time_t *)&now.tv_sec)); 149*36831Skarels } else if (tracehistory == 0) { 15034564Skarels tracehistory++; 151*36831Skarels if (ftrace) 152*36831Skarels fprintf(ftrace, "Tracing history started %s\n", 153*36831Skarels ctime((time_t *)&now.tv_sec)); 154*36831Skarels } else { 15534564Skarels tracepackets++; 156*36831Skarels tracecontents++; 15734564Skarels tracehistory = 0; 158*36831Skarels if (ftrace) 159*36831Skarels fprintf(ftrace, "Tracing packet contents started %s\n", 160*36831Skarels ctime((time_t *)&now.tv_sec)); 16134564Skarels } 162*36831Skarels if (ftrace) 163*36831Skarels fflush(ftrace); 16434564Skarels } 16534564Skarels 1669022Ssam trace(ifd, who, p, len, m) 1679022Ssam register struct ifdebug *ifd; 1689022Ssam struct sockaddr *who; 1699022Ssam char *p; 1709022Ssam int len, m; 1719022Ssam { 1729022Ssam register struct iftrace *t; 1739022Ssam 1749022Ssam if (ifd->ifd_records == 0) 1759022Ssam return; 1769022Ssam t = ifd->ifd_front++; 1779022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 1789022Ssam ifd->ifd_front = ifd->ifd_records; 17916314Skarels if (ifd->ifd_count < NRECORDS) 18016314Skarels ifd->ifd_count++; 18126960Skarels if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 1829022Ssam free(t->ift_packet); 18326960Skarels t->ift_packet = 0; 18426960Skarels } 185*36831Skarels t->ift_stamp = now; 1869022Ssam t->ift_who = *who; 18726960Skarels if (len > 0 && t->ift_packet == 0) { 1889022Ssam t->ift_packet = malloc(len); 18926960Skarels if (t->ift_packet == 0) 1909022Ssam len = 0; 1919022Ssam } 19226960Skarels if (len > 0) 19326960Skarels bcopy(p, t->ift_packet, len); 1949022Ssam t->ift_size = len; 1959022Ssam t->ift_metric = m; 1969022Ssam } 1979022Ssam 1989022Ssam traceaction(fd, action, rt) 1999022Ssam FILE *fd; 2009022Ssam char *action; 2019022Ssam struct rt_entry *rt; 2029022Ssam { 2039022Ssam struct sockaddr_in *dst, *gate; 2049022Ssam static struct bits { 2059022Ssam int t_bits; 2069022Ssam char *t_name; 2079022Ssam } flagbits[] = { 2089022Ssam { RTF_UP, "UP" }, 2099022Ssam { RTF_GATEWAY, "GATEWAY" }, 2109022Ssam { RTF_HOST, "HOST" }, 2119022Ssam { 0 } 2129022Ssam }, statebits[] = { 2139022Ssam { RTS_PASSIVE, "PASSIVE" }, 2149022Ssam { RTS_REMOTE, "REMOTE" }, 2159022Ssam { RTS_INTERFACE,"INTERFACE" }, 2169022Ssam { RTS_CHANGED, "CHANGED" }, 21728906Skarels { RTS_INTERNAL, "INTERNAL" }, 21828906Skarels { RTS_EXTERNAL, "EXTERNAL" }, 21928906Skarels { RTS_SUBNET, "SUBNET" }, 2209022Ssam { 0 } 2219022Ssam }; 2229022Ssam register struct bits *p; 2239022Ssam register int first; 2249022Ssam char *cp; 2259022Ssam struct interface *ifp; 2269022Ssam 2279022Ssam if (fd == NULL) 2289022Ssam return; 229*36831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 230*36831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 231*36831Skarels lastlog = now; 23234564Skarels } 2339022Ssam fprintf(fd, "%s ", action); 2349022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 2359022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 23615099Ssam fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 23715099Ssam fprintf(fd, "router %s, metric %d, flags", 23815099Ssam inet_ntoa(gate->sin_addr), rt->rt_metric); 2399022Ssam cp = " %s"; 2409022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 2419022Ssam if ((rt->rt_flags & p->t_bits) == 0) 2429022Ssam continue; 2439022Ssam fprintf(fd, cp, p->t_name); 2449022Ssam if (first) { 2459022Ssam cp = "|%s"; 2469022Ssam first = 0; 2479022Ssam } 2489022Ssam } 2499022Ssam fprintf(fd, " state"); 2509022Ssam cp = " %s"; 2519022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 2529022Ssam if ((rt->rt_state & p->t_bits) == 0) 2539022Ssam continue; 2549022Ssam fprintf(fd, cp, p->t_name); 2559022Ssam if (first) { 2569022Ssam cp = "|%s"; 2579022Ssam first = 0; 2589022Ssam } 2599022Ssam } 26034564Skarels fprintf(fd, " timer %d\n", rt->rt_timer); 261*36831Skarels if (tracehistory && !tracepackets && 262*36831Skarels (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 2639022Ssam dumpif(fd, rt->rt_ifp); 2649022Ssam fflush(fd); 265*36831Skarels if (ferror(fd)) 266*36831Skarels traceoff(); 2679022Ssam } 2689022Ssam 26934564Skarels tracenewmetric(fd, rt, newmetric) 27034564Skarels FILE *fd; 27134564Skarels struct rt_entry *rt; 27234564Skarels int newmetric; 27334564Skarels { 27434564Skarels struct sockaddr_in *dst, *gate; 27534564Skarels 27634564Skarels if (fd == NULL) 27734564Skarels return; 278*36831Skarels if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { 279*36831Skarels fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); 280*36831Skarels lastlog = now; 281*36831Skarels } 28234564Skarels dst = (struct sockaddr_in *)&rt->rt_dst; 28334564Skarels gate = (struct sockaddr_in *)&rt->rt_router; 28434564Skarels fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 28534564Skarels fprintf(fd, "router %s, from %d to %d\n", 28634564Skarels inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 28734564Skarels fflush(fd); 288*36831Skarels if (ferror(fd)) 289*36831Skarels traceoff(); 29034564Skarels } 29134564Skarels 2929022Ssam dumpif(fd, ifp) 293*36831Skarels FILE *fd; 2949022Ssam register struct interface *ifp; 2959022Ssam { 29616314Skarels if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 29716314Skarels fprintf(fd, "*** Packet history for interface %s ***\n", 29816314Skarels ifp->int_name); 29934564Skarels #ifdef notneeded 30016314Skarels dumptrace(fd, "to", &ifp->int_output); 30134564Skarels #endif 30216314Skarels dumptrace(fd, "from", &ifp->int_input); 30316314Skarels fprintf(fd, "*** end packet history ***\n"); 30416314Skarels } 3059022Ssam } 3069022Ssam 3079022Ssam dumptrace(fd, dir, ifd) 3089022Ssam FILE *fd; 3099022Ssam char *dir; 3109022Ssam register struct ifdebug *ifd; 3119022Ssam { 3129022Ssam register struct iftrace *t; 3139022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 3149022Ssam 3159022Ssam if (ifd->ifd_front == ifd->ifd_records && 3169022Ssam ifd->ifd_front->ift_size == 0) { 3179022Ssam fprintf(fd, "%s: no packets.\n", cp); 31826960Skarels fflush(fd); 3199022Ssam return; 3209022Ssam } 3219022Ssam fprintf(fd, "%s trace:\n", cp); 32216314Skarels t = ifd->ifd_front - ifd->ifd_count; 32316314Skarels if (t < ifd->ifd_records) 32416314Skarels t += NRECORDS; 32516314Skarels for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 32616314Skarels if (t >= ifd->ifd_records + NRECORDS) 32716314Skarels t = ifd->ifd_records; 3289022Ssam if (t->ift_size == 0) 3299022Ssam continue; 33034564Skarels dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 33134564Skarels &t->ift_stamp); 3329022Ssam } 3339022Ssam } 3349022Ssam 335*36831Skarels dumppacket(fd, dir, who, cp, size, stamp) 3369022Ssam FILE *fd; 3379022Ssam struct sockaddr_in *who; /* should be sockaddr */ 3389022Ssam char *dir, *cp; 3399022Ssam register int size; 340*36831Skarels struct timeval *stamp; 3419022Ssam { 3429022Ssam register struct rip *msg = (struct rip *)cp; 3439022Ssam register struct netinfo *n; 3449022Ssam 345*36831Skarels if (fd == NULL) 346*36831Skarels return; 3479022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 348*36831Skarels fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd], 349*36831Skarels dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 350*36831Skarels ctime((time_t *)&stamp->tv_sec)); 351*36831Skarels else { 352*36831Skarels fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd, 35315099Ssam dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 354*36831Skarels fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet, 355*36831Skarels ctime((time_t *)&stamp->tv_sec)); 35626960Skarels fflush(fd); 3579022Ssam return; 3589022Ssam } 359*36831Skarels if (tracepackets && tracecontents == 0) { 360*36831Skarels fflush(fd); 361*36831Skarels return; 362*36831Skarels } 3639022Ssam switch (msg->rip_cmd) { 3649022Ssam 3659022Ssam case RIPCMD_REQUEST: 3669022Ssam case RIPCMD_RESPONSE: 3679022Ssam size -= 4 * sizeof (char); 3689022Ssam n = msg->rip_nets; 3699022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 370*36831Skarels if (size < sizeof (struct netinfo)) { 371*36831Skarels fprintf(fd, "(truncated record, len %d)\n", 372*36831Skarels size); 3739022Ssam break; 374*36831Skarels } 375*36831Skarels if (sizeof(n->rip_dst.sa_family) > 1) 376*36831Skarels n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); 377*36831Skarels 378*36831Skarels switch ((int)n->rip_dst.sa_family) { 379*36831Skarels 380*36831Skarels case AF_INET: 381*36831Skarels fprintf(fd, "\tdst %s metric %d\n", 38215099Ssam #define satosin(sa) ((struct sockaddr_in *)&sa) 383*36831Skarels inet_ntoa(satosin(n->rip_dst)->sin_addr), 384*36831Skarels ntohl(n->rip_metric)); 385*36831Skarels break; 386*36831Skarels 387*36831Skarels default: 388*36831Skarels fprintf(fd, "\taf %d? metric %d\n", 389*36831Skarels n->rip_dst.sa_family, 390*36831Skarels ntohl(n->rip_metric)); 391*36831Skarels break; 392*36831Skarels } 3939022Ssam } 3949022Ssam break; 3959022Ssam 3969022Ssam case RIPCMD_TRACEON: 39734564Skarels fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 3989022Ssam break; 3999022Ssam 4009022Ssam case RIPCMD_TRACEOFF: 4019022Ssam break; 4029022Ssam } 40326960Skarels fflush(fd); 404*36831Skarels if (ferror(fd)) 405*36831Skarels traceoff(); 4069022Ssam } 407