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