xref: /csrg-svn/sbin/routed/trace.c (revision 33489)
122001Sdist /*
222001Sdist  * Copyright (c) 1983 Regents of the University of California.
3*33489Sbostic  * All rights reserved.
4*33489Sbostic  *
5*33489Sbostic  * Redistribution and use in source and binary forms are permitted
6*33489Sbostic  * provided that this notice is preserved and that due credit is given
7*33489Sbostic  * to the University of California at Berkeley. The name of the University
8*33489Sbostic  * may not be used to endorse or promote products derived from this
9*33489Sbostic  * software without specific prior written permission. This software
10*33489Sbostic  * is provided ``as is'' without express or implied warranty.
1122001Sdist  */
1222001Sdist 
139022Ssam #ifndef lint
14*33489Sbostic static char sccsid[] = "@(#)trace.c	5.4 (Berkeley) 02/16/88";
15*33489Sbostic #endif /* not lint */
169022Ssam 
179022Ssam /*
189022Ssam  * Routing Table Management Daemon
199022Ssam  */
209022Ssam #define	RIPCMDS
2110245Ssam #include "defs.h"
2228906Skarels #include <sys/stat.h>
239022Ssam 
249022Ssam #define	NRECORDS	50		/* size of circular trace buffer */
259022Ssam #ifdef DEBUG
269022Ssam FILE	*ftrace = stdout;
279022Ssam int	tracing = 1;
289022Ssam #endif
299022Ssam 
309022Ssam traceinit(ifp)
319022Ssam 	register struct interface *ifp;
329022Ssam {
339022Ssam 
349022Ssam 	if (iftraceinit(ifp, &ifp->int_input) &&
359022Ssam 	    iftraceinit(ifp, &ifp->int_output))
369022Ssam 		return;
379022Ssam 	tracing = 0;
389022Ssam 	fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
399022Ssam }
409022Ssam 
419022Ssam static
429022Ssam iftraceinit(ifp, ifd)
439022Ssam 	struct interface *ifp;
449022Ssam 	register struct ifdebug *ifd;
459022Ssam {
469022Ssam 	register struct iftrace *t;
479022Ssam 
489022Ssam 	ifd->ifd_records =
499022Ssam 	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
509022Ssam 	if (ifd->ifd_records == 0)
519022Ssam 		return (0);
529022Ssam 	ifd->ifd_front = ifd->ifd_records;
5316314Skarels 	ifd->ifd_count = 0;
549022Ssam 	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
559022Ssam 		t->ift_size = 0;
569022Ssam 		t->ift_packet = 0;
579022Ssam 	}
589022Ssam 	ifd->ifd_if = ifp;
599022Ssam 	return (1);
609022Ssam }
619022Ssam 
629022Ssam traceon(file)
639022Ssam 	char *file;
649022Ssam {
6528906Skarels 	struct stat stbuf;
669022Ssam 
679022Ssam 	if (ftrace != NULL)
689022Ssam 		return;
6928906Skarels 	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
7028906Skarels 		return;
719022Ssam 	ftrace = fopen(file, "a");
729022Ssam 	if (ftrace == NULL)
739022Ssam 		return;
749022Ssam 	dup2(fileno(ftrace), 1);
759022Ssam 	dup2(fileno(ftrace), 2);
769022Ssam 	tracing = 1;
779022Ssam }
789022Ssam 
799022Ssam traceoff()
809022Ssam {
819022Ssam 	if (!tracing)
829022Ssam 		return;
839022Ssam 	if (ftrace != NULL)
849022Ssam 		fclose(ftrace);
859022Ssam 	ftrace = NULL;
869022Ssam 	tracing = 0;
879022Ssam }
889022Ssam 
899022Ssam trace(ifd, who, p, len, m)
909022Ssam 	register struct ifdebug *ifd;
919022Ssam 	struct sockaddr *who;
929022Ssam 	char *p;
939022Ssam 	int len, m;
949022Ssam {
959022Ssam 	register struct iftrace *t;
969022Ssam 
979022Ssam 	if (ifd->ifd_records == 0)
989022Ssam 		return;
999022Ssam 	t = ifd->ifd_front++;
1009022Ssam 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
1019022Ssam 		ifd->ifd_front = ifd->ifd_records;
10216314Skarels 	if (ifd->ifd_count < NRECORDS)
10316314Skarels 		ifd->ifd_count++;
10426960Skarels 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
1059022Ssam 		free(t->ift_packet);
10626960Skarels 		t->ift_packet = 0;
10726960Skarels 	}
1089022Ssam 	t->ift_stamp = time(0);
1099022Ssam 	t->ift_who = *who;
11026960Skarels 	if (len > 0 && t->ift_packet == 0) {
1119022Ssam 		t->ift_packet = malloc(len);
11226960Skarels 		if (t->ift_packet == 0)
1139022Ssam 			len = 0;
1149022Ssam 	}
11526960Skarels 	if (len > 0)
11626960Skarels 		bcopy(p, t->ift_packet, len);
1179022Ssam 	t->ift_size = len;
1189022Ssam 	t->ift_metric = m;
1199022Ssam }
1209022Ssam 
1219022Ssam traceaction(fd, action, rt)
1229022Ssam 	FILE *fd;
1239022Ssam 	char *action;
1249022Ssam 	struct rt_entry *rt;
1259022Ssam {
1269022Ssam 	struct sockaddr_in *dst, *gate;
1279022Ssam 	static struct bits {
1289022Ssam 		int	t_bits;
1299022Ssam 		char	*t_name;
1309022Ssam 	} flagbits[] = {
1319022Ssam 		{ RTF_UP,	"UP" },
1329022Ssam 		{ RTF_GATEWAY,	"GATEWAY" },
1339022Ssam 		{ RTF_HOST,	"HOST" },
1349022Ssam 		{ 0 }
1359022Ssam 	}, statebits[] = {
1369022Ssam 		{ RTS_PASSIVE,	"PASSIVE" },
1379022Ssam 		{ RTS_REMOTE,	"REMOTE" },
1389022Ssam 		{ RTS_INTERFACE,"INTERFACE" },
1399022Ssam 		{ RTS_CHANGED,	"CHANGED" },
14028906Skarels 		{ RTS_INTERNAL,	"INTERNAL" },
14128906Skarels 		{ RTS_EXTERNAL,	"EXTERNAL" },
14228906Skarels 		{ RTS_SUBNET,	"SUBNET" },
1439022Ssam 		{ 0 }
1449022Ssam 	};
1459022Ssam 	register struct bits *p;
1469022Ssam 	register int first;
1479022Ssam 	char *cp;
1489022Ssam 	struct interface *ifp;
1499022Ssam 
1509022Ssam 	if (fd == NULL)
1519022Ssam 		return;
1529022Ssam 	fprintf(fd, "%s ", action);
1539022Ssam 	dst = (struct sockaddr_in *)&rt->rt_dst;
1549022Ssam 	gate = (struct sockaddr_in *)&rt->rt_router;
15515099Ssam 	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
15615099Ssam 	fprintf(fd, "router %s, metric %d, flags",
15715099Ssam 	     inet_ntoa(gate->sin_addr), rt->rt_metric);
1589022Ssam 	cp = " %s";
1599022Ssam 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
1609022Ssam 		if ((rt->rt_flags & p->t_bits) == 0)
1619022Ssam 			continue;
1629022Ssam 		fprintf(fd, cp, p->t_name);
1639022Ssam 		if (first) {
1649022Ssam 			cp = "|%s";
1659022Ssam 			first = 0;
1669022Ssam 		}
1679022Ssam 	}
1689022Ssam 	fprintf(fd, " state");
1699022Ssam 	cp = " %s";
1709022Ssam 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
1719022Ssam 		if ((rt->rt_state & p->t_bits) == 0)
1729022Ssam 			continue;
1739022Ssam 		fprintf(fd, cp, p->t_name);
1749022Ssam 		if (first) {
1759022Ssam 			cp = "|%s";
1769022Ssam 			first = 0;
1779022Ssam 		}
1789022Ssam 	}
1799022Ssam 	putc('\n', fd);
18016128Skarels 	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
1819022Ssam 		dumpif(fd, rt->rt_ifp);
1829022Ssam 	fflush(fd);
1839022Ssam }
1849022Ssam 
1859022Ssam dumpif(fd, ifp)
1869022Ssam 	register struct interface *ifp;
1879022Ssam {
18816314Skarels 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
18916314Skarels 		fprintf(fd, "*** Packet history for interface %s ***\n",
19016314Skarels 			ifp->int_name);
19116314Skarels 		dumptrace(fd, "to", &ifp->int_output);
19216314Skarels 		dumptrace(fd, "from", &ifp->int_input);
19316314Skarels 		fprintf(fd, "*** end packet history ***\n");
19416314Skarels 	}
19526960Skarels 	fflush(fd);
1969022Ssam }
1979022Ssam 
1989022Ssam dumptrace(fd, dir, ifd)
1999022Ssam 	FILE *fd;
2009022Ssam 	char *dir;
2019022Ssam 	register struct ifdebug *ifd;
2029022Ssam {
2039022Ssam 	register struct iftrace *t;
2049022Ssam 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
2059022Ssam 
2069022Ssam 	if (ifd->ifd_front == ifd->ifd_records &&
2079022Ssam 	    ifd->ifd_front->ift_size == 0) {
2089022Ssam 		fprintf(fd, "%s: no packets.\n", cp);
20926960Skarels 		fflush(fd);
2109022Ssam 		return;
2119022Ssam 	}
2129022Ssam 	fprintf(fd, "%s trace:\n", cp);
21316314Skarels 	t = ifd->ifd_front - ifd->ifd_count;
21416314Skarels 	if (t < ifd->ifd_records)
21516314Skarels 		t += NRECORDS;
21616314Skarels 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
21716314Skarels 		if (t >= ifd->ifd_records + NRECORDS)
21816314Skarels 			t = ifd->ifd_records;
2199022Ssam 		if (t->ift_size == 0)
2209022Ssam 			continue;
2219022Ssam 		fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
2229022Ssam 			t->ift_metric);
2239022Ssam 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
2249022Ssam 	}
2259022Ssam }
2269022Ssam 
2279022Ssam dumppacket(fd, dir, who, cp, size)
2289022Ssam 	FILE *fd;
2299022Ssam 	struct sockaddr_in *who;		/* should be sockaddr */
2309022Ssam 	char *dir, *cp;
2319022Ssam 	register int size;
2329022Ssam {
2339022Ssam 	register struct rip *msg = (struct rip *)cp;
2349022Ssam 	register struct netinfo *n;
2359022Ssam 
2369022Ssam 	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
23715099Ssam 		fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd],
23815099Ssam 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
2399022Ssam 	else {
2409022Ssam 		fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd,
24115099Ssam 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
2429022Ssam 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
24326960Skarels 		fflush(fd);
2449022Ssam 		return;
2459022Ssam 	}
2469022Ssam 	switch (msg->rip_cmd) {
2479022Ssam 
2489022Ssam 	case RIPCMD_REQUEST:
2499022Ssam 	case RIPCMD_RESPONSE:
2509022Ssam 		fprintf(fd, ":\n");
2519022Ssam 		size -= 4 * sizeof (char);
2529022Ssam 		n = msg->rip_nets;
2539022Ssam 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
2549022Ssam 			if (size < sizeof (struct netinfo))
2559022Ssam 				break;
25615099Ssam 			fprintf(fd, "\tdst %s metric %d\n",
25715099Ssam #define	satosin(sa)	((struct sockaddr_in *)&sa)
25815099Ssam 			     inet_ntoa(satosin(n->rip_dst)->sin_addr),
25915099Ssam 			     ntohl(n->rip_metric));
2609022Ssam 		}
2619022Ssam 		break;
2629022Ssam 
2639022Ssam 	case RIPCMD_TRACEON:
2649022Ssam 		fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile);
2659022Ssam 		break;
2669022Ssam 
2679022Ssam 	case RIPCMD_TRACEOFF:
2689022Ssam 		fprintf(fd, "\n");
2699022Ssam 		break;
2709022Ssam 	}
27126960Skarels 	fflush(fd);
2729022Ssam }
273