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