xref: /original-bsd/sbin/routed/trace.c (revision f25de740)
1 /*
2  * Copyright (c) 1983, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that this notice is preserved and that due credit is given
7  * to the University of California at Berkeley. The name of the University
8  * may not be used to endorse or promote products derived from this
9  * software without specific prior written permission. This software
10  * is provided ``as is'' without express or implied warranty.
11  */
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)trace.c	5.6 (Berkeley) 05/31/88";
15 #endif /* not lint */
16 
17 /*
18  * Routing Table Management Daemon
19  */
20 #define	RIPCMDS
21 #include "defs.h"
22 #include <sys/file.h>
23 #include <sys/stat.h>
24 #include <sys/signal.h>
25 
26 #define	NRECORDS	50		/* size of circular trace buffer */
27 #ifdef DEBUG
28 FILE	*ftrace = stdout;
29 int	traceactions = 1;
30 #endif
31 
32 traceinit(ifp)
33 	register struct interface *ifp;
34 {
35 
36 	if (iftraceinit(ifp, &ifp->int_input) &&
37 	    iftraceinit(ifp, &ifp->int_output))
38 		return;
39 	tracehistory = 0;
40 	fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
41 }
42 
43 static
44 iftraceinit(ifp, ifd)
45 	struct interface *ifp;
46 	register struct ifdebug *ifd;
47 {
48 	register struct iftrace *t;
49 
50 	ifd->ifd_records =
51 	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
52 	if (ifd->ifd_records == 0)
53 		return (0);
54 	ifd->ifd_front = ifd->ifd_records;
55 	ifd->ifd_count = 0;
56 	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
57 		t->ift_size = 0;
58 		t->ift_packet = 0;
59 	}
60 	ifd->ifd_if = ifp;
61 	return (1);
62 }
63 
64 traceon(file)
65 	char *file;
66 {
67 	struct stat stbuf;
68 
69 	if (ftrace != NULL)
70 		return;
71 	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
72 		return;
73 	ftrace = fopen(file, "a");
74 	if (ftrace == NULL)
75 		return;
76 	dup2(fileno(ftrace), 1);
77 	dup2(fileno(ftrace), 2);
78 	traceactions = 1;
79 }
80 
81 traceoff()
82 {
83 	if (!traceactions)
84 		return;
85 	if (ftrace != NULL) {
86 		int fd = open("/dev/null", O_RDWR);
87 
88 		fprintf(ftrace, "Tracing disabled\n");
89 		(void) dup2(fd, 1);
90 		(void) dup2(fd, 2);
91 		(void) close(fd);
92 		fclose(ftrace);
93 		ftrace = NULL;
94 	}
95 	traceactions = 0;
96 	tracehistory = 0;
97 }
98 
99 sigtrace(s)
100 	int s;
101 {
102 	if (s == SIGUSR2) {
103 		traceoff();
104 		tracepackets = 0;
105 	} else if (traceactions == 0)
106 		traceactions++;
107 	else if (tracehistory == 0)
108 		tracehistory++;
109 	else {
110 		tracepackets++;
111 		tracehistory = 0;
112 	}
113 }
114 
115 trace(ifd, who, p, len, m)
116 	register struct ifdebug *ifd;
117 	struct sockaddr *who;
118 	char *p;
119 	int len, m;
120 {
121 	register struct iftrace *t;
122 
123 	if (ifd->ifd_records == 0)
124 		return;
125 	t = ifd->ifd_front++;
126 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
127 		ifd->ifd_front = ifd->ifd_records;
128 	if (ifd->ifd_count < NRECORDS)
129 		ifd->ifd_count++;
130 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
131 		free(t->ift_packet);
132 		t->ift_packet = 0;
133 	}
134 	t->ift_stamp = time(0);
135 	t->ift_who = *who;
136 	if (len > 0 && t->ift_packet == 0) {
137 		t->ift_packet = malloc(len);
138 		if (t->ift_packet == 0)
139 			len = 0;
140 	}
141 	if (len > 0)
142 		bcopy(p, t->ift_packet, len);
143 	t->ift_size = len;
144 	t->ift_metric = m;
145 }
146 
147 traceaction(fd, action, rt)
148 	FILE *fd;
149 	char *action;
150 	struct rt_entry *rt;
151 {
152 	struct sockaddr_in *dst, *gate;
153 	static struct bits {
154 		int	t_bits;
155 		char	*t_name;
156 	} flagbits[] = {
157 		{ RTF_UP,	"UP" },
158 		{ RTF_GATEWAY,	"GATEWAY" },
159 		{ RTF_HOST,	"HOST" },
160 		{ 0 }
161 	}, statebits[] = {
162 		{ RTS_PASSIVE,	"PASSIVE" },
163 		{ RTS_REMOTE,	"REMOTE" },
164 		{ RTS_INTERFACE,"INTERFACE" },
165 		{ RTS_CHANGED,	"CHANGED" },
166 		{ RTS_INTERNAL,	"INTERNAL" },
167 		{ RTS_EXTERNAL,	"EXTERNAL" },
168 		{ RTS_SUBNET,	"SUBNET" },
169 		{ 0 }
170 	};
171 	register struct bits *p;
172 	register int first;
173 	char *cp;
174 	struct interface *ifp;
175 
176 	if (fd == NULL)
177 		return;
178 	if (curtime) {
179 		fprintf(fd, "\n%s", curtime);
180 		curtime = NULL;
181 	}
182 	fprintf(fd, "%s ", action);
183 	dst = (struct sockaddr_in *)&rt->rt_dst;
184 	gate = (struct sockaddr_in *)&rt->rt_router;
185 	fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
186 	fprintf(fd, "router %s, metric %d, flags",
187 	     inet_ntoa(gate->sin_addr), rt->rt_metric);
188 	cp = " %s";
189 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
190 		if ((rt->rt_flags & p->t_bits) == 0)
191 			continue;
192 		fprintf(fd, cp, p->t_name);
193 		if (first) {
194 			cp = "|%s";
195 			first = 0;
196 		}
197 	}
198 	fprintf(fd, " state");
199 	cp = " %s";
200 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
201 		if ((rt->rt_state & p->t_bits) == 0)
202 			continue;
203 		fprintf(fd, cp, p->t_name);
204 		if (first) {
205 			cp = "|%s";
206 			first = 0;
207 		}
208 	}
209 	fprintf(fd, " timer %d\n", rt->rt_timer);
210 	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
211 		dumpif(fd, rt->rt_ifp);
212 	fflush(fd);
213 }
214 
215 tracenewmetric(fd, rt, newmetric)
216 	FILE *fd;
217 	struct rt_entry *rt;
218 	int newmetric;
219 {
220 	struct sockaddr_in *dst, *gate;
221 
222 	if (fd == NULL)
223 		return;
224 	dst = (struct sockaddr_in *)&rt->rt_dst;
225 	gate = (struct sockaddr_in *)&rt->rt_router;
226 	fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
227 	fprintf(fd, "router %s, from %d to %d\n",
228 	     inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
229 	fflush(fd);
230 }
231 
232 dumpif(fd, ifp)
233 	register struct interface *ifp;
234 {
235 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
236 		fprintf(fd, "*** Packet history for interface %s ***\n",
237 			ifp->int_name);
238 #ifdef notneeded
239 		dumptrace(fd, "to", &ifp->int_output);
240 #endif
241 		dumptrace(fd, "from", &ifp->int_input);
242 		fprintf(fd, "*** end packet history ***\n");
243 	}
244 	fflush(fd);
245 }
246 
247 dumptrace(fd, dir, ifd)
248 	FILE *fd;
249 	char *dir;
250 	register struct ifdebug *ifd;
251 {
252 	register struct iftrace *t;
253 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
254 
255 	if (ifd->ifd_front == ifd->ifd_records &&
256 	    ifd->ifd_front->ift_size == 0) {
257 		fprintf(fd, "%s: no packets.\n", cp);
258 		fflush(fd);
259 		return;
260 	}
261 	fprintf(fd, "%s trace:\n", cp);
262 	t = ifd->ifd_front - ifd->ifd_count;
263 	if (t < ifd->ifd_records)
264 		t += NRECORDS;
265 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
266 		if (t >= ifd->ifd_records + NRECORDS)
267 			t = ifd->ifd_records;
268 		if (t->ift_size == 0)
269 			continue;
270 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
271 		    &t->ift_stamp);
272 	}
273 }
274 
275 dumppacket(fd, dir, who, cp, size, tstamp)
276 	FILE *fd;
277 	struct sockaddr_in *who;		/* should be sockaddr */
278 	char *dir, *cp;
279 	register int size;
280 	time_t *tstamp;
281 {
282 	register struct rip *msg = (struct rip *)cp;
283 	register struct netinfo *n;
284 
285 	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
286 		fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd],
287 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
288 	else {
289 		fprintf(fd, "Bad cmd 0x%x %s %x.%d %.24s\n", msg->rip_cmd,
290 		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
291 		    ctime(tstamp));
292 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
293 		fflush(fd);
294 		return;
295 	}
296 	fprintf(fd, " %.24s:\n", ctime(tstamp));
297 	switch (msg->rip_cmd) {
298 
299 	case RIPCMD_REQUEST:
300 	case RIPCMD_RESPONSE:
301 		size -= 4 * sizeof (char);
302 		n = msg->rip_nets;
303 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
304 			if (size < sizeof (struct netinfo))
305 				break;
306 			fprintf(fd, "\tdst %s metric %d\n",
307 #define	satosin(sa)	((struct sockaddr_in *)&sa)
308 			     inet_ntoa(satosin(n->rip_dst)->sin_addr),
309 			     ntohl(n->rip_metric));
310 		}
311 		break;
312 
313 	case RIPCMD_TRACEON:
314 		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
315 		break;
316 
317 	case RIPCMD_TRACEOFF:
318 		break;
319 	}
320 	fflush(fd);
321 }
322