1 /* 2 * Copyright (c) 1985 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This file includes significant work done at Cornell University by 6 * Bill Nesheim. That work included by permission. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)trace.c 5.9 (Berkeley) 06/01/90"; 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 (void)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 (void)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 } 286