xref: /original-bsd/sbin/XNSrouted/trace.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1985, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This file includes significant work done at Cornell University by
6  * Bill Nesheim.  That work included by permission.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)trace.c	8.1 (Berkeley) 06/05/93";
13 #endif /* not lint */
14 
15 /*
16  * Routing Table Management Daemon
17  */
18 #define	RIPCMDS
19 #include <stdlib.h>
20 #include "defs.h"
21 
22 #define	NRECORDS	50		/* size of circular trace buffer */
23 #ifdef DEBUG
24 FILE	*ftrace = stdout;
25 int	tracing = 1;
26 #else DEBUG
27 FILE	*ftrace = NULL;
28 int	tracing = 0;
29 #endif
30 
31 char *xns_ntoa();
32 
33 traceinit(ifp)
34 	register struct interface *ifp;
35 {
36 	static int iftraceinit();
37 
38 	if (iftraceinit(ifp, &ifp->int_input) &&
39 	    iftraceinit(ifp, &ifp->int_output))
40 		return;
41 	tracing = 0;
42 	syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
43 }
44 
45 static
46 iftraceinit(ifp, ifd)
47 	struct interface *ifp;
48 	register struct ifdebug *ifd;
49 {
50 	register struct iftrace *t;
51 
52 	ifd->ifd_records =
53 	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
54 	if (ifd->ifd_records == 0)
55 		return (0);
56 	ifd->ifd_front = ifd->ifd_records;
57 	ifd->ifd_count = 0;
58 	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
59 		t->ift_size = 0;
60 		t->ift_packet = 0;
61 	}
62 	ifd->ifd_if = ifp;
63 	return (1);
64 }
65 
66 traceon(file)
67 	char *file;
68 {
69 
70 	if (ftrace != NULL)
71 		return;
72 	ftrace = fopen(file, "a");
73 	if (ftrace == NULL)
74 		return;
75 	dup2(fileno(ftrace), 1);
76 	dup2(fileno(ftrace), 2);
77 	tracing = 1;
78 }
79 
80 traceoff()
81 {
82 	if (!tracing)
83 		return;
84 	if (ftrace != NULL)
85 		fclose(ftrace);
86 	ftrace = NULL;
87 	tracing = 0;
88 }
89 
90 trace(ifd, who, p, len, m)
91 	register struct ifdebug *ifd;
92 	struct sockaddr *who;
93 	char *p;
94 	int len, m;
95 {
96 	register struct iftrace *t;
97 
98 	if (ifd->ifd_records == 0)
99 		return;
100 	t = ifd->ifd_front++;
101 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
102 		ifd->ifd_front = ifd->ifd_records;
103 	if (ifd->ifd_count < NRECORDS)
104 		ifd->ifd_count++;
105 	if (t->ift_size > 0 && t->ift_packet)
106 		free(t->ift_packet);
107 	t->ift_packet = 0;
108 	t->ift_stamp = time(0);
109 	t->ift_who = *who;
110 	if (len > 0) {
111 		t->ift_packet = malloc(len);
112 		if (t->ift_packet)
113 			bcopy(p, t->ift_packet, len);
114 		else
115 			len = 0;
116 	}
117 	t->ift_size = len;
118 	t->ift_metric = m;
119 }
120 
121 traceaction(fd, action, rt)
122 	FILE *fd;
123 	char *action;
124 	struct rt_entry *rt;
125 {
126 	struct sockaddr_ns *dst, *gate;
127 	static struct bits {
128 		int	t_bits;
129 		char	*t_name;
130 	} flagbits[] = {
131 		{ RTF_UP,	"UP" },
132 		{ RTF_GATEWAY,	"GATEWAY" },
133 		{ RTF_HOST,	"HOST" },
134 		{ 0 }
135 	}, statebits[] = {
136 		{ RTS_PASSIVE,	"PASSIVE" },
137 		{ RTS_REMOTE,	"REMOTE" },
138 		{ RTS_INTERFACE,"INTERFACE" },
139 		{ RTS_CHANGED,	"CHANGED" },
140 		{ 0 }
141 	};
142 	register struct bits *p;
143 	register int first;
144 	char *cp;
145 	struct interface *ifp;
146 
147 	if (fd == NULL)
148 		return;
149 	fprintf(fd, "%s ", action);
150 	dst = (struct sockaddr_ns *)&rt->rt_dst;
151 	gate = (struct sockaddr_ns *)&rt->rt_router;
152 	fprintf(fd, "dst %s, ", xns_ntoa(&dst->sns_addr));
153 	fprintf(fd, "router %s, metric %d, flags",
154 	     xns_ntoa(&gate->sns_addr), rt->rt_metric);
155 	cp = " %s";
156 	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
157 		if ((rt->rt_flags & p->t_bits) == 0)
158 			continue;
159 		fprintf(fd, cp, p->t_name);
160 		if (first) {
161 			cp = "|%s";
162 			first = 0;
163 		}
164 	}
165 	fprintf(fd, " state");
166 	cp = " %s";
167 	for (first = 1, p = statebits; p->t_bits > 0; p++) {
168 		if ((rt->rt_state & p->t_bits) == 0)
169 			continue;
170 		fprintf(fd, cp, p->t_name);
171 		if (first) {
172 			cp = "|%s";
173 			first = 0;
174 		}
175 	}
176 	putc('\n', fd);
177 	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
178 		dumpif(fd, rt->rt_ifp);
179 	fflush(fd);
180 }
181 
182 dumpif(fd, ifp)
183 	register struct interface *ifp;
184 	FILE *fd;
185 {
186 	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
187 		fprintf(fd, "*** Packet history for interface %s ***\n",
188 			ifp->int_name);
189 		dumptrace(fd, "to", &ifp->int_output);
190 		dumptrace(fd, "from", &ifp->int_input);
191 		fprintf(fd, "*** end packet history ***\n");
192 	}
193 }
194 
195 dumptrace(fd, dir, ifd)
196 	FILE *fd;
197 	char *dir;
198 	register struct ifdebug *ifd;
199 {
200 	register struct iftrace *t;
201 	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
202 
203 	if (ifd->ifd_front == ifd->ifd_records &&
204 	    ifd->ifd_front->ift_size == 0) {
205 		fprintf(fd, "%s: no packets.\n", cp);
206 		return;
207 	}
208 	fprintf(fd, "%s trace:\n", cp);
209 	t = ifd->ifd_front - ifd->ifd_count;
210 	if (t < ifd->ifd_records)
211 		t += NRECORDS;
212 	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
213 		if (t >= ifd->ifd_records + NRECORDS)
214 			t = ifd->ifd_records;
215 		if (t->ift_size == 0)
216 			continue;
217 		fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
218 			t->ift_metric);
219 		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
220 	}
221 }
222 
223 dumppacket(fd, dir, who, cp, size)
224 	FILE *fd;
225 	struct sockaddr_ns *who;		/* should be sockaddr */
226 	char *dir, *cp;
227 	register int size;
228 {
229 	register struct rip *msg = (struct rip *)cp;
230 	register struct netinfo *n;
231 	char *xns_nettoa();
232 
233 	if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
234 		fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
235 		    dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
236 	else {
237 		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
238 		    dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
239 		fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
240 		return;
241 	}
242 	switch (ntohs(msg->rip_cmd)) {
243 
244 	case RIPCMD_REQUEST:
245 	case RIPCMD_RESPONSE:
246 		fprintf(fd, ":\n");
247 		size -= sizeof (u_short);
248 		n = msg->rip_nets;
249 		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
250 			if (size < sizeof (struct netinfo))
251 				break;
252 			fprintf(fd, "\tnet %s metric %d\n",
253 			     xns_nettoa(n->rip_dst),
254 			     ntohs(n->rip_metric));
255 		}
256 		break;
257 
258 	}
259 }
260 
261 union ns_net_u net;
262 
263 char *
264 xns_nettoa(val)
265 union ns_net val;
266 {
267 	static char buf[100];
268 	net.net_e = val;
269 	(void)sprintf(buf, "%lx", ntohl(net.long_e));
270 	return (buf);
271 }
272 
273 
274 char *
275 xns_ntoa(addr)
276 struct ns_addr *addr;
277 {
278     static char buf[100];
279 
280     (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
281 	xns_nettoa(addr->x_net),
282 	addr->x_host.c_host[0], addr->x_host.c_host[1],
283 	addr->x_host.c_host[2], addr->x_host.c_host[3],
284 	addr->x_host.c_host[4], addr->x_host.c_host[5]);
285 
286     return(buf);
287 }
288