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