trace.c revision 97632
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 39#ifndef lint 40#if 0 41static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 42#endif 43static const char rcsid[] = 44 "$FreeBSD: head/usr.sbin/IPXrouted/trace.c 97632 2002-05-30 21:21:23Z wollman $"; 45#endif /* not lint */ 46 47/* 48 * Routing Table Management Daemon 49 */ 50#define RIPCMDS 51#define SAPCMDS 52#include <stdlib.h> 53#include <unistd.h> 54#include <sys/types.h> 55#include <time.h> 56#include "defs.h" 57 58#define NRECORDS 50 /* size of circular trace buffer */ 59#ifdef DEBUG 60FILE *ftrace = stdout; 61int tracing = 1; 62#else /* DEBUG */ 63FILE *ftrace = NULL; 64int tracing = 0; 65#endif 66 67void dumpif(FILE *fd, struct interface *ifp); 68void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd); 69 70void 71traceinit(ifp) 72 register struct interface *ifp; 73{ 74 static int iftraceinit(); 75 76 if (iftraceinit(ifp, &ifp->int_input) && 77 iftraceinit(ifp, &ifp->int_output)) 78 return; 79 tracing = 0; 80 syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name); 81} 82 83static int 84iftraceinit(ifp, ifd) 85 struct interface *ifp; 86 register struct ifdebug *ifd; 87{ 88 register struct iftrace *t; 89 90 ifd->ifd_records = 91 (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 92 if (ifd->ifd_records == 0) 93 return (0); 94 ifd->ifd_front = ifd->ifd_records; 95 ifd->ifd_count = 0; 96 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 97 t->ift_size = 0; 98 t->ift_packet = 0; 99 } 100 ifd->ifd_if = ifp; 101 return (1); 102} 103 104void 105traceon(file) 106 char *file; 107{ 108 109 if (ftrace != NULL) 110 return; 111 ftrace = fopen(file, "a"); 112 if (ftrace == NULL) 113 return; 114 dup2(fileno(ftrace), 1); 115 dup2(fileno(ftrace), 2); 116 tracing = 1; 117} 118 119void 120traceoff(void) 121{ 122 if (!tracing) 123 return; 124 if (ftrace != NULL) 125 fclose(ftrace); 126 ftrace = NULL; 127 tracing = 0; 128} 129 130void 131trace(ifd, who, p, len, m) 132 register struct ifdebug *ifd; 133 struct sockaddr *who; 134 char *p; 135 int len, m; 136{ 137 register struct iftrace *t; 138 139 if (ifd->ifd_records == 0) 140 return; 141 t = ifd->ifd_front++; 142 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 143 ifd->ifd_front = ifd->ifd_records; 144 if (ifd->ifd_count < NRECORDS) 145 ifd->ifd_count++; 146 if (t->ift_size > 0 && t->ift_packet) 147 free(t->ift_packet); 148 t->ift_packet = 0; 149 t->ift_stamp = time(0); 150 t->ift_who = *who; 151 if (len > 0) { 152 t->ift_packet = malloc(len); 153 if (t->ift_packet) 154 bcopy(p, t->ift_packet, len); 155 else 156 len = 0; 157 } 158 t->ift_size = len; 159 t->ift_metric = m; 160} 161 162void 163traceaction(fd, action, rt) 164 FILE *fd; 165 char *action; 166 struct rt_entry *rt; 167{ 168 struct sockaddr_ipx *dst, *gate; 169 static struct bits { 170 int t_bits; 171 char *t_name; 172 } flagbits[] = { 173 { RTF_UP, "UP" }, 174 { RTF_GATEWAY, "GATEWAY" }, 175 { RTF_HOST, "HOST" }, 176 { 0 } 177 }, statebits[] = { 178 { RTS_PASSIVE, "PASSIVE" }, 179 { RTS_REMOTE, "REMOTE" }, 180 { RTS_INTERFACE,"INTERFACE" }, 181 { RTS_CHANGED, "CHANGED" }, 182 { 0 } 183 }; 184 register struct bits *p; 185 register int first; 186 char *cp; 187 188 if (fd == NULL) 189 return; 190 fprintf(fd, "%s ", action); 191 dst = (struct sockaddr_ipx *)&rt->rt_dst; 192 gate = (struct sockaddr_ipx *)&rt->rt_router; 193 fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr)); 194 fprintf(fd, "router %s, metric %d, ticks %d, flags", 195 ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); 196 cp = " %s"; 197 for (first = 1, p = flagbits; p->t_bits > 0; p++) { 198 if ((rt->rt_flags & p->t_bits) == 0) 199 continue; 200 fprintf(fd, cp, p->t_name); 201 if (first) { 202 cp = "|%s"; 203 first = 0; 204 } 205 } 206 fprintf(fd, " state"); 207 cp = " %s"; 208 for (first = 1, p = statebits; p->t_bits > 0; p++) { 209 if ((rt->rt_state & p->t_bits) == 0) 210 continue; 211 fprintf(fd, cp, p->t_name); 212 if (first) { 213 cp = "|%s"; 214 first = 0; 215 } 216 } 217 putc('\n', fd); 218 if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 219 dumpif(fd, rt->rt_ifp); 220 fflush(fd); 221} 222 223void 224traceactionlog(action, rt) 225 char *action; 226 struct rt_entry *rt; 227{ 228 struct sockaddr_ipx *dst, *gate; 229 static struct bits { 230 int t_bits; 231 char *t_name; 232 } flagbits[] = { 233 { RTF_UP, "UP" }, 234 { RTF_GATEWAY, "GATEWAY" }, 235 { RTF_HOST, "HOST" }, 236 { 0 } 237 }, statebits[] = { 238 { RTS_PASSIVE, "PASSIVE" }, 239 { RTS_REMOTE, "REMOTE" }, 240 { RTS_INTERFACE,"INTERFACE" }, 241 { RTS_CHANGED, "CHANGED" }, 242 { 0 } 243 }; 244 register struct bits *p; 245 register int first; 246 char *cp; 247 char *lstr, *olstr; 248 249 dst = (struct sockaddr_ipx *)&rt->rt_dst; 250 gate = (struct sockaddr_ipx *)&rt->rt_router; 251 asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr)); 252 olstr = lstr; 253 asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags", 254 olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); 255 free(olstr); 256 olstr = lstr; 257 cp = "%s %s"; 258 for (first = 1, p = flagbits; p->t_bits > 0; p++) { 259 if ((rt->rt_flags & p->t_bits) == 0) 260 continue; 261 asprintf(&lstr, cp, olstr, p->t_name); 262 free(olstr); 263 olstr = lstr; 264 if (first) { 265 cp = "%s|%s"; 266 first = 0; 267 } 268 } 269 asprintf(&lstr, "%s state", olstr); 270 free(olstr); 271 olstr = lstr; 272 cp = "%s %s"; 273 for (first = 1, p = statebits; p->t_bits > 0; p++) { 274 if ((rt->rt_state & p->t_bits) == 0) 275 continue; 276 asprintf(&lstr, cp, olstr, p->t_name); 277 free(olstr); 278 olstr = lstr; 279 if (first) { 280 cp = "%s|%s"; 281 first = 0; 282 } 283 } 284 syslog(LOG_DEBUG, "%s", lstr); 285 free(lstr); 286} 287 288void 289tracesapactionlog(action, sap) 290 char *action; 291 struct sap_entry *sap; 292{ 293 syslog(LOG_DEBUG, "%-12.12s service %04X %-20.20s " 294 "addr %s.%04X %c metric %d\n", 295 action, 296 ntohs(sap->sap.ServType), 297 sap->sap.ServName, 298 ipxdp_ntoa(&sap->sap.ipx), 299 ntohs(sap->sap.ipx.x_port), 300 (sap->clone ? 'C' : ' '), 301 ntohs(sap->sap.hops)); 302} 303 304void 305dumpif(fd, ifp) 306 register struct interface *ifp; 307 FILE *fd; 308{ 309 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 310 fprintf(fd, "*** Packet history for interface %s ***\n", 311 ifp->int_name); 312 dumptrace(fd, "to", &ifp->int_output); 313 dumptrace(fd, "from", &ifp->int_input); 314 fprintf(fd, "*** end packet history ***\n"); 315 } 316} 317 318void 319dumptrace(fd, dir, ifd) 320 FILE *fd; 321 char *dir; 322 register struct ifdebug *ifd; 323{ 324 register struct iftrace *t; 325 char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 326 327 if (ifd->ifd_front == ifd->ifd_records && 328 ifd->ifd_front->ift_size == 0) { 329 fprintf(fd, "%s: no packets.\n", cp); 330 return; 331 } 332 fprintf(fd, "%s trace:\n", cp); 333 t = ifd->ifd_front - ifd->ifd_count; 334 if (t < ifd->ifd_records) 335 t += NRECORDS; 336 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 337 if (t >= ifd->ifd_records + NRECORDS) 338 t = ifd->ifd_records; 339 if (t->ift_size == 0) 340 continue; 341 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 342 t->ift_metric); 343 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 344 } 345} 346 347void 348dumppacket(fd, dir, source, cp, size) 349 FILE *fd; 350 char *dir; 351 struct sockaddr *source; 352 char *cp; 353 register int size; 354{ 355 register struct rip *msg = (struct rip *)cp; 356 register struct netinfo *n; 357 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 358 359 if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX) 360 fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)], 361 dir, ipxdp_ntoa(&who->sipx_addr), 362 ntohs(who->sipx_addr.x_port)); 363 else { 364 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd), 365 dir, ipxdp_ntoa(&who->sipx_addr), 366 ntohs(who->sipx_addr.x_port)); 367 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 368 (u_int)cp, (u_int)packet); 369 return; 370 } 371 switch (ntohs(msg->rip_cmd)) { 372 373 case RIPCMD_REQUEST: 374 case RIPCMD_RESPONSE: 375 fprintf(fd, ":\n"); 376 size -= sizeof (u_short); 377 n = msg->rip_nets; 378 for (; size > 0; n++, size -= sizeof (struct netinfo)) { 379 if (size < sizeof (struct netinfo)) 380 break; 381 fprintf(fd, "\tnet %s metric %d ticks %d\n", 382 ipxdp_nettoa(n->rip_dst), 383 ntohs(n->rip_metric), 384 ntohs(n->rip_ticks)); 385 } 386 break; 387 388 } 389} 390 391void 392dumpsappacket(fd, dir, source, cp, size) 393 FILE *fd; 394 char *dir; 395 struct sockaddr *source; 396 char *cp; 397 register int size; 398{ 399 register struct sap_packet *msg = (struct sap_packet *)cp; 400 register struct sap_info *n; 401 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 402 403 if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX) 404 fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)], 405 dir, ipxdp_ntoa(&who->sipx_addr), 406 ntohs(who->sipx_addr.x_port)); 407 else { 408 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd), 409 dir, ipxdp_ntoa(&who->sipx_addr), 410 ntohs(who->sipx_addr.x_port)); 411 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 412 (u_int)cp, (u_int)packet); 413 return; 414 } 415 switch (ntohs(msg->sap_cmd)) { 416 417 case SAP_REQ: 418 case SAP_RESP: 419 case SAP_REQ_NEAR: 420 case SAP_RESP_NEAR: 421 fprintf(fd, ":\n"); 422 size -= sizeof (u_short); 423 n = msg->sap; 424 for (; size > 0; n++, size -= sizeof (struct sap_info)) { 425 if (size < sizeof (struct sap_info)) 426 break; 427 fprintf(fd, " service %04X %-20.20s " 428 "addr %s.%04X metric %d\n", 429 ntohs(n->ServType), 430 n->ServName, 431 ipxdp_ntoa(&n->ipx), 432 ntohs(n->ipx.x_port), 433 ntohs(n->hops)); 434 } 435 break; 436 437 } 438} 439 440void 441dumpsaptable(fd, sh) 442 FILE *fd; 443 struct sap_hash *sh; 444{ 445 register struct sap_entry *sap; 446 struct sap_hash *hash; 447 int x = 0; 448 449 fprintf(fd, "------- SAP table dump. -------\n"); 450 for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) { 451 fprintf(fd, "HASH %d\n", x); 452 sap = hash->forw; 453 for (; sap != (struct sap_entry *)hash; sap = sap->forw) { 454 fprintf(fd, " service %04X %-20.20s " 455 "addr %s.%04X %c metric %d\n", 456 ntohs(sap->sap.ServType), 457 sap->sap.ServName, 458 ipxdp_ntoa(&sap->sap.ipx), 459 ntohs(sap->sap.ipx.x_port), 460 (sap->clone ? 'C' : ' '), 461 ntohs(sap->sap.hops)); 462 } 463 } 464 fprintf(fd, "\n"); 465} 466 467void 468dumpriptable(fd) 469 FILE *fd; 470{ 471 register struct rt_entry *rip; 472 struct rthash *hash; 473 int x; 474 struct rthash *rh = nethash; 475 476 fprintf(fd, "------- RIP table dump. -------\n"); 477 x = 0; 478 fprintf(fd, "Network table.\n"); 479 480 for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) { 481 fprintf(fd, "HASH %d\n", x); 482 rip = hash->rt_forw; 483 for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) { 484 fprintf(fd, " dest %s\t", 485 ipxdp_ntoa(&satoipx_addr(rip->rt_dst))); 486 fprintf(fd, "%s metric %d, ticks %d\n", 487 ipxdp_ntoa(&satoipx_addr(rip->rt_router)), 488 rip->rt_metric, 489 rip->rt_ticks); 490 } 491 } 492 fprintf(fd, "\n"); 493} 494 495union ipx_net_u net; 496 497char * 498ipxdp_nettoa(val) 499union ipx_net val; 500{ 501 static char buf[100]; 502 net.net_e = val; 503 (void)sprintf(buf, "%lx", ntohl(net.long_e)); 504 return (buf); 505} 506 507 508char * 509ipxdp_ntoa(addr) 510struct ipx_addr *addr; 511{ 512 static char buf[100]; 513 514 (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x", 515 ipxdp_nettoa(addr->x_net), 516 addr->x_host.c_host[0], addr->x_host.c_host[1], 517 addr->x_host.c_host[2], addr->x_host.c_host[3], 518 addr->x_host.c_host[4], addr->x_host.c_host[5]); 519 520 return(buf); 521} 522