1 /* 2 * Copyright (c) 1983, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)trace.c 5.6 (Berkeley) 05/31/88"; 15 #endif /* not lint */ 16 17 /* 18 * Routing Table Management Daemon 19 */ 20 #define RIPCMDS 21 #include "defs.h" 22 #include <sys/file.h> 23 #include <sys/stat.h> 24 #include <sys/signal.h> 25 26 #define NRECORDS 50 /* size of circular trace buffer */ 27 #ifdef DEBUG 28 FILE *ftrace = stdout; 29 int traceactions = 1; 30 #endif 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 tracehistory = 0; 40 fprintf(stderr, "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 struct stat stbuf; 68 69 if (ftrace != NULL) 70 return; 71 if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) 72 return; 73 ftrace = fopen(file, "a"); 74 if (ftrace == NULL) 75 return; 76 dup2(fileno(ftrace), 1); 77 dup2(fileno(ftrace), 2); 78 traceactions = 1; 79 } 80 81 traceoff() 82 { 83 if (!traceactions) 84 return; 85 if (ftrace != NULL) { 86 int fd = open("/dev/null", O_RDWR); 87 88 fprintf(ftrace, "Tracing disabled\n"); 89 (void) dup2(fd, 1); 90 (void) dup2(fd, 2); 91 (void) close(fd); 92 fclose(ftrace); 93 ftrace = NULL; 94 } 95 traceactions = 0; 96 tracehistory = 0; 97 } 98 99 sigtrace(s) 100 int s; 101 { 102 if (s == SIGUSR2) { 103 traceoff(); 104 tracepackets = 0; 105 } else if (traceactions == 0) 106 traceactions++; 107 else if (tracehistory == 0) 108 tracehistory++; 109 else { 110 tracepackets++; 111 tracehistory = 0; 112 } 113 } 114 115 trace(ifd, who, p, len, m) 116 register struct ifdebug *ifd; 117 struct sockaddr *who; 118 char *p; 119 int len, m; 120 { 121 register struct iftrace *t; 122 123 if (ifd->ifd_records == 0) 124 return; 125 t = ifd->ifd_front++; 126 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 127 ifd->ifd_front = ifd->ifd_records; 128 if (ifd->ifd_count < NRECORDS) 129 ifd->ifd_count++; 130 if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { 131 free(t->ift_packet); 132 t->ift_packet = 0; 133 } 134 t->ift_stamp = time(0); 135 t->ift_who = *who; 136 if (len > 0 && t->ift_packet == 0) { 137 t->ift_packet = malloc(len); 138 if (t->ift_packet == 0) 139 len = 0; 140 } 141 if (len > 0) 142 bcopy(p, t->ift_packet, len); 143 t->ift_size = len; 144 t->ift_metric = m; 145 } 146 147 traceaction(fd, action, rt) 148 FILE *fd; 149 char *action; 150 struct rt_entry *rt; 151 { 152 struct sockaddr_in *dst, *gate; 153 static struct bits { 154 int t_bits; 155 char *t_name; 156 } flagbits[] = { 157 { RTF_UP, "UP" }, 158 { RTF_GATEWAY, "GATEWAY" }, 159 { RTF_HOST, "HOST" }, 160 { 0 } 161 }, statebits[] = { 162 { RTS_PASSIVE, "PASSIVE" }, 163 { RTS_REMOTE, "REMOTE" }, 164 { RTS_INTERFACE,"INTERFACE" }, 165 { RTS_CHANGED, "CHANGED" }, 166 { RTS_INTERNAL, "INTERNAL" }, 167 { RTS_EXTERNAL, "EXTERNAL" }, 168 { RTS_SUBNET, "SUBNET" }, 169 { 0 } 170 }; 171 register struct bits *p; 172 register int first; 173 char *cp; 174 struct interface *ifp; 175 176 if (fd == NULL) 177 return; 178 if (curtime) { 179 fprintf(fd, "\n%s", curtime); 180 curtime = NULL; 181 } 182 fprintf(fd, "%s ", action); 183 dst = (struct sockaddr_in *)&rt->rt_dst; 184 gate = (struct sockaddr_in *)&rt->rt_router; 185 fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); 186 fprintf(fd, "router %s, metric %d, flags", 187 inet_ntoa(gate->sin_addr), rt->rt_metric); 188 cp = " %s"; 189 for (first = 1, p = flagbits; p->t_bits > 0; p++) { 190 if ((rt->rt_flags & p->t_bits) == 0) 191 continue; 192 fprintf(fd, cp, p->t_name); 193 if (first) { 194 cp = "|%s"; 195 first = 0; 196 } 197 } 198 fprintf(fd, " state"); 199 cp = " %s"; 200 for (first = 1, p = statebits; p->t_bits > 0; p++) { 201 if ((rt->rt_state & p->t_bits) == 0) 202 continue; 203 fprintf(fd, cp, p->t_name); 204 if (first) { 205 cp = "|%s"; 206 first = 0; 207 } 208 } 209 fprintf(fd, " timer %d\n", rt->rt_timer); 210 if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 211 dumpif(fd, rt->rt_ifp); 212 fflush(fd); 213 } 214 215 tracenewmetric(fd, rt, newmetric) 216 FILE *fd; 217 struct rt_entry *rt; 218 int newmetric; 219 { 220 struct sockaddr_in *dst, *gate; 221 222 if (fd == NULL) 223 return; 224 dst = (struct sockaddr_in *)&rt->rt_dst; 225 gate = (struct sockaddr_in *)&rt->rt_router; 226 fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); 227 fprintf(fd, "router %s, from %d to %d\n", 228 inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); 229 fflush(fd); 230 } 231 232 dumpif(fd, ifp) 233 register struct interface *ifp; 234 { 235 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 236 fprintf(fd, "*** Packet history for interface %s ***\n", 237 ifp->int_name); 238 #ifdef notneeded 239 dumptrace(fd, "to", &ifp->int_output); 240 #endif 241 dumptrace(fd, "from", &ifp->int_input); 242 fprintf(fd, "*** end packet history ***\n"); 243 } 244 fflush(fd); 245 } 246 247 dumptrace(fd, dir, ifd) 248 FILE *fd; 249 char *dir; 250 register struct ifdebug *ifd; 251 { 252 register struct iftrace *t; 253 char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 254 255 if (ifd->ifd_front == ifd->ifd_records && 256 ifd->ifd_front->ift_size == 0) { 257 fprintf(fd, "%s: no packets.\n", cp); 258 fflush(fd); 259 return; 260 } 261 fprintf(fd, "%s trace:\n", cp); 262 t = ifd->ifd_front - ifd->ifd_count; 263 if (t < ifd->ifd_records) 264 t += NRECORDS; 265 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 266 if (t >= ifd->ifd_records + NRECORDS) 267 t = ifd->ifd_records; 268 if (t->ift_size == 0) 269 continue; 270 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, 271 &t->ift_stamp); 272 } 273 } 274 275 dumppacket(fd, dir, who, cp, size, tstamp) 276 FILE *fd; 277 struct sockaddr_in *who; /* should be sockaddr */ 278 char *dir, *cp; 279 register int size; 280 time_t *tstamp; 281 { 282 register struct rip *msg = (struct rip *)cp; 283 register struct netinfo *n; 284 285 if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) 286 fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], 287 dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); 288 else { 289 fprintf(fd, "Bad cmd 0x%x %s %x.%d %.24s\n", msg->rip_cmd, 290 dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), 291 ctime(tstamp)); 292 fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); 293 fflush(fd); 294 return; 295 } 296 fprintf(fd, " %.24s:\n", ctime(tstamp)); 297 switch (msg->rip_cmd) { 298 299 case RIPCMD_REQUEST: 300 case RIPCMD_RESPONSE: 301 size -= 4 * sizeof (char); 302 n = msg->rip_nets; 303 for (; size > 0; n++, size -= sizeof (struct netinfo)) { 304 if (size < sizeof (struct netinfo)) 305 break; 306 fprintf(fd, "\tdst %s metric %d\n", 307 #define satosin(sa) ((struct sockaddr_in *)&sa) 308 inet_ntoa(satosin(n->rip_dst)->sin_addr), 309 ntohl(n->rip_metric)); 310 } 311 break; 312 313 case RIPCMD_TRACEON: 314 fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); 315 break; 316 317 case RIPCMD_TRACEOFF: 318 break; 319 } 320 fflush(fd); 321 } 322