trace.c revision 11820
186071Sache/* 286071Sache * Copyright (c) 1985, 1993 386071Sache * The Regents of the University of California. All rights reserved. 486071Sache * 586071Sache * Copyright (c) 1995 John Hay. All rights reserved. 686071Sache * 786071Sache * This file includes significant work done at Cornell University by 886071Sache * Bill Nesheim. That work included by permission. 986071Sache * 1086071Sache * Redistribution and use in source and binary forms, with or without 1186071Sache * modification, are permitted provided that the following conditions 1286071Sache * are met: 1386071Sache * 1. Redistributions of source code must retain the above copyright 1486071Sache * notice, this list of conditions and the following disclaimer. 1586071Sache * 2. Redistributions in binary form must reproduce the above copyright 1686071Sache * notice, this list of conditions and the following disclaimer in the 1786071Sache * documentation and/or other materials provided with the distribution. 1886071Sache * 3. All advertising materials mentioning features or use of this software 1986071Sache * must display the following acknowledgement: 2086071Sache * This product includes software developed by the University of 2186071Sache * California, Berkeley and its contributors. 2286071Sache * 4. Neither the name of the University nor the names of its contributors 2386071Sache * may be used to endorse or promote products derived from this software 2486071Sache * without specific prior written permission. 2586071Sache * 2686071Sache * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2786071Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2886071Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2986071Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3086071Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3186071Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3286071Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3386071Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3486071Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3586071Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3686071Sache * SUCH DAMAGE. 3786071Sache * 3886071Sache * $Id: trace.c,v 1.6 1995/10/11 18:57:33 jhay Exp $ 3986071Sache */ 4086071Sache 4186071Sache#ifndef lint 4286071Sachestatic char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 4386071Sache#endif /* not lint */ 4486071Sache 4586071Sache/* 4686071Sache * Routing Table Management Daemon 4786071Sache */ 4886071Sache#define RIPCMDS 4986071Sache#define SAPCMDS 5086071Sache#include <stdlib.h> 5186071Sache#include <unistd.h> 5286071Sache#include <sys/types.h> 5386071Sache#include <time.h> 5486071Sache#include "defs.h" 5586071Sache 5686071Sache#define NRECORDS 50 /* size of circular trace buffer */ 5786071Sache#ifdef DEBUG 5886071SacheFILE *ftrace = stdout; 5986071Sacheint tracing = 1; 6086071Sache#else DEBUG 6186071SacheFILE *ftrace = NULL; 6286071Sacheint tracing = 0; 6386071Sache#endif 6486071Sache 6586071Sachevoid dumpif(FILE *fd, struct interface *ifp); 6686071Sachevoid dumptrace(FILE *fd, char *dir, struct ifdebug *ifd); 6786071Sache 6886071Sachevoid 6986071Sachetraceinit(ifp) 7086071Sache register struct interface *ifp; 7186071Sache{ 7286071Sache static int iftraceinit(); 7386071Sache 7486071Sache if (iftraceinit(ifp, &ifp->int_input) && 7586071Sache iftraceinit(ifp, &ifp->int_output)) 7686071Sache return; 7786071Sache tracing = 0; 7886071Sache syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name); 7986071Sache} 8086071Sache 8186071Sachestatic int 8286071Sacheiftraceinit(ifp, ifd) 8386071Sache struct interface *ifp; 8486071Sache register struct ifdebug *ifd; 8586071Sache{ 8686071Sache register struct iftrace *t; 8786071Sache 8886071Sache ifd->ifd_records = 8986071Sache (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); 9086071Sache if (ifd->ifd_records == 0) 9186071Sache return (0); 9286071Sache ifd->ifd_front = ifd->ifd_records; 9386071Sache ifd->ifd_count = 0; 9486071Sache for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { 9586071Sache t->ift_size = 0; 9686071Sache t->ift_packet = 0; 9786071Sache } 9886071Sache ifd->ifd_if = ifp; 9986071Sache return (1); 10086071Sache} 10186071Sache 10286071Sachevoid 10386071Sachetraceon(file) 10486071Sache char *file; 10586071Sache{ 10686071Sache 10786071Sache if (ftrace != NULL) 10886071Sache return; 10986071Sache ftrace = fopen(file, "a"); 11086071Sache if (ftrace == NULL) 11186071Sache return; 11286071Sache dup2(fileno(ftrace), 1); 11386071Sache dup2(fileno(ftrace), 2); 11486071Sache tracing = 1; 11586071Sache} 11686071Sache 11786071Sachevoid 11886071Sachetraceoff(void) 11986071Sache{ 12086071Sache if (!tracing) 12186071Sache return; 12286071Sache if (ftrace != NULL) 12386071Sache fclose(ftrace); 12486071Sache ftrace = NULL; 12586071Sache tracing = 0; 12686071Sache} 12786071Sache 12886071Sachevoid 12986071Sachetrace(ifd, who, p, len, m) 13086071Sache register struct ifdebug *ifd; 13186071Sache struct sockaddr *who; 13286071Sache char *p; 13386071Sache int len, m; 13486071Sache{ 13586071Sache register struct iftrace *t; 13686071Sache 13786071Sache if (ifd->ifd_records == 0) 13886071Sache return; 13986071Sache t = ifd->ifd_front++; 14086071Sache if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) 14186071Sache ifd->ifd_front = ifd->ifd_records; 14286071Sache if (ifd->ifd_count < NRECORDS) 14386071Sache ifd->ifd_count++; 14486071Sache if (t->ift_size > 0 && t->ift_packet) 14586071Sache free(t->ift_packet); 14686071Sache t->ift_packet = 0; 14786071Sache t->ift_stamp = time(0); 14886071Sache t->ift_who = *who; 14986071Sache if (len > 0) { 15086071Sache t->ift_packet = malloc(len); 15186071Sache if (t->ift_packet) 15286071Sache bcopy(p, t->ift_packet, len); 15386071Sache else 15486071Sache len = 0; 15586071Sache } 15686071Sache t->ift_size = len; 15786071Sache t->ift_metric = m; 15886071Sache} 15986071Sache 16086071Sachevoid 16186071Sachetraceaction(fd, action, rt) 16286071Sache FILE *fd; 16386071Sache char *action; 16486071Sache struct rt_entry *rt; 16586071Sache{ 16686071Sache struct sockaddr_ipx *dst, *gate; 16786071Sache static struct bits { 16886071Sache int t_bits; 16986071Sache char *t_name; 17086071Sache } flagbits[] = { 17186071Sache { RTF_UP, "UP" }, 17286071Sache { RTF_GATEWAY, "GATEWAY" }, 17386071Sache { RTF_HOST, "HOST" }, 17486071Sache { 0 } 17586071Sache }, statebits[] = { 17686071Sache { RTS_PASSIVE, "PASSIVE" }, 17786071Sache { RTS_REMOTE, "REMOTE" }, 17886071Sache { RTS_INTERFACE,"INTERFACE" }, 17986071Sache { RTS_CHANGED, "CHANGED" }, 18086071Sache { 0 } 18186071Sache }; 18286071Sache register struct bits *p; 18386071Sache register int first; 18486071Sache char *cp; 18586071Sache 18686071Sache if (fd == NULL) 18786071Sache return; 18886071Sache fprintf(fd, "%s ", action); 18986071Sache dst = (struct sockaddr_ipx *)&rt->rt_dst; 19086071Sache gate = (struct sockaddr_ipx *)&rt->rt_router; 19186071Sache fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr)); 19286071Sache fprintf(fd, "router %s, metric %d, ticks %d, flags", 19386071Sache ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks); 19486071Sache cp = " %s"; 19586071Sache for (first = 1, p = flagbits; p->t_bits > 0; p++) { 19686071Sache if ((rt->rt_flags & p->t_bits) == 0) 19786071Sache continue; 19886071Sache fprintf(fd, cp, p->t_name); 19986071Sache if (first) { 20086071Sache cp = "|%s"; 20186071Sache first = 0; 20286071Sache } 20386071Sache } 20486071Sache fprintf(fd, " state"); 20586071Sache cp = " %s"; 20686071Sache for (first = 1, p = statebits; p->t_bits > 0; p++) { 20786071Sache if ((rt->rt_state & p->t_bits) == 0) 20886071Sache continue; 20986071Sache fprintf(fd, cp, p->t_name); 21086071Sache if (first) { 21186071Sache cp = "|%s"; 21286071Sache first = 0; 21386071Sache } 21486071Sache } 21586071Sache putc('\n', fd); 21686071Sache if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) 21786071Sache dumpif(fd, rt->rt_ifp); 21886071Sache fflush(fd); 21986071Sache} 22086071Sache 22186071Sachevoid 22286071Sachedumpif(fd, ifp) 22386071Sache register struct interface *ifp; 22486071Sache FILE *fd; 22586071Sache{ 22686071Sache if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { 22786071Sache fprintf(fd, "*** Packet history for interface %s ***\n", 22886071Sache ifp->int_name); 22986071Sache dumptrace(fd, "to", &ifp->int_output); 23086071Sache dumptrace(fd, "from", &ifp->int_input); 23186071Sache fprintf(fd, "*** end packet history ***\n"); 23286071Sache } 23386071Sache} 23486071Sache 23586071Sachevoid 23686071Sachedumptrace(fd, dir, ifd) 23786071Sache FILE *fd; 23886071Sache char *dir; 23986071Sache register struct ifdebug *ifd; 24086071Sache{ 24186071Sache register struct iftrace *t; 24286071Sache char *cp = !strcmp(dir, "to") ? "Output" : "Input"; 24386071Sache 24486071Sache if (ifd->ifd_front == ifd->ifd_records && 24586071Sache ifd->ifd_front->ift_size == 0) { 24686071Sache fprintf(fd, "%s: no packets.\n", cp); 24786071Sache return; 24886071Sache } 24986071Sache fprintf(fd, "%s trace:\n", cp); 25086071Sache t = ifd->ifd_front - ifd->ifd_count; 25186071Sache if (t < ifd->ifd_records) 25286071Sache t += NRECORDS; 25386071Sache for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { 25486071Sache if (t >= ifd->ifd_records + NRECORDS) 25586071Sache t = ifd->ifd_records; 25686071Sache if (t->ift_size == 0) 25786071Sache continue; 258 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp), 259 t->ift_metric); 260 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); 261 } 262} 263 264void 265dumppacket(fd, dir, source, cp, size) 266 FILE *fd; 267 char *dir; 268 struct sockaddr *source; 269 char *cp; 270 register int size; 271{ 272 register struct rip *msg = (struct rip *)cp; 273 register struct netinfo *n; 274 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 275 276 if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX) 277 fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)], 278 dir, ipxdp_ntoa(&who->sipx_addr), 279 ntohs(who->sipx_addr.x_port)); 280 else { 281 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd), 282 dir, ipxdp_ntoa(&who->sipx_addr), 283 ntohs(who->sipx_addr.x_port)); 284 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 285 (u_int)cp, (u_int)packet); 286 return; 287 } 288 switch (ntohs(msg->rip_cmd)) { 289 290 case RIPCMD_REQUEST: 291 case RIPCMD_RESPONSE: 292 fprintf(fd, ":\n"); 293 size -= sizeof (u_short); 294 n = msg->rip_nets; 295 for (; size > 0; n++, size -= sizeof (struct netinfo)) { 296 if (size < sizeof (struct netinfo)) 297 break; 298 fprintf(fd, "\tnet %s metric %d ticks %d\n", 299 ipxdp_nettoa(n->rip_dst), 300 ntohs(n->rip_metric), 301 ntohs(n->rip_ticks)); 302 } 303 break; 304 305 } 306} 307 308void 309dumpsappacket(fd, dir, source, cp, size) 310 FILE *fd; 311 char *dir; 312 struct sockaddr *source; 313 char *cp; 314 register int size; 315{ 316 register struct sap_packet *msg = (struct sap_packet *)cp; 317 register struct sap_info *n; 318 struct sockaddr_ipx *who = (struct sockaddr_ipx *)source; 319 320 if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX) 321 fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)], 322 dir, ipxdp_ntoa(&who->sipx_addr), 323 ntohs(who->sipx_addr.x_port)); 324 else { 325 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd), 326 dir, ipxdp_ntoa(&who->sipx_addr), 327 ntohs(who->sipx_addr.x_port)); 328 fprintf(fd, "size=%d cp=%x packet=%x\n", size, 329 (u_int)cp, (u_int)packet); 330 return; 331 } 332 switch (ntohs(msg->sap_cmd)) { 333 334 case SAP_REQ: 335 case SAP_RESP: 336 case SAP_REQ_NEAR: 337 case SAP_RESP_NEAR: 338 fprintf(fd, ":\n"); 339 size -= sizeof (u_short); 340 n = msg->sap; 341 for (; size > 0; n++, size -= sizeof (struct sap_info)) { 342 if (size < sizeof (struct sap_info)) 343 break; 344 fprintf(fd, " service %04X %-20.20s " 345 "addr %s.%04X metric %d\n", 346 ntohs(n->ServType), 347 n->ServName, 348 ipxdp_ntoa(&n->ipx), 349 ntohs(n->ipx.x_port), 350 ntohs(n->hops)); 351 } 352 break; 353 354 } 355} 356 357void 358dumpsaptable(fd, sh) 359 FILE *fd; 360 struct sap_hash *sh; 361{ 362 register struct sap_entry *sap; 363 struct sap_hash *hash; 364 int x = 0; 365 366 fprintf(fd, "------- SAP table dump. -------\n"); 367 for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) { 368 fprintf(fd, "HASH %d\n", x); 369 sap = hash->forw; 370 for (; sap != (struct sap_entry *)hash; sap = sap->forw) { 371 fprintf(fd, " service %04X %-20.20s " 372 "addr %s.%04X %c metric %d\n", 373 ntohs(sap->sap.ServType), 374 sap->sap.ServName, 375 ipxdp_ntoa(&sap->sap.ipx), 376 ntohs(sap->sap.ipx.x_port), 377 (sap->clone ? 'C' : ' '), 378 ntohs(sap->sap.hops)); 379 } 380 } 381 fprintf(fd, "\n"); 382} 383 384union ipx_net_u net; 385 386char * 387ipxdp_nettoa(val) 388union ipx_net val; 389{ 390 static char buf[100]; 391 net.net_e = val; 392 (void)sprintf(buf, "%lx", ntohl(net.long_e)); 393 return (buf); 394} 395 396 397char * 398ipxdp_ntoa(addr) 399struct ipx_addr *addr; 400{ 401 static char buf[100]; 402 403 (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x", 404 ipxdp_nettoa(addr->x_net), 405 addr->x_host.c_host[0], addr->x_host.c_host[1], 406 addr->x_host.c_host[2], addr->x_host.c_host[3], 407 addr->x_host.c_host[4], addr->x_host.c_host[5]); 408 409 return(buf); 410} 411