/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)trace.c 5.3 (Berkeley) 5/30/86"; #endif not lint /* * Routing Table Management Daemon */ #define RIPCMDS #include "defs.h" #include #define NRECORDS 50 /* size of circular trace buffer */ #ifdef DEBUG FILE *ftrace = stdout; int tracing = 1; #endif traceinit(ifp) register struct interface *ifp; { if (iftraceinit(ifp, &ifp->int_input) && iftraceinit(ifp, &ifp->int_output)) return; tracing = 0; fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); } static iftraceinit(ifp, ifd) struct interface *ifp; register struct ifdebug *ifd; { register struct iftrace *t; ifd->ifd_records = (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); if (ifd->ifd_records == 0) return (0); ifd->ifd_front = ifd->ifd_records; ifd->ifd_count = 0; for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { t->ift_size = 0; t->ift_packet = 0; } ifd->ifd_if = ifp; return (1); } traceon(file) char *file; { struct stat stbuf; if (ftrace != NULL) return; if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) return; ftrace = fopen(file, "a"); if (ftrace == NULL) return; dup2(fileno(ftrace), 1); dup2(fileno(ftrace), 2); tracing = 1; } traceoff() { if (!tracing) return; if (ftrace != NULL) fclose(ftrace); ftrace = NULL; tracing = 0; } trace(ifd, who, p, len, m) register struct ifdebug *ifd; struct sockaddr *who; char *p; int len, m; { register struct iftrace *t; if (ifd->ifd_records == 0) return; t = ifd->ifd_front++; if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) ifd->ifd_front = ifd->ifd_records; if (ifd->ifd_count < NRECORDS) ifd->ifd_count++; if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { free(t->ift_packet); t->ift_packet = 0; } t->ift_stamp = time((time_t *)0); t->ift_who = *who; if (len > 0 && t->ift_packet == 0) { t->ift_packet = malloc(len); if (t->ift_packet == 0) len = 0; } if (len > 0) bcopy(p, t->ift_packet, len); t->ift_size = len; t->ift_metric = m; } traceaction(fd, action, rt) FILE *fd; char *action; struct rt_entry *rt; { struct sockaddr_in *dst, *gate; static struct bits { int t_bits; char *t_name; } flagbits[] = { { RTF_UP, "UP" }, { RTF_GATEWAY, "GATEWAY" }, { RTF_HOST, "HOST" }, { 0 } }, statebits[] = { { RTS_PASSIVE, "PASSIVE" }, { RTS_REMOTE, "REMOTE" }, { RTS_INTERFACE,"INTERFACE" }, { RTS_CHANGED, "CHANGED" }, { RTS_INTERNAL, "INTERNAL" }, { RTS_EXTERNAL, "EXTERNAL" }, { RTS_SUBNET, "SUBNET" }, { 0 } }; register struct bits *p; register int first; char *cp; struct interface *ifp; if (fd == NULL) return; fprintf(fd, "%s ", action); dst = (struct sockaddr_in *)&rt->rt_dst; gate = (struct sockaddr_in *)&rt->rt_router; fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); fprintf(fd, "router %s, metric %d, flags", inet_ntoa(gate->sin_addr), rt->rt_metric); cp = " %s"; for (first = 1, p = flagbits; p->t_bits > 0; p++) { if ((rt->rt_flags & p->t_bits) == 0) continue; fprintf(fd, cp, p->t_name); if (first) { cp = "|%s"; first = 0; } } fprintf(fd, " state"); cp = " %s"; for (first = 1, p = statebits; p->t_bits > 0; p++) { if ((rt->rt_state & p->t_bits) == 0) continue; fprintf(fd, cp, p->t_name); if (first) { cp = "|%s"; first = 0; } } putc('\n', fd); if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) dumpif(fd, rt->rt_ifp); fflush(fd); } dumpif(fd, ifp) register struct interface *ifp; { if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { fprintf(fd, "*** Packet history for interface %s ***\n", ifp->int_name); dumptrace(fd, "to", &ifp->int_output); dumptrace(fd, "from", &ifp->int_input); fprintf(fd, "*** end packet history ***\n"); } fflush(fd); } dumptrace(fd, dir, ifd) FILE *fd; char *dir; register struct ifdebug *ifd; { register struct iftrace *t; char *cp = !strcmp(dir, "to") ? "Output" : "Input"; if (ifd->ifd_front == ifd->ifd_records && ifd->ifd_front->ift_size == 0) { fprintf(fd, "%s: no packets.\n", cp); fflush(fd); return; } fprintf(fd, "%s trace:\n", cp); t = ifd->ifd_front - ifd->ifd_count; if (t < ifd->ifd_records) t += NRECORDS; for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { if (t >= ifd->ifd_records + NRECORDS) t = ifd->ifd_records; if (t->ift_size == 0) continue; fprintf(fd, "%.24s: metric=%D\n", ctime(&t->ift_stamp), t->ift_metric); dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); } } dumppacket(fd, dir, who, cp, size) FILE *fd; struct sockaddr_in *who; /* should be sockaddr */ char *dir, *cp; register int size; { register struct rip *msg = (struct rip *)cp; register struct netinfo *n; if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); else { fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd, dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); fflush(fd); return; } switch (msg->rip_cmd) { case RIPCMD_REQUEST: case RIPCMD_RESPONSE: fprintf(fd, ":\n"); size -= 4 * sizeof (char); n = msg->rip_nets; for (; size > 0; n++, size -= sizeof (struct netinfo)) { if (size < sizeof (struct netinfo)) break; fprintf(fd, "\tdst %s metric %D\n", #define satosin(sa) ((struct sockaddr_in *)&sa) inet_ntoa(satosin(n->rip_dst)->sin_addr), ntohl(n->rip_metric)); } break; case RIPCMD_TRACEON: fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile); break; case RIPCMD_TRACEOFF: fprintf(fd, "\n"); break; } fflush(fd); }