1: /* 2: * Copyright (c) 1985 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: * Includes material written at Cornell University by Bill Nesheim, 7: * by permission of the author. 8: */ 9: 10: 11: #ifndef lint 12: static char sccsid[] = "@(#)trace.c 5.6 (Berkeley) 2/14/86"; 13: #endif not lint 14: 15: /* 16: * Routing Table Management Daemon 17: */ 18: #define RIPCMDS 19: #include "defs.h" 20: 21: #define NRECORDS 50 /* size of circular trace buffer */ 22: #ifdef DEBUG 23: FILE *ftrace = stdout; 24: int tracing = 1; 25: #else DEBUG 26: FILE *ftrace = NULL; 27: int tracing = 0; 28: #endif 29: 30: char *xns_ntoa(); 31: 32: traceinit(ifp) 33: register struct interface *ifp; 34: { 35: 36: if (iftraceinit(ifp, &ifp->int_input) && 37: iftraceinit(ifp, &ifp->int_output)) 38: return; 39: tracing = 0; 40: syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name); 41: } 42: 43: static 44: iftraceinit(ifp, ifd) 45: struct interface *ifp; 46: register struct ifdebug *ifd; 47: { 48: register struct iftrace *t; 49: 50: ifd->ifd_records = 51: (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 52: if (ifd->ifd_records == 0) 53: return (0); 54: ifd->ifd_front = ifd->ifd_records; 55: ifd->ifd_count = 0; 56: for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 57: t->ift_size = 0; 58: t->ift_packet = 0; 59: } 60: ifd->ifd_if = ifp; 61: return (1); 62: } 63: 64: traceon(file) 65: char *file; 66: { 67: 68: if (ftrace != NULL) 69: return; 70: ftrace = fopen(file, "a"); 71: if (ftrace == NULL) 72: return; 73: dup2(fileno(ftrace), 1); 74: dup2(fileno(ftrace), 2); 75: tracing = 1; 76: } 77: 78: traceoff() 79: { 80: if (!tracing) 81: return; 82: if (ftrace != NULL) 83: fclose(ftrace); 84: ftrace = NULL; 85: tracing = 0; 86: } 87: 88: trace(ifd, who, p, len, m) 89: register struct ifdebug *ifd; 90: struct sockaddr *who; 91: char *p; 92: int len, m; 93: { 94: register struct iftrace *t; 95: 96: if (ifd->ifd_records == 0) 97: return; 98: t = ifd->ifd_front++; 99: if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 100: ifd->ifd_front = ifd->ifd_records; 101: if (ifd->ifd_count < NRECORDS) 102: ifd->ifd_count++; 103: if (t->ift_size > 0 && t->ift_packet) 104: free(t->ift_packet); 105: t->ift_packet = 0; 106: t->ift_stamp = time(0); 107: t->ift_who = *who; 108: if (len > 0) { 109: t->ift_packet = malloc(len); 110: if (t->ift_packet) 111: bcopy(p, t->ift_packet, len); 112: else 113: len = 0; 114: } 115: t->ift_size = len; 116: t->ift_metric = m; 117: } 118: 119: traceaction(fd, action, rt) 120: FILE *fd; 121: char *action; 122: struct rt_entry *rt; 123: { 124: struct sockaddr_ns *dst, *gate; 125: static struct bits { 126: int t_bits; 127: char *t_name; 128: } flagbits[] = { 129: { RTF_UP, "UP" }, 130: { RTF_GATEWAY, "GATEWAY" }, 131: { RTF_HOST, "HOST" }, 132: { 0 } 133: }, statebits[] = { 134: { RTS_PASSIVE, "PASSIVE" }, 135: { RTS_REMOTE, "REMOTE" }, 136: { RTS_INTERFACE,"INTERFACE" }, 137: { RTS_CHANGED, "CHANGED" }, 138: { 0 } 139: }; 140: register struct bits *p; 141: register int first; 142: char *cp; 143: struct interface *ifp; 144: 145: if (fd == NULL) 146: return; 147: fprintf(fd, "%s ", action); 148: dst = (struct sockaddr_ns *)&rt->rt_dst; 149: gate = (struct sockaddr_ns *)&rt->rt_router; 150: fprintf(fd, "dst %s, ", xns_ntoa(&dst->sns_addr)); 151: fprintf(fd, "router %s, metric %d, flags", 152: xns_ntoa(&gate->sns_addr), rt->rt_metric); 153: cp = " %s"; 154: for (first = 1, p = flagbits; p->t_bits > 0; p++) { 155: if ((rt->rt_flags & p->t_bits) == 0) 156: continue; 157: fprintf(fd, cp, p->t_name); 158: if (first) { 159: cp = "|%s"; 160: first = 0; 161: } 162: } 163: fprintf(fd, " state"); 164: cp = " %s"; 165: for (first = 1, p = statebits; p->t_bits > 0; p++) { 166: if ((rt->rt_state & p->t_bits) == 0) 167: continue; 168: fprintf(fd, cp, p->t_name); 169: if (first) { 170: cp = "|%s"; 171: first = 0; 172: } 173: } 174: putc('\n', fd); 175: if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 176: dumpif(fd, rt->rt_ifp); 177: fflush(fd); 178: } 179: 180: dumpif(fd, ifp) 181: register struct interface *ifp; 182: FILE *fd; 183: { 184: if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 185: fprintf(fd, "*** Packet history for interface %s ***\n", 186: ifp->int_name); 187: dumptrace(fd, "to", &ifp->int_output); 188: dumptrace(fd, "from", &ifp->int_input); 189: fprintf(fd, "*** end packet history ***\n"); 190: } 191: } 192: 193: dumptrace(fd, dir, ifd) 194: FILE *fd; 195: char *dir; 196: register struct ifdebug *ifd; 197: { 198: register struct iftrace *t; 199: char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 200: 201: if (ifd->ifd_front == ifd->ifd_records && 202: ifd->ifd_front->ift_size == 0) { 203: fprintf(fd, "%s: no packets.\n", cp); 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_ns *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: char *xns_nettoa(); 230: 231: if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX) 232: fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)], 233: dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port)); 234: else { 235: fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd), 236: dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port)); 237: fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 238: return; 239: } 240: switch (ntohs(msg->rip_cmd)) { 241: 242: case RIPCMD_REQUEST: 243: case RIPCMD_RESPONSE: 244: fprintf(fd, ":\n"); 245: size -= sizeof (u_short); 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, "\tnet %s metric %d\n", 251: xns_nettoa(n->rip_dst), 252: ntohs(n->rip_metric)); 253: } 254: break; 255: 256: } 257: } 258: 259: union ns_net_u net; 260: 261: char * 262: xns_nettoa(val) 263: union ns_net val; 264: { 265: static char buf[100]; 266: net.net_e = val; 267: sprintf(buf, "%lx", ntohl(net.long_e)); 268: return (buf); 269: } 270: 271: 272: char * 273: xns_ntoa(addr) 274: struct ns_addr *addr; 275: { 276: static char buf[100]; 277: 278: sprintf(buf, "%s#%x:%x:%x:%x:%x:%x", 279: xns_nettoa(addr->x_net), 280: addr->x_host.c_host[0], addr->x_host.c_host[1], 281: addr->x_host.c_host[2], addr->x_host.c_host[3], 282: addr->x_host.c_host[4], addr->x_host.c_host[5]); 283: 284: return(buf); 285: }