xref: /csrg-svn/sbin/routed/trace.c (revision 69003)
122001Sdist /*
261540Sbostic  * Copyright (c) 1983, 1988, 1993
361540Sbostic  *	The Regents of the University of California.  All rights reserved.
433489Sbostic  *
542712Sbostic  * %sccs.include.redist.c%
622001Sdist  */
722001Sdist 
89022Ssam #ifndef lint
9*69003Sbostic static char sccsid[] = "@(#)trace.c	8.2 (Berkeley) 04/28/95";
1033489Sbostic #endif /* not lint */
119022Ssam 
129022Ssam /*
139022Ssam  * Routing Table Management Daemon
149022Ssam  */
159022Ssam #define	RIPCMDS
1610245Ssam #include "defs.h"
1728906Skarels #include <sys/stat.h>
1834564Skarels #include <sys/signal.h>
1946784Sbostic #include <fcntl.h>
2046784Sbostic #include <stdlib.h>
2137970Sbostic #include "pathnames.h"
229022Ssam 
239022Ssam #define	NRECORDS	50		/* size of circular trace buffer */
249022Ssam #ifdef DEBUG
259022Ssam FILE	*ftrace = stdout;
2636831Skarels int	traceactions = 0;
279022Ssam #endif
2836831Skarels static	struct timeval lastlog;
2936831Skarels static	char *savetracename;
309022Ssam 
319022Ssam traceinit(ifp)
329022Ssam 	register struct interface *ifp;
339022Ssam {
3446784Sbostic 	static int iftraceinit();
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;
7336831Skarels 	savetracename = file;
7436831Skarels 	(void) gettimeofday(&now, (struct timezone *)NULL);
759022Ssam 	ftrace = fopen(file, "a");
769022Ssam 	if (ftrace == NULL)
779022Ssam 		return;
789022Ssam 	dup2(fileno(ftrace), 1);
799022Ssam 	dup2(fileno(ftrace), 2);
8034564Skarels 	traceactions = 1;
8136831Skarels 	fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
829022Ssam }
839022Ssam 
849022Ssam traceoff()
859022Ssam {
8634564Skarels 	if (!traceactions)
879022Ssam 		return;
8834571Skarels 	if (ftrace != NULL) {
8937970Sbostic 		int fd = open(_PATH_DEVNULL, O_RDWR);
9034571Skarels 
9136831Skarels 		fprintf(ftrace, "Tracing disabled %s\n",
9236831Skarels 		    ctime((time_t *)&now.tv_sec));
9336831Skarels 		fflush(ftrace);
9434571Skarels 		(void) dup2(fd, 1);
9534571Skarels 		(void) dup2(fd, 2);
9634571Skarels 		(void) close(fd);
979022Ssam 		fclose(ftrace);
9834571Skarels 		ftrace = NULL;
9934571Skarels 	}
10034564Skarels 	traceactions = 0;
10134564Skarels 	tracehistory = 0;
10236831Skarels 	tracepackets = 0;
10336831Skarels 	tracecontents = 0;
1049022Ssam }
1059022Ssam 
10646784Sbostic void
10734564Skarels sigtrace(s)
10834564Skarels 	int s;
10934564Skarels {
11036831Skarels 
11136831Skarels 	if (s == SIGUSR2)
11234564Skarels 		traceoff();
11336831Skarels 	else if (ftrace == NULL && savetracename)
11436831Skarels 		traceon(savetracename);
11536831Skarels 	else
11636831Skarels 		bumploglevel();
11736831Skarels }
11836831Skarels 
11936831Skarels /*
12036831Skarels  * Move to next higher level of tracing when -t option processed or
12136831Skarels  * SIGUSR1 is received.  Successive levels are:
12236831Skarels  *	traceactions
12336831Skarels  *	traceactions + tracepackets
12436831Skarels  *	traceactions + tracehistory (packets and contents after change)
12536831Skarels  *	traceactions + tracepackets + tracecontents
12636831Skarels  */
12736831Skarels bumploglevel()
12836831Skarels {
12936831Skarels 
13036831Skarels 	(void) gettimeofday(&now, (struct timezone *)NULL);
13136831Skarels 	if (traceactions == 0) {
13234564Skarels 		traceactions++;
13336831Skarels 		if (ftrace)
13436831Skarels 			fprintf(ftrace, "Tracing actions started %s\n",
13536831Skarels 			    ctime((time_t *)&now.tv_sec));
13636831Skarels 	} else if (tracepackets == 0) {
13736831Skarels 		tracepackets++;
13836831Skarels 		tracehistory = 0;
13936831Skarels 		tracecontents = 0;
14036831Skarels 		if (ftrace)
14136831Skarels 			fprintf(ftrace, "Tracing packets started %s\n",
14236831Skarels 			    ctime((time_t *)&now.tv_sec));
14336831Skarels 	} else if (tracehistory == 0) {
14434564Skarels 		tracehistory++;
14536831Skarels 		if (ftrace)
14636831Skarels 			fprintf(ftrace, "Tracing history started %s\n",
14736831Skarels 			    ctime((time_t *)&now.tv_sec));
14836831Skarels 	} else {
14934564Skarels 		tracepackets++;
15036831Skarels 		tracecontents++;
15134564Skarels 		tracehistory = 0;
15236831Skarels 		if (ftrace)
15336831Skarels 			fprintf(ftrace, "Tracing packet contents started %s\n",
15436831Skarels 			    ctime((time_t *)&now.tv_sec));
15534564Skarels 	}
15636831Skarels 	if (ftrace)
15736831Skarels 		fflush(ftrace);
15834564Skarels }
15934564Skarels 
1609022Ssam trace(ifd, who, p, len, m)
1619022Ssam 	register struct ifdebug *ifd;
1629022Ssam 	struct sockaddr *who;
1639022Ssam 	char *p;
1649022Ssam 	int len, m;
1659022Ssam {
1669022Ssam 	register struct iftrace *t;
1679022Ssam 
1689022Ssam 	if (ifd->ifd_records == 0)
1699022Ssam 		return;
1709022Ssam 	t = ifd->ifd_front++;
1719022Ssam 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
1729022Ssam 		ifd->ifd_front = ifd->ifd_records;
17316314Skarels 	if (ifd->ifd_count < NRECORDS)
17416314Skarels 		ifd->ifd_count++;
17526960Skarels 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
1769022Ssam 		free(t->ift_packet);
17726960Skarels 		t->ift_packet = 0;
17826960Skarels 	}
17936831Skarels 	t->ift_stamp = now;
1809022Ssam 	t->ift_who = *who;
18126960Skarels 	if (len > 0 && t->ift_packet == 0) {
1829022Ssam 		t->ift_packet = malloc(len);
18326960Skarels 		if (t->ift_packet == 0)
1849022Ssam 			len = 0;
1859022Ssam 	}
18626960Skarels 	if (len > 0)
187*69003Sbostic 		memmove(t->ift_packet, p, len);
1889022Ssam 	t->ift_size = len;
1899022Ssam 	t->ift_metric = m;
1909022Ssam }
1919022Ssam 
1929022Ssam traceaction(fd, action, rt)
1939022Ssam 	FILE *fd;
1949022Ssam 	char *action;
1959022Ssam 	struct rt_entry *rt;
1969022Ssam {
1979022Ssam 	struct sockaddr_in *dst, *gate;
1989022Ssam 	static struct bits {
1999022Ssam 		int	t_bits;
2009022Ssam 		char	*t_name;
2019022Ssam 	} flagbits[] = {
2029022Ssam 		{ RTF_UP,	"UP" },
2039022Ssam 		{ RTF_GATEWAY,	"GATEWAY" },
2049022Ssam 		{ RTF_HOST,	"HOST" },
2059022Ssam 		{ 0 }
2069022Ssam 	}, statebits[] = {
2079022Ssam 		{ RTS_PASSIVE,	"PASSIVE" },
2089022Ssam 		{ RTS_REMOTE,	"REMOTE" },
2099022Ssam 		{ RTS_INTERFACE,"INTERFACE" },
2109022Ssam 		{ RTS_CHANGED,	"CHANGED" },
21128906Skarels 		{ RTS_INTERNAL,	"INTERNAL" },
21228906Skarels 		{ RTS_EXTERNAL,	"EXTERNAL" },
21328906Skarels 		{ RTS_SUBNET,	"SUBNET" },
2149022Ssam 		{ 0 }
2159022Ssam 	};
2169022Ssam 	register struct bits *p;
2179022Ssam 	register int first;
2189022Ssam 	char *cp;
2199022Ssam 	struct interface *ifp;
2209022Ssam 
2219022Ssam 	if (fd == NULL)
2229022Ssam 		return;
22336831Skarels 	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
22436831Skarels 		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
22536831Skarels 		lastlog = now;
22634564Skarels 	}
2279022Ssam 	fprintf(fd, "%s ", action);
2289022Ssam 	dst = (struct sockaddr_in *)&rt->rt_dst;
2299022Ssam 	gate = (struct sockaddr_in *)&rt->rt_router;
23015099Ssam 	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
23115099Ssam 	fprintf(fd, "router %s, metric %d, flags",
23215099Ssam 	     inet_ntoa(gate->sin_addr), rt->rt_metric);
2339022Ssam 	cp = " %s";
2349022Ssam 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
2359022Ssam 		if ((rt->rt_flags & p->t_bits) == 0)
2369022Ssam 			continue;
2379022Ssam 		fprintf(fd, cp, p->t_name);
2389022Ssam 		if (first) {
2399022Ssam 			cp = "|%s";
2409022Ssam 			first = 0;
2419022Ssam 		}
2429022Ssam 	}
2439022Ssam 	fprintf(fd, " state");
2449022Ssam 	cp = " %s";
2459022Ssam 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
2469022Ssam 		if ((rt->rt_state & p->t_bits) == 0)
2479022Ssam 			continue;
2489022Ssam 		fprintf(fd, cp, p->t_name);
2499022Ssam 		if (first) {
2509022Ssam 			cp = "|%s";
2519022Ssam 			first = 0;
2529022Ssam 		}
2539022Ssam 	}
25434564Skarels 	fprintf(fd, " timer %d\n", rt->rt_timer);
25536831Skarels 	if (tracehistory && !tracepackets &&
25636831Skarels 	    (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
2579022Ssam 		dumpif(fd, rt->rt_ifp);
2589022Ssam 	fflush(fd);
25936831Skarels 	if (ferror(fd))
26036831Skarels 		traceoff();
2619022Ssam }
2629022Ssam 
26334564Skarels tracenewmetric(fd, rt, newmetric)
26434564Skarels 	FILE *fd;
26534564Skarels 	struct rt_entry *rt;
26634564Skarels 	int newmetric;
26734564Skarels {
26834564Skarels 	struct sockaddr_in *dst, *gate;
26934564Skarels 
27034564Skarels 	if (fd == NULL)
27134564Skarels 		return;
27236831Skarels 	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
27336831Skarels 		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
27436831Skarels 		lastlog = now;
27536831Skarels 	}
27634564Skarels 	dst = (struct sockaddr_in *)&rt->rt_dst;
27734564Skarels 	gate = (struct sockaddr_in *)&rt->rt_router;
27834564Skarels 	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
27934564Skarels 	fprintf(fd, "router %s, from %d to %d\n",
28034564Skarels 	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
28134564Skarels 	fflush(fd);
28236831Skarels 	if (ferror(fd))
28336831Skarels 		traceoff();
28434564Skarels }
28534564Skarels 
2869022Ssam dumpif(fd, ifp)
28736831Skarels 	FILE *fd;
2889022Ssam 	register struct interface *ifp;
2899022Ssam {
29016314Skarels 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
29116314Skarels 		fprintf(fd, "*** Packet history for interface %s ***\n",
29216314Skarels 			ifp->int_name);
29334564Skarels #ifdef notneeded
29416314Skarels 		dumptrace(fd, "to", &ifp->int_output);
29534564Skarels #endif
29616314Skarels 		dumptrace(fd, "from", &ifp->int_input);
29716314Skarels 		fprintf(fd, "*** end packet history ***\n");
29816314Skarels 	}
2999022Ssam }
3009022Ssam 
3019022Ssam dumptrace(fd, dir, ifd)
3029022Ssam 	FILE *fd;
3039022Ssam 	char *dir;
3049022Ssam 	register struct ifdebug *ifd;
3059022Ssam {
3069022Ssam 	register struct iftrace *t;
3079022Ssam 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
3089022Ssam 
3099022Ssam 	if (ifd->ifd_front == ifd->ifd_records &&
3109022Ssam 	    ifd->ifd_front->ift_size == 0) {
3119022Ssam 		fprintf(fd, "%s: no packets.\n", cp);
31226960Skarels 		fflush(fd);
3139022Ssam 		return;
3149022Ssam 	}
3159022Ssam 	fprintf(fd, "%s trace:\n", cp);
31616314Skarels 	t = ifd->ifd_front - ifd->ifd_count;
31716314Skarels 	if (t < ifd->ifd_records)
31816314Skarels 		t += NRECORDS;
31916314Skarels 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
32016314Skarels 		if (t >= ifd->ifd_records + NRECORDS)
32116314Skarels 			t = ifd->ifd_records;
3229022Ssam 		if (t->ift_size == 0)
3239022Ssam 			continue;
32434564Skarels 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
32534564Skarels 		    &t->ift_stamp);
3269022Ssam 	}
3279022Ssam }
3289022Ssam 
32936831Skarels dumppacket(fd, dir, who, cp, size, stamp)
3309022Ssam 	FILE *fd;
3319022Ssam 	struct sockaddr_in *who;		/* should be sockaddr */
3329022Ssam 	char *dir, *cp;
3339022Ssam 	register int size;
33436831Skarels 	struct timeval *stamp;
3359022Ssam {
3369022Ssam 	register struct rip *msg = (struct rip *)cp;
3379022Ssam 	register struct netinfo *n;
3389022Ssam 
33936831Skarels 	if (fd == NULL)
34036831Skarels 		return;
3419022Ssam 	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
34236831Skarels 		fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
34336831Skarels 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
34436831Skarels 		    ctime((time_t *)&stamp->tv_sec));
34536831Skarels 	else {
34636831Skarels 		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
34715099Ssam 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
34836831Skarels 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
34936831Skarels 		    ctime((time_t *)&stamp->tv_sec));
35026960Skarels 		fflush(fd);
3519022Ssam 		return;
3529022Ssam 	}
35336831Skarels 	if (tracepackets && tracecontents == 0) {
35436831Skarels 		fflush(fd);
35536831Skarels 		return;
35636831Skarels 	}
3579022Ssam 	switch (msg->rip_cmd) {
3589022Ssam 
3599022Ssam 	case RIPCMD_REQUEST:
3609022Ssam 	case RIPCMD_RESPONSE:
3619022Ssam 		size -= 4 * sizeof (char);
3629022Ssam 		n = msg->rip_nets;
3639022Ssam 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
36436831Skarels 			if (size < sizeof (struct netinfo)) {
36536831Skarels 				fprintf(fd, "(truncated record, len %d)\n",
36636831Skarels 				    size);
3679022Ssam 				break;
36836831Skarels 			}
36936831Skarels 			if (sizeof(n->rip_dst.sa_family) > 1)
37036831Skarels 			    n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
37136831Skarels 
37236831Skarels 			switch ((int)n->rip_dst.sa_family) {
37336831Skarels 
37436831Skarels 			case AF_INET:
37536831Skarels 				fprintf(fd, "\tdst %s metric %d\n",
37615099Ssam #define	satosin(sa)	((struct sockaddr_in *)&sa)
37736831Skarels 				     inet_ntoa(satosin(n->rip_dst)->sin_addr),
37836831Skarels 				     ntohl(n->rip_metric));
37936831Skarels 				break;
38036831Skarels 
38136831Skarels 			default:
38236831Skarels 				fprintf(fd, "\taf %d? metric %d\n",
38336831Skarels 				     n->rip_dst.sa_family,
38436831Skarels 				     ntohl(n->rip_metric));
38536831Skarels 				break;
38636831Skarels 			}
3879022Ssam 		}
3889022Ssam 		break;
3899022Ssam 
3909022Ssam 	case RIPCMD_TRACEON:
39134564Skarels 		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
3929022Ssam 		break;
3939022Ssam 
3949022Ssam 	case RIPCMD_TRACEOFF:
3959022Ssam 		break;
3969022Ssam 	}
39726960Skarels 	fflush(fd);
39836831Skarels 	if (ferror(fd))
39936831Skarels 		traceoff();
4009022Ssam }
401