xref: /csrg-svn/sbin/routed/trace.c (revision 34571)
122001Sdist /*
234564Skarels  * Copyright (c) 1983, 1988 Regents of the University of California.
333489Sbostic  * All rights reserved.
433489Sbostic  *
533489Sbostic  * Redistribution and use in source and binary forms are permitted
633489Sbostic  * provided that this notice is preserved and that due credit is given
733489Sbostic  * to the University of California at Berkeley. The name of the University
833489Sbostic  * may not be used to endorse or promote products derived from this
933489Sbostic  * software without specific prior written permission. This software
1033489Sbostic  * is provided ``as is'' without express or implied warranty.
1122001Sdist  */
1222001Sdist 
139022Ssam #ifndef lint
14*34571Skarels static char sccsid[] = "@(#)trace.c	5.6 (Berkeley) 05/31/88";
1533489Sbostic #endif /* not lint */
169022Ssam 
179022Ssam /*
189022Ssam  * Routing Table Management Daemon
199022Ssam  */
209022Ssam #define	RIPCMDS
2110245Ssam #include "defs.h"
22*34571Skarels #include <sys/file.h>
2328906Skarels #include <sys/stat.h>
2434564Skarels #include <sys/signal.h>
259022Ssam 
269022Ssam #define	NRECORDS	50		/* size of circular trace buffer */
279022Ssam #ifdef DEBUG
289022Ssam FILE	*ftrace = stdout;
2934564Skarels int	traceactions = 1;
309022Ssam #endif
319022Ssam 
329022Ssam traceinit(ifp)
339022Ssam 	register struct interface *ifp;
349022Ssam {
359022Ssam 
369022Ssam 	if (iftraceinit(ifp, &ifp->int_input) &&
379022Ssam 	    iftraceinit(ifp, &ifp->int_output))
389022Ssam 		return;
3934564Skarels 	tracehistory = 0;
409022Ssam 	fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
419022Ssam }
429022Ssam 
439022Ssam static
449022Ssam iftraceinit(ifp, ifd)
459022Ssam 	struct interface *ifp;
469022Ssam 	register struct ifdebug *ifd;
479022Ssam {
489022Ssam 	register struct iftrace *t;
499022Ssam 
509022Ssam 	ifd->ifd_records =
519022Ssam 	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
529022Ssam 	if (ifd->ifd_records == 0)
539022Ssam 		return (0);
549022Ssam 	ifd->ifd_front = ifd->ifd_records;
5516314Skarels 	ifd->ifd_count = 0;
569022Ssam 	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
579022Ssam 		t->ift_size = 0;
589022Ssam 		t->ift_packet = 0;
599022Ssam 	}
609022Ssam 	ifd->ifd_if = ifp;
619022Ssam 	return (1);
629022Ssam }
639022Ssam 
649022Ssam traceon(file)
659022Ssam 	char *file;
669022Ssam {
6728906Skarels 	struct stat stbuf;
689022Ssam 
699022Ssam 	if (ftrace != NULL)
709022Ssam 		return;
7128906Skarels 	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
7228906Skarels 		return;
739022Ssam 	ftrace = fopen(file, "a");
749022Ssam 	if (ftrace == NULL)
759022Ssam 		return;
769022Ssam 	dup2(fileno(ftrace), 1);
779022Ssam 	dup2(fileno(ftrace), 2);
7834564Skarels 	traceactions = 1;
799022Ssam }
809022Ssam 
819022Ssam traceoff()
829022Ssam {
8334564Skarels 	if (!traceactions)
849022Ssam 		return;
85*34571Skarels 	if (ftrace != NULL) {
86*34571Skarels 		int fd = open("/dev/null", O_RDWR);
87*34571Skarels 
88*34571Skarels 		fprintf(ftrace, "Tracing disabled\n");
89*34571Skarels 		(void) dup2(fd, 1);
90*34571Skarels 		(void) dup2(fd, 2);
91*34571Skarels 		(void) close(fd);
929022Ssam 		fclose(ftrace);
93*34571Skarels 		ftrace = NULL;
94*34571Skarels 	}
9534564Skarels 	traceactions = 0;
9634564Skarels 	tracehistory = 0;
979022Ssam }
989022Ssam 
9934564Skarels sigtrace(s)
10034564Skarels 	int s;
10134564Skarels {
10234564Skarels 	if (s == SIGUSR2) {
10334564Skarels 		traceoff();
10434564Skarels 		tracepackets = 0;
10534564Skarels 	} else if (traceactions == 0)
10634564Skarels 		traceactions++;
10734564Skarels 	else if (tracehistory == 0)
10834564Skarels 		tracehistory++;
10934564Skarels 	else {
11034564Skarels 		tracepackets++;
11134564Skarels 		tracehistory = 0;
11234564Skarels 	}
11334564Skarels }
11434564Skarels 
1159022Ssam trace(ifd, who, p, len, m)
1169022Ssam 	register struct ifdebug *ifd;
1179022Ssam 	struct sockaddr *who;
1189022Ssam 	char *p;
1199022Ssam 	int len, m;
1209022Ssam {
1219022Ssam 	register struct iftrace *t;
1229022Ssam 
1239022Ssam 	if (ifd->ifd_records == 0)
1249022Ssam 		return;
1259022Ssam 	t = ifd->ifd_front++;
1269022Ssam 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
1279022Ssam 		ifd->ifd_front = ifd->ifd_records;
12816314Skarels 	if (ifd->ifd_count < NRECORDS)
12916314Skarels 		ifd->ifd_count++;
13026960Skarels 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
1319022Ssam 		free(t->ift_packet);
13226960Skarels 		t->ift_packet = 0;
13326960Skarels 	}
1349022Ssam 	t->ift_stamp = time(0);
1359022Ssam 	t->ift_who = *who;
13626960Skarels 	if (len > 0 && t->ift_packet == 0) {
1379022Ssam 		t->ift_packet = malloc(len);
13826960Skarels 		if (t->ift_packet == 0)
1399022Ssam 			len = 0;
1409022Ssam 	}
14126960Skarels 	if (len > 0)
14226960Skarels 		bcopy(p, t->ift_packet, len);
1439022Ssam 	t->ift_size = len;
1449022Ssam 	t->ift_metric = m;
1459022Ssam }
1469022Ssam 
1479022Ssam traceaction(fd, action, rt)
1489022Ssam 	FILE *fd;
1499022Ssam 	char *action;
1509022Ssam 	struct rt_entry *rt;
1519022Ssam {
1529022Ssam 	struct sockaddr_in *dst, *gate;
1539022Ssam 	static struct bits {
1549022Ssam 		int	t_bits;
1559022Ssam 		char	*t_name;
1569022Ssam 	} flagbits[] = {
1579022Ssam 		{ RTF_UP,	"UP" },
1589022Ssam 		{ RTF_GATEWAY,	"GATEWAY" },
1599022Ssam 		{ RTF_HOST,	"HOST" },
1609022Ssam 		{ 0 }
1619022Ssam 	}, statebits[] = {
1629022Ssam 		{ RTS_PASSIVE,	"PASSIVE" },
1639022Ssam 		{ RTS_REMOTE,	"REMOTE" },
1649022Ssam 		{ RTS_INTERFACE,"INTERFACE" },
1659022Ssam 		{ RTS_CHANGED,	"CHANGED" },
16628906Skarels 		{ RTS_INTERNAL,	"INTERNAL" },
16728906Skarels 		{ RTS_EXTERNAL,	"EXTERNAL" },
16828906Skarels 		{ RTS_SUBNET,	"SUBNET" },
1699022Ssam 		{ 0 }
1709022Ssam 	};
1719022Ssam 	register struct bits *p;
1729022Ssam 	register int first;
1739022Ssam 	char *cp;
1749022Ssam 	struct interface *ifp;
1759022Ssam 
1769022Ssam 	if (fd == NULL)
1779022Ssam 		return;
17834564Skarels 	if (curtime) {
17934564Skarels 		fprintf(fd, "\n%s", curtime);
18034564Skarels 		curtime = NULL;
18134564Skarels 	}
1829022Ssam 	fprintf(fd, "%s ", action);
1839022Ssam 	dst = (struct sockaddr_in *)&rt->rt_dst;
1849022Ssam 	gate = (struct sockaddr_in *)&rt->rt_router;
18515099Ssam 	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
18615099Ssam 	fprintf(fd, "router %s, metric %d, flags",
18715099Ssam 	     inet_ntoa(gate->sin_addr), rt->rt_metric);
1889022Ssam 	cp = " %s";
1899022Ssam 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
1909022Ssam 		if ((rt->rt_flags & p->t_bits) == 0)
1919022Ssam 			continue;
1929022Ssam 		fprintf(fd, cp, p->t_name);
1939022Ssam 		if (first) {
1949022Ssam 			cp = "|%s";
1959022Ssam 			first = 0;
1969022Ssam 		}
1979022Ssam 	}
1989022Ssam 	fprintf(fd, " state");
1999022Ssam 	cp = " %s";
2009022Ssam 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
2019022Ssam 		if ((rt->rt_state & p->t_bits) == 0)
2029022Ssam 			continue;
2039022Ssam 		fprintf(fd, cp, p->t_name);
2049022Ssam 		if (first) {
2059022Ssam 			cp = "|%s";
2069022Ssam 			first = 0;
2079022Ssam 		}
2089022Ssam 	}
20934564Skarels 	fprintf(fd, " timer %d\n", rt->rt_timer);
21016128Skarels 	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
2119022Ssam 		dumpif(fd, rt->rt_ifp);
2129022Ssam 	fflush(fd);
2139022Ssam }
2149022Ssam 
21534564Skarels tracenewmetric(fd, rt, newmetric)
21634564Skarels 	FILE *fd;
21734564Skarels 	struct rt_entry *rt;
21834564Skarels 	int newmetric;
21934564Skarels {
22034564Skarels 	struct sockaddr_in *dst, *gate;
22134564Skarels 
22234564Skarels 	if (fd == NULL)
22334564Skarels 		return;
22434564Skarels 	dst = (struct sockaddr_in *)&rt->rt_dst;
22534564Skarels 	gate = (struct sockaddr_in *)&rt->rt_router;
22634564Skarels 	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
22734564Skarels 	fprintf(fd, "router %s, from %d to %d\n",
22834564Skarels 	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
22934564Skarels 	fflush(fd);
23034564Skarels }
23134564Skarels 
2329022Ssam dumpif(fd, ifp)
2339022Ssam 	register struct interface *ifp;
2349022Ssam {
23516314Skarels 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
23616314Skarels 		fprintf(fd, "*** Packet history for interface %s ***\n",
23716314Skarels 			ifp->int_name);
23834564Skarels #ifdef notneeded
23916314Skarels 		dumptrace(fd, "to", &ifp->int_output);
24034564Skarels #endif
24116314Skarels 		dumptrace(fd, "from", &ifp->int_input);
24216314Skarels 		fprintf(fd, "*** end packet history ***\n");
24316314Skarels 	}
24426960Skarels 	fflush(fd);
2459022Ssam }
2469022Ssam 
2479022Ssam dumptrace(fd, dir, ifd)
2489022Ssam 	FILE *fd;
2499022Ssam 	char *dir;
2509022Ssam 	register struct ifdebug *ifd;
2519022Ssam {
2529022Ssam 	register struct iftrace *t;
2539022Ssam 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
2549022Ssam 
2559022Ssam 	if (ifd->ifd_front == ifd->ifd_records &&
2569022Ssam 	    ifd->ifd_front->ift_size == 0) {
2579022Ssam 		fprintf(fd, "%s: no packets.\n", cp);
25826960Skarels 		fflush(fd);
2599022Ssam 		return;
2609022Ssam 	}
2619022Ssam 	fprintf(fd, "%s trace:\n", cp);
26216314Skarels 	t = ifd->ifd_front - ifd->ifd_count;
26316314Skarels 	if (t < ifd->ifd_records)
26416314Skarels 		t += NRECORDS;
26516314Skarels 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
26616314Skarels 		if (t >= ifd->ifd_records + NRECORDS)
26716314Skarels 			t = ifd->ifd_records;
2689022Ssam 		if (t->ift_size == 0)
2699022Ssam 			continue;
27034564Skarels 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
27134564Skarels 		    &t->ift_stamp);
2729022Ssam 	}
2739022Ssam }
2749022Ssam 
27534564Skarels dumppacket(fd, dir, who, cp, size, tstamp)
2769022Ssam 	FILE *fd;
2779022Ssam 	struct sockaddr_in *who;		/* should be sockaddr */
2789022Ssam 	char *dir, *cp;
2799022Ssam 	register int size;
28034564Skarels 	time_t *tstamp;
2819022Ssam {
2829022Ssam 	register struct rip *msg = (struct rip *)cp;
2839022Ssam 	register struct netinfo *n;
2849022Ssam 
2859022Ssam 	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
28615099Ssam 		fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd],
28715099Ssam 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
2889022Ssam 	else {
28934564Skarels 		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.24s\n", msg->rip_cmd,
29034564Skarels 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
29134564Skarels 		    ctime(tstamp));
2929022Ssam 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
29326960Skarels 		fflush(fd);
2949022Ssam 		return;
2959022Ssam 	}
29634564Skarels 	fprintf(fd, " %.24s:\n", ctime(tstamp));
2979022Ssam 	switch (msg->rip_cmd) {
2989022Ssam 
2999022Ssam 	case RIPCMD_REQUEST:
3009022Ssam 	case RIPCMD_RESPONSE:
3019022Ssam 		size -= 4 * sizeof (char);
3029022Ssam 		n = msg->rip_nets;
3039022Ssam 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
3049022Ssam 			if (size < sizeof (struct netinfo))
3059022Ssam 				break;
30615099Ssam 			fprintf(fd, "\tdst %s metric %d\n",
30715099Ssam #define	satosin(sa)	((struct sockaddr_in *)&sa)
30815099Ssam 			     inet_ntoa(satosin(n->rip_dst)->sin_addr),
30915099Ssam 			     ntohl(n->rip_metric));
3109022Ssam 		}
3119022Ssam 		break;
3129022Ssam 
3139022Ssam 	case RIPCMD_TRACEON:
31434564Skarels 		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
3159022Ssam 		break;
3169022Ssam 
3179022Ssam 	case RIPCMD_TRACEOFF:
3189022Ssam 		break;
3199022Ssam 	}
32026960Skarels 	fflush(fd);
3219022Ssam }
322