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