trace.c revision 15248
1/*
2 * Copyright (c) 1985, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Copyright (c) 1995 John Hay.  All rights reserved.
6 *
7 * This file includes significant work done at Cornell University by
8 * Bill Nesheim.  That work included by permission.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	$Id: trace.c,v 1.1 1995/10/26 21:28:29 julian Exp $
39 */
40
41#ifndef lint
42static char sccsid[] = "@(#)trace.c	8.1 (Berkeley) 6/5/93";
43#endif /* not lint */
44
45/*
46 * Routing Table Management Daemon
47 */
48#define	RIPCMDS
49#define	SAPCMDS
50#include <stdlib.h>
51#include <unistd.h>
52#include <sys/types.h>
53#include <time.h>
54#include "defs.h"
55
56#define	NRECORDS	50		/* size of circular trace buffer */
57#ifdef DEBUG
58FILE	*ftrace = stdout;
59int	tracing = 1;
60#else DEBUG
61FILE	*ftrace = NULL;
62int	tracing = 0;
63#endif
64
65void dumpif(FILE *fd, struct interface *ifp);
66void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd);
67
68void
69traceinit(ifp)
70	register struct interface *ifp;
71{
72	static int iftraceinit();
73
74	if (iftraceinit(ifp, &ifp->int_input) &&
75	    iftraceinit(ifp, &ifp->int_output))
76		return;
77	tracing = 0;
78	syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
79}
80
81static int
82iftraceinit(ifp, ifd)
83	struct interface *ifp;
84	register struct ifdebug *ifd;
85{
86	register struct iftrace *t;
87
88	ifd->ifd_records =
89	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
90	if (ifd->ifd_records == 0)
91		return (0);
92	ifd->ifd_front = ifd->ifd_records;
93	ifd->ifd_count = 0;
94	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
95		t->ift_size = 0;
96		t->ift_packet = 0;
97	}
98	ifd->ifd_if = ifp;
99	return (1);
100}
101
102void
103traceon(file)
104	char *file;
105{
106
107	if (ftrace != NULL)
108		return;
109	ftrace = fopen(file, "a");
110	if (ftrace == NULL)
111		return;
112	dup2(fileno(ftrace), 1);
113	dup2(fileno(ftrace), 2);
114	tracing = 1;
115}
116
117void
118traceoff(void)
119{
120	if (!tracing)
121		return;
122	if (ftrace != NULL)
123		fclose(ftrace);
124	ftrace = NULL;
125	tracing = 0;
126}
127
128void
129trace(ifd, who, p, len, m)
130	register struct ifdebug *ifd;
131	struct sockaddr *who;
132	char *p;
133	int len, m;
134{
135	register struct iftrace *t;
136
137	if (ifd->ifd_records == 0)
138		return;
139	t = ifd->ifd_front++;
140	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
141		ifd->ifd_front = ifd->ifd_records;
142	if (ifd->ifd_count < NRECORDS)
143		ifd->ifd_count++;
144	if (t->ift_size > 0 && t->ift_packet)
145		free(t->ift_packet);
146	t->ift_packet = 0;
147	t->ift_stamp = time(0);
148	t->ift_who = *who;
149	if (len > 0) {
150		t->ift_packet = malloc(len);
151		if (t->ift_packet)
152			bcopy(p, t->ift_packet, len);
153		else
154			len = 0;
155	}
156	t->ift_size = len;
157	t->ift_metric = m;
158}
159
160void
161traceaction(fd, action, rt)
162	FILE *fd;
163	char *action;
164	struct rt_entry *rt;
165{
166	struct sockaddr_ipx *dst, *gate;
167	static struct bits {
168		int	t_bits;
169		char	*t_name;
170	} flagbits[] = {
171		{ RTF_UP,	"UP" },
172		{ RTF_GATEWAY,	"GATEWAY" },
173		{ RTF_HOST,	"HOST" },
174		{ 0 }
175	}, statebits[] = {
176		{ RTS_PASSIVE,	"PASSIVE" },
177		{ RTS_REMOTE,	"REMOTE" },
178		{ RTS_INTERFACE,"INTERFACE" },
179		{ RTS_CHANGED,	"CHANGED" },
180		{ 0 }
181	};
182	register struct bits *p;
183	register int first;
184	char *cp;
185
186	if (fd == NULL)
187		return;
188	fprintf(fd, "%s ", action);
189	dst = (struct sockaddr_ipx *)&rt->rt_dst;
190	gate = (struct sockaddr_ipx *)&rt->rt_router;
191	fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr));
192	fprintf(fd, "router %s, metric %d, ticks %d, flags",
193	     ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
194	cp = " %s";
195	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
196		if ((rt->rt_flags & p->t_bits) == 0)
197			continue;
198		fprintf(fd, cp, p->t_name);
199		if (first) {
200			cp = "|%s";
201			first = 0;
202		}
203	}
204	fprintf(fd, " state");
205	cp = " %s";
206	for (first = 1, p = statebits; p->t_bits > 0; p++) {
207		if ((rt->rt_state & p->t_bits) == 0)
208			continue;
209		fprintf(fd, cp, p->t_name);
210		if (first) {
211			cp = "|%s";
212			first = 0;
213		}
214	}
215	putc('\n', fd);
216	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
217		dumpif(fd, rt->rt_ifp);
218	fflush(fd);
219}
220
221void
222dumpif(fd, ifp)
223	register struct interface *ifp;
224	FILE *fd;
225{
226	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
227		fprintf(fd, "*** Packet history for interface %s ***\n",
228			ifp->int_name);
229		dumptrace(fd, "to", &ifp->int_output);
230		dumptrace(fd, "from", &ifp->int_input);
231		fprintf(fd, "*** end packet history ***\n");
232	}
233}
234
235void
236dumptrace(fd, dir, ifd)
237	FILE *fd;
238	char *dir;
239	register struct ifdebug *ifd;
240{
241	register struct iftrace *t;
242	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
243
244	if (ifd->ifd_front == ifd->ifd_records &&
245	    ifd->ifd_front->ift_size == 0) {
246		fprintf(fd, "%s: no packets.\n", cp);
247		return;
248	}
249	fprintf(fd, "%s trace:\n", cp);
250	t = ifd->ifd_front - ifd->ifd_count;
251	if (t < ifd->ifd_records)
252		t += NRECORDS;
253	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
254		if (t >= ifd->ifd_records + NRECORDS)
255			t = ifd->ifd_records;
256		if (t->ift_size == 0)
257			continue;
258		fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
259			t->ift_metric);
260		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
261	}
262}
263
264void
265dumppacket(fd, dir, source, cp, size)
266	FILE *fd;
267	char *dir;
268	struct sockaddr *source;
269	char *cp;
270	register int size;
271{
272	register struct rip *msg = (struct rip *)cp;
273	register struct netinfo *n;
274	struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
275
276	if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
277		fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
278		    dir, ipxdp_ntoa(&who->sipx_addr),
279		    ntohs(who->sipx_addr.x_port));
280	else {
281		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
282		    dir, ipxdp_ntoa(&who->sipx_addr),
283		    ntohs(who->sipx_addr.x_port));
284		fprintf(fd, "size=%d cp=%x packet=%x\n", size,
285			(u_int)cp, (u_int)packet);
286		return;
287	}
288	switch (ntohs(msg->rip_cmd)) {
289
290	case RIPCMD_REQUEST:
291	case RIPCMD_RESPONSE:
292		fprintf(fd, ":\n");
293		size -= sizeof (u_short);
294		n = msg->rip_nets;
295		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
296			if (size < sizeof (struct netinfo))
297				break;
298			fprintf(fd, "\tnet %s metric %d ticks %d\n",
299			     ipxdp_nettoa(n->rip_dst),
300			     ntohs(n->rip_metric),
301			     ntohs(n->rip_ticks));
302		}
303		break;
304
305	}
306}
307
308void
309dumpsappacket(fd, dir, source, cp, size)
310	FILE *fd;
311	char *dir;
312	struct sockaddr *source;
313	char *cp;
314	register int size;
315{
316	register struct sap_packet *msg = (struct sap_packet *)cp;
317	register struct sap_info *n;
318	struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
319
320	if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX)
321		fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)],
322		    dir, ipxdp_ntoa(&who->sipx_addr),
323		    ntohs(who->sipx_addr.x_port));
324	else {
325		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd),
326		    dir, ipxdp_ntoa(&who->sipx_addr),
327		    ntohs(who->sipx_addr.x_port));
328		fprintf(fd, "size=%d cp=%x packet=%x\n", size,
329			(u_int)cp, (u_int)packet);
330		return;
331	}
332	switch (ntohs(msg->sap_cmd)) {
333
334	case SAP_REQ:
335	case SAP_RESP:
336	case SAP_REQ_NEAR:
337	case SAP_RESP_NEAR:
338		fprintf(fd, ":\n");
339		size -= sizeof (u_short);
340		n = msg->sap;
341		for (; size > 0; n++, size -= sizeof (struct sap_info)) {
342			if (size < sizeof (struct sap_info))
343				break;
344			fprintf(fd, "  service %04X %-20.20s "
345				    "addr %s.%04X metric %d\n",
346			     ntohs(n->ServType),
347			     n->ServName,
348			     ipxdp_ntoa(&n->ipx),
349			     ntohs(n->ipx.x_port),
350			     ntohs(n->hops));
351		}
352		break;
353
354	}
355}
356
357void
358dumpsaptable(fd, sh)
359	FILE *fd;
360	struct sap_hash *sh;
361{
362	register struct sap_entry *sap;
363	struct sap_hash *hash;
364	int x = 0;
365
366	fprintf(fd, "------- SAP table dump. -------\n");
367	for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) {
368		fprintf(fd, "HASH %d\n", x);
369		sap = hash->forw;
370		for (; sap != (struct sap_entry *)hash; sap = sap->forw) {
371			fprintf(fd, "  service %04X %-20.20s "
372				    "addr %s.%04X %c metric %d\n",
373				     ntohs(sap->sap.ServType),
374				     sap->sap.ServName,
375				     ipxdp_ntoa(&sap->sap.ipx),
376				     ntohs(sap->sap.ipx.x_port),
377				     (sap->clone ? 'C' : ' '),
378				     ntohs(sap->sap.hops));
379		}
380	}
381	fprintf(fd, "\n");
382}
383
384void
385dumpriptable(fd)
386	FILE *fd;
387{
388	register struct rt_entry *rip;
389	struct rthash *hash;
390	int x;
391	struct rthash *rh = nethash;
392
393	fprintf(fd, "------- RIP table dump. -------\n");
394	x = 0;
395	fprintf(fd, "Network table.\n");
396
397	for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) {
398		fprintf(fd, "HASH %d\n", x);
399		rip = hash->rt_forw;
400		for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) {
401			fprintf(fd, "  dest %s\t",
402				ipxdp_ntoa(&satoipx_addr(rip->rt_dst)));
403			fprintf(fd, "%s metric %d, ticks %d\n",
404				ipxdp_ntoa(&satoipx_addr(rip->rt_router)),
405				rip->rt_metric,
406				rip->rt_ticks);
407		}
408	}
409	fprintf(fd, "\n");
410}
411
412union ipx_net_u net;
413
414char *
415ipxdp_nettoa(val)
416union ipx_net val;
417{
418	static char buf[100];
419	net.net_e = val;
420	(void)sprintf(buf, "%lx", ntohl(net.long_e));
421	return (buf);
422}
423
424
425char *
426ipxdp_ntoa(addr)
427struct ipx_addr *addr;
428{
429    static char buf[100];
430
431    (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
432	ipxdp_nettoa(addr->x_net),
433	addr->x_host.c_host[0], addr->x_host.c_host[1],
434	addr->x_host.c_host[2], addr->x_host.c_host[3],
435	addr->x_host.c_host[4], addr->x_host.c_host[5]);
436
437    return(buf);
438}
439