trace.c revision 27244
1/* 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Copyright (c) 1995 John Hay. All rights reserved. 6 * 7 * This file includes significant work done at Cornell University by 8 * Bill Nesheim. That work included by permission. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * $Id: trace.c,v 1.4 1997/02/22 16:01:04 peter Exp $ 39 */ 40 41#ifndef lint 42static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 43#endif /* not lint */ 44 45/* 46 * Routing Table Management Daemon 47 */ 48#define RIPCMDS 49#define SAPCMDS 50#include <stdlib.h> 51#include <unistd.h> 52#include <sys/types.h> 53#include <time.h> 54#include "defs.h" 55 56#define NRECORDS 50 /* size of circular trace buffer */ 57#ifdef DEBUG 58FILE *ftrace = stdout; 59int tracing = 1; 60#else DEBUG 61FILE *ftrace = NULL; 62int tracing = 0; 63#endif 64 65void dumpif(FILE *fd, struct interface *ifp); 66void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd); 67 68void 69traceinit(ifp) 70 register struct interface *ifp; 71{ 72 static int iftraceinit(); 73 74 if (iftraceinit(ifp, &ifp->int_input) && 75 iftraceinit(ifp, &ifp->int_output)) 76 return; 77 tracing = 0; 78 syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name); 79} 80 81static int 82iftraceinit(ifp, ifd) 83 struct interface *ifp; 84 register struct ifdebug *ifd; 85{ 86 register struct iftrace *t; 87 88 ifd->ifd_records = 89 (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 90 if (ifd->ifd_records == 0) 91 return (0); 92 ifd->ifd_front = ifd->ifd_records; 93 ifd->ifd_count = 0; 94 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 95 t->ift_size = 0; 96 t->ift_packet = 0; 97 } 98 ifd->ifd_if = ifp; 99 return (1); 100} 101 102void 103traceon(file) 104 char *file; 105{ 106 107 if (ftrace != NULL) 108 return; 109 ftrace = fopen(file, "a"); 110 if (ftrace == NULL) 111 return; 112 dup2(fileno(ftrace), 1); 113 dup2(fileno(ftrace), 2); 114 tracing = 1; 115} 116 117void 118traceoff(void) 119{ 120 if (!tracing) 121 return; 122 if (ftrace != NULL) 123 fclose(ftrace); 124 ftrace = NULL; 125 tracing = 0; 126} 127 128void 129trace(ifd, who, p, len, m) 130 register struct ifdebug *ifd; 131 struct sockaddr *who; 132 char *p; 133 int len, m; 134{ 135 register struct iftrace *t; 136 137 if (ifd->ifd_records == 0) 138 return; 139 t = ifd->ifd_front++; 140 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 141 ifd->ifd_front = ifd->ifd_records; 142 if (ifd->ifd_count < NRECORDS) 143 ifd->ifd_count++; 144 if (t->ift_size > 0 && t->ift_packet) 145 free(t->ift_packet); 146 t->ift_packet = 0; 147 t->ift_stamp = time(0); 148 t->ift_who = *who; 149 if (len > 0) { 150 t->ift_packet = malloc(len); 151 if (t->ift_packet) 152 bcopy(p, t->ift_packet, len); 153 else 154 len = 0; 155 } 156 t->ift_size = len; 157 t->ift_metric = m; 158} 159 160void 161traceaction(fd, action, rt) 162 FILE *fd; 163 char *action; 164 struct rt_entry *rt; 165{ 166 struct sockaddr_ipx *dst, *gate; 167 static struct bits { 168 int t_bits; 169 char *t_name; 170 } flagbits[] = { 171 { RTF_UP, "UP" }, 172 { RTF_GATEWAY, "GATEWAY" }, 173 { RTF_HOST, "HOST" }, 174 { 0 } 175 }, statebits[] = { 176 { RTS_PASSIVE, "PASSIVE" }, 177 { RTS_REMOTE, "REMOTE" }, 178 { RTS_INTERFACE,"INTERFACE" }, 179 { RTS_CHANGED, "CHANGED" }, 180 { 0 } 181 }; 182 register struct bits *p; 183 register int first; 184 char *cp; 185 186 if (fd == NULL) 187 return; 188 fprintf(fd, "%s ", action); 189 dst = (struct sockaddr_ipx *)&rt->rt_dst; 190 gate = (struct sockaddr_ipx *)&rt->rt_router; 191 fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr)); 192 fprintf(fd, "router %s, metric %d, ticks %d, flags", 193 ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); 194 cp = " %s"; 195 for (first = 1, p = flagbits; p->t_bits > 0; p++) { 196 if ((rt->rt_flags & p->t_bits) == 0) 197 continue; 198 fprintf(fd, cp, p->t_name); 199 if (first) { 200 cp = "|%s"; 201 first = 0; 202 } 203 } 204 fprintf(fd, " state"); 205 cp = " %s"; 206 for (first = 1, p = statebits; p->t_bits > 0; p++) { 207 if ((rt->rt_state & p->t_bits) == 0) 208 continue; 209 fprintf(fd, cp, p->t_name); 210 if (first) { 211 cp = "|%s"; 212 first = 0; 213 } 214 } 215 putc('\n', fd); 216 if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 217 dumpif(fd, rt->rt_ifp); 218 fflush(fd); 219} 220 221void 222traceactionlog(action, rt) 223 char *action; 224 struct rt_entry *rt; 225{ 226 struct sockaddr_ipx *dst, *gate; 227 static struct bits { 228 int t_bits; 229 char *t_name; 230 } flagbits[] = { 231 { RTF_UP, "UP" }, 232 { RTF_GATEWAY, "GATEWAY" }, 233 { RTF_HOST, "HOST" }, 234 { 0 } 235 }, statebits[] = { 236 { RTS_PASSIVE, "PASSIVE" }, 237 { RTS_REMOTE, "REMOTE" }, 238 { RTS_INTERFACE,"INTERFACE" }, 239 { RTS_CHANGED, "CHANGED" }, 240 { 0 } 241 }; 242 register struct bits *p; 243 register int first; 244 char *cp; 245 char *lstr, *olstr; 246 247 dst = (struct sockaddr_ipx *)&rt->rt_dst; 248 gate = (struct sockaddr_ipx *)&rt->rt_router; 249 asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr)); 250 olstr = lstr; 251 asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags", 252 olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); 253 free(olstr); 254 olstr = lstr; 255 cp = "%s %s"; 256 for (first = 1, p = flagbits; p->t_bits > 0; p++) { 257 if ((rt->rt_flags & p->t_bits) == 0) 258 continue; 259 asprintf(&lstr, cp, olstr, p->t_name); 260 free(olstr); 261 olstr = lstr; 262 if (first) { 263 cp = "%s|%s"; 264 first = 0; 265 } 266 } 267 asprintf(&lstr, "%s state", olstr); 268 free(olstr); 269 olstr = lstr; 270 cp = "%s %s"; 271 for (first = 1, p = statebits; p->t_bits > 0; p++) { 272 if ((rt->rt_state & p->t_bits) == 0) 273 continue; 274 asprintf(&lstr, cp, olstr, p->t_name); 275 free(olstr); 276 olstr = lstr; 277 if (first) { 278 cp = "%s|%s"; 279 first = 0; 280 } 281 } 282 syslog(LOG_DEBUG, lstr); 283 free(lstr); 284} 285 286void 287tracesapactionlog(action, sap) 288 char *action; 289 struct sap_entry *sap; 290{ 291 syslog(LOG_DEBUG, "%-12.12s service %04X %-20.20s " 292 "addr %s.%04X %c metric %d\n", 293 action, 294 ntohs(sap->sap.ServType), 295 sap->sap.ServName, 296 ipxdp_ntoa(&sap->sap.ipx), 297 ntohs(sap->sap.ipx.x_port), 298 (sap->clone ? 'C' : ' '), 299 ntohs(sap->sap.hops)); 300} 301 302void 303dumpif(fd, ifp) 304 register struct interface *ifp; 305 FILE *fd; 306{ 307 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 308 fprintf(fd, "*** Packet history for interface %s ***\n", 309 ifp->int_name); 310 dumptrace(fd, "to", &ifp->int_output); 311 dumptrace(fd, "from", &ifp->int_input); 312 fprintf(fd, "*** end packet history ***\n"); 313 } 314} 315 316void 317dumptrace(fd, dir, ifd) 318 FILE *fd; 319 char *dir; 320 register struct ifdebug *ifd; 321{ 322 register struct iftrace *t; 323 char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 324 325 if (ifd->ifd_front == ifd->ifd_records && 326 ifd->ifd_front->ift_size == 0) { 327 fprintf(fd, "%s: no packets.\n", cp); 328 return; 329 } 330 fprintf(fd, "%s trace:\n", cp); 331 t = ifd->ifd_front - ifd->ifd_count; 332 if (t < ifd->ifd_records) 333 t += NRECORDS; 334 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 335 if (t >= ifd->ifd_records + NRECORDS) 336 t = ifd->ifd_records; 337 if (t->ift_size == 0) 338 continue; 339 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 340 t->ift_metric); 341 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 342 } 343} 344 345void 346dumppacket(fd, dir, source, cp, size) 347 FILE *fd; 348 char *dir; 349 struct sockaddr *source; 350 char *cp; 351 register int size; 352{ 353 register struct rip *msg = (struct rip *)cp; 354 register struct netinfo *n; 355 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 356 357 if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX) 358 fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)], 359 dir, ipxdp_ntoa(&who->sipx_addr), 360 ntohs(who->sipx_addr.x_port)); 361 else { 362 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd), 363 dir, ipxdp_ntoa(&who->sipx_addr), 364 ntohs(who->sipx_addr.x_port)); 365 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 366 (u_int)cp, (u_int)packet); 367 return; 368 } 369 switch (ntohs(msg->rip_cmd)) { 370 371 case RIPCMD_REQUEST: 372 case RIPCMD_RESPONSE: 373 fprintf(fd, ":\n"); 374 size -= sizeof (u_short); 375 n = msg->rip_nets; 376 for (; size > 0; n++, size -= sizeof (struct netinfo)) { 377 if (size < sizeof (struct netinfo)) 378 break; 379 fprintf(fd, "\tnet %s metric %d ticks %d\n", 380 ipxdp_nettoa(n->rip_dst), 381 ntohs(n->rip_metric), 382 ntohs(n->rip_ticks)); 383 } 384 break; 385 386 } 387} 388 389void 390dumpsappacket(fd, dir, source, cp, size) 391 FILE *fd; 392 char *dir; 393 struct sockaddr *source; 394 char *cp; 395 register int size; 396{ 397 register struct sap_packet *msg = (struct sap_packet *)cp; 398 register struct sap_info *n; 399 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 400 401 if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX) 402 fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)], 403 dir, ipxdp_ntoa(&who->sipx_addr), 404 ntohs(who->sipx_addr.x_port)); 405 else { 406 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd), 407 dir, ipxdp_ntoa(&who->sipx_addr), 408 ntohs(who->sipx_addr.x_port)); 409 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 410 (u_int)cp, (u_int)packet); 411 return; 412 } 413 switch (ntohs(msg->sap_cmd)) { 414 415 case SAP_REQ: 416 case SAP_RESP: 417 case SAP_REQ_NEAR: 418 case SAP_RESP_NEAR: 419 fprintf(fd, ":\n"); 420 size -= sizeof (u_short); 421 n = msg->sap; 422 for (; size > 0; n++, size -= sizeof (struct sap_info)) { 423 if (size < sizeof (struct sap_info)) 424 break; 425 fprintf(fd, " service %04X %-20.20s " 426 "addr %s.%04X metric %d\n", 427 ntohs(n->ServType), 428 n->ServName, 429 ipxdp_ntoa(&n->ipx), 430 ntohs(n->ipx.x_port), 431 ntohs(n->hops)); 432 } 433 break; 434 435 } 436} 437 438void 439dumpsaptable(fd, sh) 440 FILE *fd; 441 struct sap_hash *sh; 442{ 443 register struct sap_entry *sap; 444 struct sap_hash *hash; 445 int x = 0; 446 447 fprintf(fd, "------- SAP table dump. -------\n"); 448 for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) { 449 fprintf(fd, "HASH %d\n", x); 450 sap = hash->forw; 451 for (; sap != (struct sap_entry *)hash; sap = sap->forw) { 452 fprintf(fd, " service %04X %-20.20s " 453 "addr %s.%04X %c metric %d\n", 454 ntohs(sap->sap.ServType), 455 sap->sap.ServName, 456 ipxdp_ntoa(&sap->sap.ipx), 457 ntohs(sap->sap.ipx.x_port), 458 (sap->clone ? 'C' : ' '), 459 ntohs(sap->sap.hops)); 460 } 461 } 462 fprintf(fd, "\n"); 463} 464 465void 466dumpriptable(fd) 467 FILE *fd; 468{ 469 register struct rt_entry *rip; 470 struct rthash *hash; 471 int x; 472 struct rthash *rh = nethash; 473 474 fprintf(fd, "------- RIP table dump. -------\n"); 475 x = 0; 476 fprintf(fd, "Network table.\n"); 477 478 for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) { 479 fprintf(fd, "HASH %d\n", x); 480 rip = hash->rt_forw; 481 for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) { 482 fprintf(fd, " dest %s\t", 483 ipxdp_ntoa(&satoipx_addr(rip->rt_dst))); 484 fprintf(fd, "%s metric %d, ticks %d\n", 485 ipxdp_ntoa(&satoipx_addr(rip->rt_router)), 486 rip->rt_metric, 487 rip->rt_ticks); 488 } 489 } 490 fprintf(fd, "\n"); 491} 492 493union ipx_net_u net; 494 495char * 496ipxdp_nettoa(val) 497union ipx_net val; 498{ 499 static char buf[100]; 500 net.net_e = val; 501 (void)sprintf(buf, "%lx", ntohl(net.long_e)); 502 return (buf); 503} 504 505 506char * 507ipxdp_ntoa(addr) 508struct ipx_addr *addr; 509{ 510 static char buf[100]; 511 512 (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x", 513 ipxdp_nettoa(addr->x_net), 514 addr->x_host.c_host[0], addr->x_host.c_host[1], 515 addr->x_host.c_host[2], addr->x_host.c_host[3], 516 addr->x_host.c_host[4], addr->x_host.c_host[5]); 517 518 return(buf); 519} 520