1*9022Ssam #ifndef lint 2*9022Ssam static char sccsid[] = "@(#)trace.c 4.1 11/02/82"; 3*9022Ssam #endif 4*9022Ssam 5*9022Ssam /* 6*9022Ssam * Routing Table Management Daemon 7*9022Ssam */ 8*9022Ssam #define RIPCMDS 9*9022Ssam #include "router.h" 10*9022Ssam 11*9022Ssam #define NRECORDS 50 /* size of circular trace buffer */ 12*9022Ssam #ifdef DEBUG 13*9022Ssam FILE *ftrace = stdout; 14*9022Ssam int tracing = 1; 15*9022Ssam #endif 16*9022Ssam 17*9022Ssam traceinit(ifp) 18*9022Ssam register struct interface *ifp; 19*9022Ssam { 20*9022Ssam 21*9022Ssam if (iftraceinit(ifp, &ifp->int_input) && 22*9022Ssam iftraceinit(ifp, &ifp->int_output)) 23*9022Ssam return; 24*9022Ssam tracing = 0; 25*9022Ssam fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); 26*9022Ssam } 27*9022Ssam 28*9022Ssam static 29*9022Ssam iftraceinit(ifp, ifd) 30*9022Ssam struct interface *ifp; 31*9022Ssam register struct ifdebug *ifd; 32*9022Ssam { 33*9022Ssam register struct iftrace *t; 34*9022Ssam 35*9022Ssam ifd->ifd_records = 36*9022Ssam (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 37*9022Ssam if (ifd->ifd_records == 0) 38*9022Ssam return (0); 39*9022Ssam ifd->ifd_front = ifd->ifd_records; 40*9022Ssam for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 41*9022Ssam t->ift_size = 0; 42*9022Ssam t->ift_packet = 0; 43*9022Ssam } 44*9022Ssam ifd->ifd_if = ifp; 45*9022Ssam return (1); 46*9022Ssam } 47*9022Ssam 48*9022Ssam traceon(file) 49*9022Ssam char *file; 50*9022Ssam { 51*9022Ssam 52*9022Ssam if (ftrace != NULL) 53*9022Ssam return; 54*9022Ssam ftrace = fopen(file, "a"); 55*9022Ssam if (ftrace == NULL) 56*9022Ssam return; 57*9022Ssam dup2(fileno(ftrace), 1); 58*9022Ssam dup2(fileno(ftrace), 2); 59*9022Ssam tracing = 1; 60*9022Ssam } 61*9022Ssam 62*9022Ssam traceoff() 63*9022Ssam { 64*9022Ssam if (!tracing) 65*9022Ssam return; 66*9022Ssam if (ftrace != NULL) 67*9022Ssam fclose(ftrace); 68*9022Ssam ftrace = NULL; 69*9022Ssam tracing = 0; 70*9022Ssam } 71*9022Ssam 72*9022Ssam trace(ifd, who, p, len, m) 73*9022Ssam register struct ifdebug *ifd; 74*9022Ssam struct sockaddr *who; 75*9022Ssam char *p; 76*9022Ssam int len, m; 77*9022Ssam { 78*9022Ssam register struct iftrace *t; 79*9022Ssam 80*9022Ssam if (ifd->ifd_records == 0) 81*9022Ssam return; 82*9022Ssam t = ifd->ifd_front++; 83*9022Ssam if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 84*9022Ssam ifd->ifd_front = ifd->ifd_records; 85*9022Ssam if (t->ift_size > 0 && t->ift_packet) 86*9022Ssam free(t->ift_packet); 87*9022Ssam t->ift_packet = 0; 88*9022Ssam t->ift_stamp = time(0); 89*9022Ssam t->ift_who = *who; 90*9022Ssam if (len > 0) { 91*9022Ssam t->ift_packet = malloc(len); 92*9022Ssam if (t->ift_packet) 93*9022Ssam bcopy(p, t->ift_packet, len); 94*9022Ssam else 95*9022Ssam len = 0; 96*9022Ssam } 97*9022Ssam t->ift_size = len; 98*9022Ssam t->ift_metric = m; 99*9022Ssam } 100*9022Ssam 101*9022Ssam traceaction(fd, action, rt) 102*9022Ssam FILE *fd; 103*9022Ssam char *action; 104*9022Ssam struct rt_entry *rt; 105*9022Ssam { 106*9022Ssam struct sockaddr_in *dst, *gate; 107*9022Ssam static struct bits { 108*9022Ssam int t_bits; 109*9022Ssam char *t_name; 110*9022Ssam } flagbits[] = { 111*9022Ssam { RTF_UP, "UP" }, 112*9022Ssam { RTF_GATEWAY, "GATEWAY" }, 113*9022Ssam { RTF_HOST, "HOST" }, 114*9022Ssam { 0 } 115*9022Ssam }, statebits[] = { 116*9022Ssam { RTS_PASSIVE, "PASSIVE" }, 117*9022Ssam { RTS_REMOTE, "REMOTE" }, 118*9022Ssam { RTS_INTERFACE,"INTERFACE" }, 119*9022Ssam { RTS_CHANGED, "CHANGED" }, 120*9022Ssam { 0 } 121*9022Ssam }; 122*9022Ssam register struct bits *p; 123*9022Ssam register int first; 124*9022Ssam char *cp; 125*9022Ssam struct interface *ifp; 126*9022Ssam 127*9022Ssam if (fd == NULL) 128*9022Ssam return; 129*9022Ssam fprintf(fd, "%s ", action); 130*9022Ssam dst = (struct sockaddr_in *)&rt->rt_dst; 131*9022Ssam gate = (struct sockaddr_in *)&rt->rt_router; 132*9022Ssam fprintf(fd, "dst %x, router %x, metric %d, flags", dst->sin_addr, 133*9022Ssam gate->sin_addr, rt->rt_metric); 134*9022Ssam cp = " %s"; 135*9022Ssam for (first = 1, p = flagbits; p->t_bits > 0; p++) { 136*9022Ssam if ((rt->rt_flags & p->t_bits) == 0) 137*9022Ssam continue; 138*9022Ssam fprintf(fd, cp, p->t_name); 139*9022Ssam if (first) { 140*9022Ssam cp = "|%s"; 141*9022Ssam first = 0; 142*9022Ssam } 143*9022Ssam } 144*9022Ssam fprintf(fd, " state"); 145*9022Ssam cp = " %s"; 146*9022Ssam for (first = 1, p = statebits; p->t_bits > 0; p++) { 147*9022Ssam if ((rt->rt_state & p->t_bits) == 0) 148*9022Ssam continue; 149*9022Ssam fprintf(fd, cp, p->t_name); 150*9022Ssam if (first) { 151*9022Ssam cp = "|%s"; 152*9022Ssam first = 0; 153*9022Ssam } 154*9022Ssam } 155*9022Ssam putc('\n', fd); 156*9022Ssam if ((rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 157*9022Ssam dumpif(fd, rt->rt_ifp); 158*9022Ssam fflush(fd); 159*9022Ssam } 160*9022Ssam 161*9022Ssam dumpif(fd, ifp) 162*9022Ssam register struct interface *ifp; 163*9022Ssam { 164*9022Ssam register struct ifdebug *ifd; 165*9022Ssam 166*9022Ssam fprintf(fd, "*** Packet history for interface %s ***\n", 167*9022Ssam ifp->int_name); 168*9022Ssam dumptrace(fd, "to", &ifp->int_output); 169*9022Ssam dumptrace(fd, "from", &ifp->int_output); 170*9022Ssam fprintf(fd, "*** end packet history ***\n"); 171*9022Ssam } 172*9022Ssam 173*9022Ssam dumptrace(fd, dir, ifd) 174*9022Ssam FILE *fd; 175*9022Ssam char *dir; 176*9022Ssam register struct ifdebug *ifd; 177*9022Ssam { 178*9022Ssam register struct iftrace *t; 179*9022Ssam char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 180*9022Ssam 181*9022Ssam if (ifd->ifd_front == ifd->ifd_records && 182*9022Ssam ifd->ifd_front->ift_size == 0) { 183*9022Ssam fprintf(fd, "%s: no packets.\n", cp); 184*9022Ssam return; 185*9022Ssam } 186*9022Ssam fprintf(fd, "%s trace:\n", cp); 187*9022Ssam for (t = ifd->ifd_front; t <= ifd->ifd_records + NRECORDS; t++) { 188*9022Ssam if (t->ift_size == 0) 189*9022Ssam continue; 190*9022Ssam fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 191*9022Ssam t->ift_metric); 192*9022Ssam dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 193*9022Ssam } 194*9022Ssam for (t = ifd->ifd_records; t < ifd->ifd_front; t++) { 195*9022Ssam if (t->ift_size == 0) 196*9022Ssam continue; 197*9022Ssam fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 198*9022Ssam t->ift_metric); 199*9022Ssam dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 200*9022Ssam } 201*9022Ssam } 202*9022Ssam 203*9022Ssam dumppacket(fd, dir, who, cp, size) 204*9022Ssam FILE *fd; 205*9022Ssam struct sockaddr_in *who; /* should be sockaddr */ 206*9022Ssam char *dir, *cp; 207*9022Ssam register int size; 208*9022Ssam { 209*9022Ssam register struct rip *msg = (struct rip *)cp; 210*9022Ssam register struct netinfo *n; 211*9022Ssam 212*9022Ssam if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 213*9022Ssam fprintf(fd, "%s %s %x.%d", ripcmds[msg->rip_cmd], 214*9022Ssam dir, who->sin_addr, ntohs(who->sin_port)); 215*9022Ssam else { 216*9022Ssam fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd, 217*9022Ssam dir, who->sin_addr, ntohs(who->sin_port)); 218*9022Ssam fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 219*9022Ssam return; 220*9022Ssam } 221*9022Ssam switch (msg->rip_cmd) { 222*9022Ssam 223*9022Ssam case RIPCMD_REQUEST: 224*9022Ssam case RIPCMD_RESPONSE: 225*9022Ssam fprintf(fd, ":\n"); 226*9022Ssam size -= 4 * sizeof (char); 227*9022Ssam n = msg->rip_nets; 228*9022Ssam for (; size > 0; n++, size -= sizeof (struct netinfo)) { 229*9022Ssam if (size < sizeof (struct netinfo)) 230*9022Ssam break; 231*9022Ssam fprintf(fd, "\tdst %x metric %d\n", 232*9022Ssam ((struct sockaddr_in *)&n->rip_dst)->sin_addr, 233*9022Ssam n->rip_metric); 234*9022Ssam } 235*9022Ssam break; 236*9022Ssam 237*9022Ssam case RIPCMD_TRACEON: 238*9022Ssam fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile); 239*9022Ssam break; 240*9022Ssam 241*9022Ssam case RIPCMD_TRACEOFF: 242*9022Ssam fprintf(fd, "\n"); 243*9022Ssam break; 244*9022Ssam } 245*9022Ssam } 246