xref: /csrg-svn/sbin/routed/trace.c (revision 37970)
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
634771Sbostic  * provided that the above copyright notice and this paragraph are
734771Sbostic  * duplicated in all such forms and that any documentation,
834771Sbostic  * advertising materials, and other materials related to such
934771Sbostic  * distribution and use acknowledge that the software was developed
1034771Sbostic  * by the University of California, Berkeley.  The name of the
1134771Sbostic  * University may not be used to endorse or promote products derived
1234771Sbostic  * from this software without specific prior written permission.
1334771Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434771Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534771Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1622001Sdist  */
1722001Sdist 
189022Ssam #ifndef lint
19*37970Sbostic static char sccsid[] = "@(#)trace.c	5.9 (Berkeley) 05/11/89";
2033489Sbostic #endif /* not lint */
219022Ssam 
229022Ssam /*
239022Ssam  * Routing Table Management Daemon
249022Ssam  */
259022Ssam #define	RIPCMDS
2610245Ssam #include "defs.h"
2734571Skarels #include <sys/file.h>
2828906Skarels #include <sys/stat.h>
2934564Skarels #include <sys/signal.h>
30*37970Sbostic #include "pathnames.h"
319022Ssam 
329022Ssam #define	NRECORDS	50		/* size of circular trace buffer */
339022Ssam #ifdef DEBUG
349022Ssam FILE	*ftrace = stdout;
3536831Skarels int	traceactions = 0;
369022Ssam #endif
3736831Skarels static	struct timeval lastlog;
3836831Skarels static	char *savetracename;
399022Ssam 
409022Ssam traceinit(ifp)
419022Ssam 	register struct interface *ifp;
429022Ssam {
439022Ssam 
449022Ssam 	if (iftraceinit(ifp, &ifp->int_input) &&
459022Ssam 	    iftraceinit(ifp, &ifp->int_output))
469022Ssam 		return;
4734564Skarels 	tracehistory = 0;
489022Ssam 	fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
499022Ssam }
509022Ssam 
519022Ssam static
529022Ssam iftraceinit(ifp, ifd)
539022Ssam 	struct interface *ifp;
549022Ssam 	register struct ifdebug *ifd;
559022Ssam {
569022Ssam 	register struct iftrace *t;
579022Ssam 
589022Ssam 	ifd->ifd_records =
599022Ssam 	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
609022Ssam 	if (ifd->ifd_records == 0)
619022Ssam 		return (0);
629022Ssam 	ifd->ifd_front = ifd->ifd_records;
6316314Skarels 	ifd->ifd_count = 0;
649022Ssam 	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
659022Ssam 		t->ift_size = 0;
669022Ssam 		t->ift_packet = 0;
679022Ssam 	}
689022Ssam 	ifd->ifd_if = ifp;
699022Ssam 	return (1);
709022Ssam }
719022Ssam 
729022Ssam traceon(file)
739022Ssam 	char *file;
749022Ssam {
7528906Skarels 	struct stat stbuf;
769022Ssam 
779022Ssam 	if (ftrace != NULL)
789022Ssam 		return;
7928906Skarels 	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
8028906Skarels 		return;
8136831Skarels 	savetracename = file;
8236831Skarels 	(void) gettimeofday(&now, (struct timezone *)NULL);
839022Ssam 	ftrace = fopen(file, "a");
849022Ssam 	if (ftrace == NULL)
859022Ssam 		return;
869022Ssam 	dup2(fileno(ftrace), 1);
879022Ssam 	dup2(fileno(ftrace), 2);
8834564Skarels 	traceactions = 1;
8936831Skarels 	fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
909022Ssam }
919022Ssam 
929022Ssam traceoff()
939022Ssam {
9434564Skarels 	if (!traceactions)
959022Ssam 		return;
9634571Skarels 	if (ftrace != NULL) {
97*37970Sbostic 		int fd = open(_PATH_DEVNULL, O_RDWR);
9834571Skarels 
9936831Skarels 		fprintf(ftrace, "Tracing disabled %s\n",
10036831Skarels 		    ctime((time_t *)&now.tv_sec));
10136831Skarels 		fflush(ftrace);
10234571Skarels 		(void) dup2(fd, 1);
10334571Skarels 		(void) dup2(fd, 2);
10434571Skarels 		(void) close(fd);
1059022Ssam 		fclose(ftrace);
10634571Skarels 		ftrace = NULL;
10734571Skarels 	}
10834564Skarels 	traceactions = 0;
10934564Skarels 	tracehistory = 0;
11036831Skarels 	tracepackets = 0;
11136831Skarels 	tracecontents = 0;
1129022Ssam }
1139022Ssam 
11434564Skarels sigtrace(s)
11534564Skarels 	int s;
11634564Skarels {
11736831Skarels 
11836831Skarels 	if (s == SIGUSR2)
11934564Skarels 		traceoff();
12036831Skarels 	else if (ftrace == NULL && savetracename)
12136831Skarels 		traceon(savetracename);
12236831Skarels 	else
12336831Skarels 		bumploglevel();
12436831Skarels }
12536831Skarels 
12636831Skarels /*
12736831Skarels  * Move to next higher level of tracing when -t option processed or
12836831Skarels  * SIGUSR1 is received.  Successive levels are:
12936831Skarels  *	traceactions
13036831Skarels  *	traceactions + tracepackets
13136831Skarels  *	traceactions + tracehistory (packets and contents after change)
13236831Skarels  *	traceactions + tracepackets + tracecontents
13336831Skarels  */
13436831Skarels bumploglevel()
13536831Skarels {
13636831Skarels 
13736831Skarels 	(void) gettimeofday(&now, (struct timezone *)NULL);
13836831Skarels 	if (traceactions == 0) {
13934564Skarels 		traceactions++;
14036831Skarels 		if (ftrace)
14136831Skarels 			fprintf(ftrace, "Tracing actions started %s\n",
14236831Skarels 			    ctime((time_t *)&now.tv_sec));
14336831Skarels 	} else if (tracepackets == 0) {
14436831Skarels 		tracepackets++;
14536831Skarels 		tracehistory = 0;
14636831Skarels 		tracecontents = 0;
14736831Skarels 		if (ftrace)
14836831Skarels 			fprintf(ftrace, "Tracing packets started %s\n",
14936831Skarels 			    ctime((time_t *)&now.tv_sec));
15036831Skarels 	} else if (tracehistory == 0) {
15134564Skarels 		tracehistory++;
15236831Skarels 		if (ftrace)
15336831Skarels 			fprintf(ftrace, "Tracing history started %s\n",
15436831Skarels 			    ctime((time_t *)&now.tv_sec));
15536831Skarels 	} else {
15634564Skarels 		tracepackets++;
15736831Skarels 		tracecontents++;
15834564Skarels 		tracehistory = 0;
15936831Skarels 		if (ftrace)
16036831Skarels 			fprintf(ftrace, "Tracing packet contents started %s\n",
16136831Skarels 			    ctime((time_t *)&now.tv_sec));
16234564Skarels 	}
16336831Skarels 	if (ftrace)
16436831Skarels 		fflush(ftrace);
16534564Skarels }
16634564Skarels 
1679022Ssam trace(ifd, who, p, len, m)
1689022Ssam 	register struct ifdebug *ifd;
1699022Ssam 	struct sockaddr *who;
1709022Ssam 	char *p;
1719022Ssam 	int len, m;
1729022Ssam {
1739022Ssam 	register struct iftrace *t;
1749022Ssam 
1759022Ssam 	if (ifd->ifd_records == 0)
1769022Ssam 		return;
1779022Ssam 	t = ifd->ifd_front++;
1789022Ssam 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
1799022Ssam 		ifd->ifd_front = ifd->ifd_records;
18016314Skarels 	if (ifd->ifd_count < NRECORDS)
18116314Skarels 		ifd->ifd_count++;
18226960Skarels 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
1839022Ssam 		free(t->ift_packet);
18426960Skarels 		t->ift_packet = 0;
18526960Skarels 	}
18636831Skarels 	t->ift_stamp = now;
1879022Ssam 	t->ift_who = *who;
18826960Skarels 	if (len > 0 && t->ift_packet == 0) {
1899022Ssam 		t->ift_packet = malloc(len);
19026960Skarels 		if (t->ift_packet == 0)
1919022Ssam 			len = 0;
1929022Ssam 	}
19326960Skarels 	if (len > 0)
19426960Skarels 		bcopy(p, t->ift_packet, len);
1959022Ssam 	t->ift_size = len;
1969022Ssam 	t->ift_metric = m;
1979022Ssam }
1989022Ssam 
1999022Ssam traceaction(fd, action, rt)
2009022Ssam 	FILE *fd;
2019022Ssam 	char *action;
2029022Ssam 	struct rt_entry *rt;
2039022Ssam {
2049022Ssam 	struct sockaddr_in *dst, *gate;
2059022Ssam 	static struct bits {
2069022Ssam 		int	t_bits;
2079022Ssam 		char	*t_name;
2089022Ssam 	} flagbits[] = {
2099022Ssam 		{ RTF_UP,	"UP" },
2109022Ssam 		{ RTF_GATEWAY,	"GATEWAY" },
2119022Ssam 		{ RTF_HOST,	"HOST" },
2129022Ssam 		{ 0 }
2139022Ssam 	}, statebits[] = {
2149022Ssam 		{ RTS_PASSIVE,	"PASSIVE" },
2159022Ssam 		{ RTS_REMOTE,	"REMOTE" },
2169022Ssam 		{ RTS_INTERFACE,"INTERFACE" },
2179022Ssam 		{ RTS_CHANGED,	"CHANGED" },
21828906Skarels 		{ RTS_INTERNAL,	"INTERNAL" },
21928906Skarels 		{ RTS_EXTERNAL,	"EXTERNAL" },
22028906Skarels 		{ RTS_SUBNET,	"SUBNET" },
2219022Ssam 		{ 0 }
2229022Ssam 	};
2239022Ssam 	register struct bits *p;
2249022Ssam 	register int first;
2259022Ssam 	char *cp;
2269022Ssam 	struct interface *ifp;
2279022Ssam 
2289022Ssam 	if (fd == NULL)
2299022Ssam 		return;
23036831Skarels 	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
23136831Skarels 		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
23236831Skarels 		lastlog = now;
23334564Skarels 	}
2349022Ssam 	fprintf(fd, "%s ", action);
2359022Ssam 	dst = (struct sockaddr_in *)&rt->rt_dst;
2369022Ssam 	gate = (struct sockaddr_in *)&rt->rt_router;
23715099Ssam 	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
23815099Ssam 	fprintf(fd, "router %s, metric %d, flags",
23915099Ssam 	     inet_ntoa(gate->sin_addr), rt->rt_metric);
2409022Ssam 	cp = " %s";
2419022Ssam 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
2429022Ssam 		if ((rt->rt_flags & p->t_bits) == 0)
2439022Ssam 			continue;
2449022Ssam 		fprintf(fd, cp, p->t_name);
2459022Ssam 		if (first) {
2469022Ssam 			cp = "|%s";
2479022Ssam 			first = 0;
2489022Ssam 		}
2499022Ssam 	}
2509022Ssam 	fprintf(fd, " state");
2519022Ssam 	cp = " %s";
2529022Ssam 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
2539022Ssam 		if ((rt->rt_state & p->t_bits) == 0)
2549022Ssam 			continue;
2559022Ssam 		fprintf(fd, cp, p->t_name);
2569022Ssam 		if (first) {
2579022Ssam 			cp = "|%s";
2589022Ssam 			first = 0;
2599022Ssam 		}
2609022Ssam 	}
26134564Skarels 	fprintf(fd, " timer %d\n", rt->rt_timer);
26236831Skarels 	if (tracehistory && !tracepackets &&
26336831Skarels 	    (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
2649022Ssam 		dumpif(fd, rt->rt_ifp);
2659022Ssam 	fflush(fd);
26636831Skarels 	if (ferror(fd))
26736831Skarels 		traceoff();
2689022Ssam }
2699022Ssam 
27034564Skarels tracenewmetric(fd, rt, newmetric)
27134564Skarels 	FILE *fd;
27234564Skarels 	struct rt_entry *rt;
27334564Skarels 	int newmetric;
27434564Skarels {
27534564Skarels 	struct sockaddr_in *dst, *gate;
27634564Skarels 
27734564Skarels 	if (fd == NULL)
27834564Skarels 		return;
27936831Skarels 	if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
28036831Skarels 		fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
28136831Skarels 		lastlog = now;
28236831Skarels 	}
28334564Skarels 	dst = (struct sockaddr_in *)&rt->rt_dst;
28434564Skarels 	gate = (struct sockaddr_in *)&rt->rt_router;
28534564Skarels 	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
28634564Skarels 	fprintf(fd, "router %s, from %d to %d\n",
28734564Skarels 	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
28834564Skarels 	fflush(fd);
28936831Skarels 	if (ferror(fd))
29036831Skarels 		traceoff();
29134564Skarels }
29234564Skarels 
2939022Ssam dumpif(fd, ifp)
29436831Skarels 	FILE *fd;
2959022Ssam 	register struct interface *ifp;
2969022Ssam {
29716314Skarels 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
29816314Skarels 		fprintf(fd, "*** Packet history for interface %s ***\n",
29916314Skarels 			ifp->int_name);
30034564Skarels #ifdef notneeded
30116314Skarels 		dumptrace(fd, "to", &ifp->int_output);
30234564Skarels #endif
30316314Skarels 		dumptrace(fd, "from", &ifp->int_input);
30416314Skarels 		fprintf(fd, "*** end packet history ***\n");
30516314Skarels 	}
3069022Ssam }
3079022Ssam 
3089022Ssam dumptrace(fd, dir, ifd)
3099022Ssam 	FILE *fd;
3109022Ssam 	char *dir;
3119022Ssam 	register struct ifdebug *ifd;
3129022Ssam {
3139022Ssam 	register struct iftrace *t;
3149022Ssam 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
3159022Ssam 
3169022Ssam 	if (ifd->ifd_front == ifd->ifd_records &&
3179022Ssam 	    ifd->ifd_front->ift_size == 0) {
3189022Ssam 		fprintf(fd, "%s: no packets.\n", cp);
31926960Skarels 		fflush(fd);
3209022Ssam 		return;
3219022Ssam 	}
3229022Ssam 	fprintf(fd, "%s trace:\n", cp);
32316314Skarels 	t = ifd->ifd_front - ifd->ifd_count;
32416314Skarels 	if (t < ifd->ifd_records)
32516314Skarels 		t += NRECORDS;
32616314Skarels 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
32716314Skarels 		if (t >= ifd->ifd_records + NRECORDS)
32816314Skarels 			t = ifd->ifd_records;
3299022Ssam 		if (t->ift_size == 0)
3309022Ssam 			continue;
33134564Skarels 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
33234564Skarels 		    &t->ift_stamp);
3339022Ssam 	}
3349022Ssam }
3359022Ssam 
33636831Skarels dumppacket(fd, dir, who, cp, size, stamp)
3379022Ssam 	FILE *fd;
3389022Ssam 	struct sockaddr_in *who;		/* should be sockaddr */
3399022Ssam 	char *dir, *cp;
3409022Ssam 	register int size;
34136831Skarels 	struct timeval *stamp;
3429022Ssam {
3439022Ssam 	register struct rip *msg = (struct rip *)cp;
3449022Ssam 	register struct netinfo *n;
3459022Ssam 
34636831Skarels 	if (fd == NULL)
34736831Skarels 		return;
3489022Ssam 	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
34936831Skarels 		fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
35036831Skarels 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
35136831Skarels 		    ctime((time_t *)&stamp->tv_sec));
35236831Skarels 	else {
35336831Skarels 		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
35415099Ssam 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
35536831Skarels 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
35636831Skarels 		    ctime((time_t *)&stamp->tv_sec));
35726960Skarels 		fflush(fd);
3589022Ssam 		return;
3599022Ssam 	}
36036831Skarels 	if (tracepackets && tracecontents == 0) {
36136831Skarels 		fflush(fd);
36236831Skarels 		return;
36336831Skarels 	}
3649022Ssam 	switch (msg->rip_cmd) {
3659022Ssam 
3669022Ssam 	case RIPCMD_REQUEST:
3679022Ssam 	case RIPCMD_RESPONSE:
3689022Ssam 		size -= 4 * sizeof (char);
3699022Ssam 		n = msg->rip_nets;
3709022Ssam 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
37136831Skarels 			if (size < sizeof (struct netinfo)) {
37236831Skarels 				fprintf(fd, "(truncated record, len %d)\n",
37336831Skarels 				    size);
3749022Ssam 				break;
37536831Skarels 			}
37636831Skarels 			if (sizeof(n->rip_dst.sa_family) > 1)
37736831Skarels 			    n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
37836831Skarels 
37936831Skarels 			switch ((int)n->rip_dst.sa_family) {
38036831Skarels 
38136831Skarels 			case AF_INET:
38236831Skarels 				fprintf(fd, "\tdst %s metric %d\n",
38315099Ssam #define	satosin(sa)	((struct sockaddr_in *)&sa)
38436831Skarels 				     inet_ntoa(satosin(n->rip_dst)->sin_addr),
38536831Skarels 				     ntohl(n->rip_metric));
38636831Skarels 				break;
38736831Skarels 
38836831Skarels 			default:
38936831Skarels 				fprintf(fd, "\taf %d? metric %d\n",
39036831Skarels 				     n->rip_dst.sa_family,
39136831Skarels 				     ntohl(n->rip_metric));
39236831Skarels 				break;
39336831Skarels 			}
3949022Ssam 		}
3959022Ssam 		break;
3969022Ssam 
3979022Ssam 	case RIPCMD_TRACEON:
39834564Skarels 		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
3999022Ssam 		break;
4009022Ssam 
4019022Ssam 	case RIPCMD_TRACEOFF:
4029022Ssam 		break;
4039022Ssam 	}
40426960Skarels 	fflush(fd);
40536831Skarels 	if (ferror(fd))
40636831Skarels 		traceoff();
4079022Ssam }
408