xref: /csrg-svn/sbin/routed/trace.c (revision 42712)
122001Sdist /*
234564Skarels  * Copyright (c) 1983, 1988 Regents of the University of California.
333489Sbostic  * All rights reserved.
433489Sbostic  *
5*42712Sbostic  * %sccs.include.redist.c%
622001Sdist  */
722001Sdist 
89022Ssam #ifndef lint
9*42712Sbostic static char sccsid[] = "@(#)trace.c	5.10 (Berkeley) 06/01/90";
1033489Sbostic #endif /* not lint */
119022Ssam 
129022Ssam /*
139022Ssam  * Routing Table Management Daemon
149022Ssam  */
159022Ssam #define	RIPCMDS
1610245Ssam #include "defs.h"
1734571Skarels #include <sys/file.h>
1828906Skarels #include <sys/stat.h>
1934564Skarels #include <sys/signal.h>
2037970Sbostic #include "pathnames.h"
219022Ssam 
229022Ssam #define	NRECORDS	50		/* size of circular trace buffer */
239022Ssam #ifdef DEBUG
249022Ssam FILE	*ftrace = stdout;
2536831Skarels int	traceactions = 0;
269022Ssam #endif
2736831Skarels static	struct timeval lastlog;
2836831Skarels static	char *savetracename;
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;
3734564Skarels 	tracehistory = 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;
7136831Skarels 	savetracename = file;
7236831Skarels 	(void) gettimeofday(&now, (struct timezone *)NULL);
739022Ssam 	ftrace = fopen(file, "a");
749022Ssam 	if (ftrace == NULL)
759022Ssam 		return;
769022Ssam 	dup2(fileno(ftrace), 1);
779022Ssam 	dup2(fileno(ftrace), 2);
7834564Skarels 	traceactions = 1;
7936831Skarels 	fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
809022Ssam }
819022Ssam 
829022Ssam traceoff()
839022Ssam {
8434564Skarels 	if (!traceactions)
859022Ssam 		return;
8634571Skarels 	if (ftrace != NULL) {
8737970Sbostic 		int fd = open(_PATH_DEVNULL, O_RDWR);
8834571Skarels 
8936831Skarels 		fprintf(ftrace, "Tracing disabled %s\n",
9036831Skarels 		    ctime((time_t *)&now.tv_sec));
9136831Skarels 		fflush(ftrace);
9234571Skarels 		(void) dup2(fd, 1);
9334571Skarels 		(void) dup2(fd, 2);
9434571Skarels 		(void) close(fd);
959022Ssam 		fclose(ftrace);
9634571Skarels 		ftrace = NULL;
9734571Skarels 	}
9834564Skarels 	traceactions = 0;
9934564Skarels 	tracehistory = 0;
10036831Skarels 	tracepackets = 0;
10136831Skarels 	tracecontents = 0;
1029022Ssam }
1039022Ssam 
10434564Skarels sigtrace(s)
10534564Skarels 	int s;
10634564Skarels {
10736831Skarels 
10836831Skarels 	if (s == SIGUSR2)
10934564Skarels 		traceoff();
11036831Skarels 	else if (ftrace == NULL && savetracename)
11136831Skarels 		traceon(savetracename);
11236831Skarels 	else
11336831Skarels 		bumploglevel();
11436831Skarels }
11536831Skarels 
11636831Skarels /*
11736831Skarels  * Move to next higher level of tracing when -t option processed or
11836831Skarels  * SIGUSR1 is received.  Successive levels are:
11936831Skarels  *	traceactions
12036831Skarels  *	traceactions + tracepackets
12136831Skarels  *	traceactions + tracehistory (packets and contents after change)
12236831Skarels  *	traceactions + tracepackets + tracecontents
12336831Skarels  */
12436831Skarels bumploglevel()
12536831Skarels {
12636831Skarels 
12736831Skarels 	(void) gettimeofday(&now, (struct timezone *)NULL);
12836831Skarels 	if (traceactions == 0) {
12934564Skarels 		traceactions++;
13036831Skarels 		if (ftrace)
13136831Skarels 			fprintf(ftrace, "Tracing actions started %s\n",
13236831Skarels 			    ctime((time_t *)&now.tv_sec));
13336831Skarels 	} else if (tracepackets == 0) {
13436831Skarels 		tracepackets++;
13536831Skarels 		tracehistory = 0;
13636831Skarels 		tracecontents = 0;
13736831Skarels 		if (ftrace)
13836831Skarels 			fprintf(ftrace, "Tracing packets started %s\n",
13936831Skarels 			    ctime((time_t *)&now.tv_sec));
14036831Skarels 	} else if (tracehistory == 0) {
14134564Skarels 		tracehistory++;
14236831Skarels 		if (ftrace)
14336831Skarels 			fprintf(ftrace, "Tracing history started %s\n",
14436831Skarels 			    ctime((time_t *)&now.tv_sec));
14536831Skarels 	} else {
14634564Skarels 		tracepackets++;
14736831Skarels 		tracecontents++;
14834564Skarels 		tracehistory = 0;
14936831Skarels 		if (ftrace)
15036831Skarels 			fprintf(ftrace, "Tracing packet contents started %s\n",
15136831Skarels 			    ctime((time_t *)&now.tv_sec));
15234564Skarels 	}
15336831Skarels 	if (ftrace)
15436831Skarels 		fflush(ftrace);
15534564Skarels }
15634564Skarels 
1579022Ssam trace(ifd, who, p, len, m)
1589022Ssam 	register struct ifdebug *ifd;
1599022Ssam 	struct sockaddr *who;
1609022Ssam 	char *p;
1619022Ssam 	int len, m;
1629022Ssam {
1639022Ssam 	register struct iftrace *t;
1649022Ssam 
1659022Ssam 	if (ifd->ifd_records == 0)
1669022Ssam 		return;
1679022Ssam 	t = ifd->ifd_front++;
1689022Ssam 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
1699022Ssam 		ifd->ifd_front = ifd->ifd_records;
17016314Skarels 	if (ifd->ifd_count < NRECORDS)
17116314Skarels 		ifd->ifd_count++;
17226960Skarels 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
1739022Ssam 		free(t->ift_packet);
17426960Skarels 		t->ift_packet = 0;
17526960Skarels 	}
17636831Skarels 	t->ift_stamp = now;
1779022Ssam 	t->ift_who = *who;
17826960Skarels 	if (len > 0 && t->ift_packet == 0) {
1799022Ssam 		t->ift_packet = malloc(len);
18026960Skarels 		if (t->ift_packet == 0)
1819022Ssam 			len = 0;
1829022Ssam 	}
18326960Skarels 	if (len > 0)
18426960Skarels 		bcopy(p, t->ift_packet, len);
1859022Ssam 	t->ift_size = len;
1869022Ssam 	t->ift_metric = m;
1879022Ssam }
1889022Ssam 
1899022Ssam traceaction(fd, action, rt)
1909022Ssam 	FILE *fd;
1919022Ssam 	char *action;
1929022Ssam 	struct rt_entry *rt;
1939022Ssam {
1949022Ssam 	struct sockaddr_in *dst, *gate;
1959022Ssam 	static struct bits {
1969022Ssam 		int	t_bits;
1979022Ssam 		char	*t_name;
1989022Ssam 	} flagbits[] = {
1999022Ssam 		{ RTF_UP,	"UP" },
2009022Ssam 		{ RTF_GATEWAY,	"GATEWAY" },
2019022Ssam 		{ RTF_HOST,	"HOST" },
2029022Ssam 		{ 0 }
2039022Ssam 	}, statebits[] = {
2049022Ssam 		{ RTS_PASSIVE,	"PASSIVE" },
2059022Ssam 		{ RTS_REMOTE,	"REMOTE" },
2069022Ssam 		{ RTS_INTERFACE,"INTERFACE" },
2079022Ssam 		{ RTS_CHANGED,	"CHANGED" },
20828906Skarels 		{ RTS_INTERNAL,	"INTERNAL" },
20928906Skarels 		{ RTS_EXTERNAL,	"EXTERNAL" },
21028906Skarels 		{ RTS_SUBNET,	"SUBNET" },
2119022Ssam 		{ 0 }
2129022Ssam 	};
2139022Ssam 	register struct bits *p;
2149022Ssam 	register int first;
2159022Ssam 	char *cp;
2169022Ssam 	struct interface *ifp;
2179022Ssam 
2189022Ssam 	if (fd == NULL)
2199022Ssam 		return;
22036831Skarels 	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
22136831Skarels 		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
22236831Skarels 		lastlog = now;
22334564Skarels 	}
2249022Ssam 	fprintf(fd, "%s ", action);
2259022Ssam 	dst = (struct sockaddr_in *)&rt->rt_dst;
2269022Ssam 	gate = (struct sockaddr_in *)&rt->rt_router;
22715099Ssam 	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
22815099Ssam 	fprintf(fd, "router %s, metric %d, flags",
22915099Ssam 	     inet_ntoa(gate->sin_addr), rt->rt_metric);
2309022Ssam 	cp = " %s";
2319022Ssam 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
2329022Ssam 		if ((rt->rt_flags & p->t_bits) == 0)
2339022Ssam 			continue;
2349022Ssam 		fprintf(fd, cp, p->t_name);
2359022Ssam 		if (first) {
2369022Ssam 			cp = "|%s";
2379022Ssam 			first = 0;
2389022Ssam 		}
2399022Ssam 	}
2409022Ssam 	fprintf(fd, " state");
2419022Ssam 	cp = " %s";
2429022Ssam 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
2439022Ssam 		if ((rt->rt_state & p->t_bits) == 0)
2449022Ssam 			continue;
2459022Ssam 		fprintf(fd, cp, p->t_name);
2469022Ssam 		if (first) {
2479022Ssam 			cp = "|%s";
2489022Ssam 			first = 0;
2499022Ssam 		}
2509022Ssam 	}
25134564Skarels 	fprintf(fd, " timer %d\n", rt->rt_timer);
25236831Skarels 	if (tracehistory && !tracepackets &&
25336831Skarels 	    (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
2549022Ssam 		dumpif(fd, rt->rt_ifp);
2559022Ssam 	fflush(fd);
25636831Skarels 	if (ferror(fd))
25736831Skarels 		traceoff();
2589022Ssam }
2599022Ssam 
26034564Skarels tracenewmetric(fd, rt, newmetric)
26134564Skarels 	FILE *fd;
26234564Skarels 	struct rt_entry *rt;
26334564Skarels 	int newmetric;
26434564Skarels {
26534564Skarels 	struct sockaddr_in *dst, *gate;
26634564Skarels 
26734564Skarels 	if (fd == NULL)
26834564Skarels 		return;
26936831Skarels 	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
27036831Skarels 		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
27136831Skarels 		lastlog = now;
27236831Skarels 	}
27334564Skarels 	dst = (struct sockaddr_in *)&rt->rt_dst;
27434564Skarels 	gate = (struct sockaddr_in *)&rt->rt_router;
27534564Skarels 	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
27634564Skarels 	fprintf(fd, "router %s, from %d to %d\n",
27734564Skarels 	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
27834564Skarels 	fflush(fd);
27936831Skarels 	if (ferror(fd))
28036831Skarels 		traceoff();
28134564Skarels }
28234564Skarels 
2839022Ssam dumpif(fd, ifp)
28436831Skarels 	FILE *fd;
2859022Ssam 	register struct interface *ifp;
2869022Ssam {
28716314Skarels 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
28816314Skarels 		fprintf(fd, "*** Packet history for interface %s ***\n",
28916314Skarels 			ifp->int_name);
29034564Skarels #ifdef notneeded
29116314Skarels 		dumptrace(fd, "to", &ifp->int_output);
29234564Skarels #endif
29316314Skarels 		dumptrace(fd, "from", &ifp->int_input);
29416314Skarels 		fprintf(fd, "*** end packet history ***\n");
29516314Skarels 	}
2969022Ssam }
2979022Ssam 
2989022Ssam dumptrace(fd, dir, ifd)
2999022Ssam 	FILE *fd;
3009022Ssam 	char *dir;
3019022Ssam 	register struct ifdebug *ifd;
3029022Ssam {
3039022Ssam 	register struct iftrace *t;
3049022Ssam 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
3059022Ssam 
3069022Ssam 	if (ifd->ifd_front == ifd->ifd_records &&
3079022Ssam 	    ifd->ifd_front->ift_size == 0) {
3089022Ssam 		fprintf(fd, "%s: no packets.\n", cp);
30926960Skarels 		fflush(fd);
3109022Ssam 		return;
3119022Ssam 	}
3129022Ssam 	fprintf(fd, "%s trace:\n", cp);
31316314Skarels 	t = ifd->ifd_front - ifd->ifd_count;
31416314Skarels 	if (t < ifd->ifd_records)
31516314Skarels 		t += NRECORDS;
31616314Skarels 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
31716314Skarels 		if (t >= ifd->ifd_records + NRECORDS)
31816314Skarels 			t = ifd->ifd_records;
3199022Ssam 		if (t->ift_size == 0)
3209022Ssam 			continue;
32134564Skarels 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
32234564Skarels 		    &t->ift_stamp);
3239022Ssam 	}
3249022Ssam }
3259022Ssam 
32636831Skarels dumppacket(fd, dir, who, cp, size, stamp)
3279022Ssam 	FILE *fd;
3289022Ssam 	struct sockaddr_in *who;		/* should be sockaddr */
3299022Ssam 	char *dir, *cp;
3309022Ssam 	register int size;
33136831Skarels 	struct timeval *stamp;
3329022Ssam {
3339022Ssam 	register struct rip *msg = (struct rip *)cp;
3349022Ssam 	register struct netinfo *n;
3359022Ssam 
33636831Skarels 	if (fd == NULL)
33736831Skarels 		return;
3389022Ssam 	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
33936831Skarels 		fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
34036831Skarels 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
34136831Skarels 		    ctime((time_t *)&stamp->tv_sec));
34236831Skarels 	else {
34336831Skarels 		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
34415099Ssam 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
34536831Skarels 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
34636831Skarels 		    ctime((time_t *)&stamp->tv_sec));
34726960Skarels 		fflush(fd);
3489022Ssam 		return;
3499022Ssam 	}
35036831Skarels 	if (tracepackets && tracecontents == 0) {
35136831Skarels 		fflush(fd);
35236831Skarels 		return;
35336831Skarels 	}
3549022Ssam 	switch (msg->rip_cmd) {
3559022Ssam 
3569022Ssam 	case RIPCMD_REQUEST:
3579022Ssam 	case RIPCMD_RESPONSE:
3589022Ssam 		size -= 4 * sizeof (char);
3599022Ssam 		n = msg->rip_nets;
3609022Ssam 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
36136831Skarels 			if (size < sizeof (struct netinfo)) {
36236831Skarels 				fprintf(fd, "(truncated record, len %d)\n",
36336831Skarels 				    size);
3649022Ssam 				break;
36536831Skarels 			}
36636831Skarels 			if (sizeof(n->rip_dst.sa_family) > 1)
36736831Skarels 			    n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
36836831Skarels 
36936831Skarels 			switch ((int)n->rip_dst.sa_family) {
37036831Skarels 
37136831Skarels 			case AF_INET:
37236831Skarels 				fprintf(fd, "\tdst %s metric %d\n",
37315099Ssam #define	satosin(sa)	((struct sockaddr_in *)&sa)
37436831Skarels 				     inet_ntoa(satosin(n->rip_dst)->sin_addr),
37536831Skarels 				     ntohl(n->rip_metric));
37636831Skarels 				break;
37736831Skarels 
37836831Skarels 			default:
37936831Skarels 				fprintf(fd, "\taf %d? metric %d\n",
38036831Skarels 				     n->rip_dst.sa_family,
38136831Skarels 				     ntohl(n->rip_metric));
38236831Skarels 				break;
38336831Skarels 			}
3849022Ssam 		}
3859022Ssam 		break;
3869022Ssam 
3879022Ssam 	case RIPCMD_TRACEON:
38834564Skarels 		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
3899022Ssam 		break;
3909022Ssam 
3919022Ssam 	case RIPCMD_TRACEOFF:
3929022Ssam 		break;
3939022Ssam 	}
39426960Skarels 	fflush(fd);
39536831Skarels 	if (ferror(fd))
39636831Skarels 		traceoff();
3979022Ssam }
398