trace.c revision 97632
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
39#ifndef lint
40#if 0
41static char sccsid[] = "@(#)trace.c	8.1 (Berkeley) 6/5/93";
42#endif
43static const char rcsid[] =
44  "$FreeBSD: head/usr.sbin/IPXrouted/trace.c 97632 2002-05-30 21:21:23Z wollman $";
45#endif /* not lint */
46
47/*
48 * Routing Table Management Daemon
49 */
50#define	RIPCMDS
51#define	SAPCMDS
52#include <stdlib.h>
53#include <unistd.h>
54#include <sys/types.h>
55#include <time.h>
56#include "defs.h"
57
58#define	NRECORDS	50		/* size of circular trace buffer */
59#ifdef DEBUG
60FILE	*ftrace = stdout;
61int	tracing = 1;
62#else /* DEBUG */
63FILE	*ftrace = NULL;
64int	tracing = 0;
65#endif
66
67void dumpif(FILE *fd, struct interface *ifp);
68void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd);
69
70void
71traceinit(ifp)
72	register struct interface *ifp;
73{
74	static int iftraceinit();
75
76	if (iftraceinit(ifp, &ifp->int_input) &&
77	    iftraceinit(ifp, &ifp->int_output))
78		return;
79	tracing = 0;
80	syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
81}
82
83static int
84iftraceinit(ifp, ifd)
85	struct interface *ifp;
86	register struct ifdebug *ifd;
87{
88	register struct iftrace *t;
89
90	ifd->ifd_records =
91	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
92	if (ifd->ifd_records == 0)
93		return (0);
94	ifd->ifd_front = ifd->ifd_records;
95	ifd->ifd_count = 0;
96	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
97		t->ift_size = 0;
98		t->ift_packet = 0;
99	}
100	ifd->ifd_if = ifp;
101	return (1);
102}
103
104void
105traceon(file)
106	char *file;
107{
108
109	if (ftrace != NULL)
110		return;
111	ftrace = fopen(file, "a");
112	if (ftrace == NULL)
113		return;
114	dup2(fileno(ftrace), 1);
115	dup2(fileno(ftrace), 2);
116	tracing = 1;
117}
118
119void
120traceoff(void)
121{
122	if (!tracing)
123		return;
124	if (ftrace != NULL)
125		fclose(ftrace);
126	ftrace = NULL;
127	tracing = 0;
128}
129
130void
131trace(ifd, who, p, len, m)
132	register struct ifdebug *ifd;
133	struct sockaddr *who;
134	char *p;
135	int len, m;
136{
137	register struct iftrace *t;
138
139	if (ifd->ifd_records == 0)
140		return;
141	t = ifd->ifd_front++;
142	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
143		ifd->ifd_front = ifd->ifd_records;
144	if (ifd->ifd_count < NRECORDS)
145		ifd->ifd_count++;
146	if (t->ift_size > 0 && t->ift_packet)
147		free(t->ift_packet);
148	t->ift_packet = 0;
149	t->ift_stamp = time(0);
150	t->ift_who = *who;
151	if (len > 0) {
152		t->ift_packet = malloc(len);
153		if (t->ift_packet)
154			bcopy(p, t->ift_packet, len);
155		else
156			len = 0;
157	}
158	t->ift_size = len;
159	t->ift_metric = m;
160}
161
162void
163traceaction(fd, action, rt)
164	FILE *fd;
165	char *action;
166	struct rt_entry *rt;
167{
168	struct sockaddr_ipx *dst, *gate;
169	static struct bits {
170		int	t_bits;
171		char	*t_name;
172	} flagbits[] = {
173		{ RTF_UP,	"UP" },
174		{ RTF_GATEWAY,	"GATEWAY" },
175		{ RTF_HOST,	"HOST" },
176		{ 0 }
177	}, statebits[] = {
178		{ RTS_PASSIVE,	"PASSIVE" },
179		{ RTS_REMOTE,	"REMOTE" },
180		{ RTS_INTERFACE,"INTERFACE" },
181		{ RTS_CHANGED,	"CHANGED" },
182		{ 0 }
183	};
184	register struct bits *p;
185	register int first;
186	char *cp;
187
188	if (fd == NULL)
189		return;
190	fprintf(fd, "%s ", action);
191	dst = (struct sockaddr_ipx *)&rt->rt_dst;
192	gate = (struct sockaddr_ipx *)&rt->rt_router;
193	fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr));
194	fprintf(fd, "router %s, metric %d, ticks %d, flags",
195	     ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
196	cp = " %s";
197	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
198		if ((rt->rt_flags & p->t_bits) == 0)
199			continue;
200		fprintf(fd, cp, p->t_name);
201		if (first) {
202			cp = "|%s";
203			first = 0;
204		}
205	}
206	fprintf(fd, " state");
207	cp = " %s";
208	for (first = 1, p = statebits; p->t_bits > 0; p++) {
209		if ((rt->rt_state & p->t_bits) == 0)
210			continue;
211		fprintf(fd, cp, p->t_name);
212		if (first) {
213			cp = "|%s";
214			first = 0;
215		}
216	}
217	putc('\n', fd);
218	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
219		dumpif(fd, rt->rt_ifp);
220	fflush(fd);
221}
222
223void
224traceactionlog(action, rt)
225	char *action;
226	struct rt_entry *rt;
227{
228	struct sockaddr_ipx *dst, *gate;
229	static struct bits {
230		int	t_bits;
231		char	*t_name;
232	} flagbits[] = {
233		{ RTF_UP,	"UP" },
234		{ RTF_GATEWAY,	"GATEWAY" },
235		{ RTF_HOST,	"HOST" },
236		{ 0 }
237	}, statebits[] = {
238		{ RTS_PASSIVE,	"PASSIVE" },
239		{ RTS_REMOTE,	"REMOTE" },
240		{ RTS_INTERFACE,"INTERFACE" },
241		{ RTS_CHANGED,	"CHANGED" },
242		{ 0 }
243	};
244	register struct bits *p;
245	register int first;
246	char *cp;
247	char *lstr, *olstr;
248
249	dst = (struct sockaddr_ipx *)&rt->rt_dst;
250	gate = (struct sockaddr_ipx *)&rt->rt_router;
251	asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr));
252	olstr = lstr;
253	asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags",
254	     olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
255	free(olstr);
256	olstr = lstr;
257	cp = "%s %s";
258	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
259		if ((rt->rt_flags & p->t_bits) == 0)
260			continue;
261		asprintf(&lstr, cp, olstr, p->t_name);
262		free(olstr);
263		olstr = lstr;
264		if (first) {
265			cp = "%s|%s";
266			first = 0;
267		}
268	}
269	asprintf(&lstr, "%s state", olstr);
270	free(olstr);
271	olstr = lstr;
272	cp = "%s %s";
273	for (first = 1, p = statebits; p->t_bits > 0; p++) {
274		if ((rt->rt_state & p->t_bits) == 0)
275			continue;
276		asprintf(&lstr, cp, olstr, p->t_name);
277		free(olstr);
278		olstr = lstr;
279		if (first) {
280			cp = "%s|%s";
281			first = 0;
282		}
283	}
284	syslog(LOG_DEBUG, "%s", lstr);
285	free(lstr);
286}
287
288void
289tracesapactionlog(action, sap)
290	char *action;
291	struct sap_entry *sap;
292{
293	syslog(LOG_DEBUG, "%-12.12s  service %04X %-20.20s "
294		    "addr %s.%04X %c metric %d\n",
295		     action,
296		     ntohs(sap->sap.ServType),
297		     sap->sap.ServName,
298		     ipxdp_ntoa(&sap->sap.ipx),
299		     ntohs(sap->sap.ipx.x_port),
300		     (sap->clone ? 'C' : ' '),
301		     ntohs(sap->sap.hops));
302}
303
304void
305dumpif(fd, ifp)
306	register struct interface *ifp;
307	FILE *fd;
308{
309	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
310		fprintf(fd, "*** Packet history for interface %s ***\n",
311			ifp->int_name);
312		dumptrace(fd, "to", &ifp->int_output);
313		dumptrace(fd, "from", &ifp->int_input);
314		fprintf(fd, "*** end packet history ***\n");
315	}
316}
317
318void
319dumptrace(fd, dir, ifd)
320	FILE *fd;
321	char *dir;
322	register struct ifdebug *ifd;
323{
324	register struct iftrace *t;
325	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
326
327	if (ifd->ifd_front == ifd->ifd_records &&
328	    ifd->ifd_front->ift_size == 0) {
329		fprintf(fd, "%s: no packets.\n", cp);
330		return;
331	}
332	fprintf(fd, "%s trace:\n", cp);
333	t = ifd->ifd_front - ifd->ifd_count;
334	if (t < ifd->ifd_records)
335		t += NRECORDS;
336	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
337		if (t >= ifd->ifd_records + NRECORDS)
338			t = ifd->ifd_records;
339		if (t->ift_size == 0)
340			continue;
341		fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
342			t->ift_metric);
343		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
344	}
345}
346
347void
348dumppacket(fd, dir, source, cp, size)
349	FILE *fd;
350	char *dir;
351	struct sockaddr *source;
352	char *cp;
353	register int size;
354{
355	register struct rip *msg = (struct rip *)cp;
356	register struct netinfo *n;
357	struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
358
359	if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
360		fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
361		    dir, ipxdp_ntoa(&who->sipx_addr),
362		    ntohs(who->sipx_addr.x_port));
363	else {
364		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
365		    dir, ipxdp_ntoa(&who->sipx_addr),
366		    ntohs(who->sipx_addr.x_port));
367		fprintf(fd, "size=%d cp=%x packet=%x\n", size,
368			(u_int)cp, (u_int)packet);
369		return;
370	}
371	switch (ntohs(msg->rip_cmd)) {
372
373	case RIPCMD_REQUEST:
374	case RIPCMD_RESPONSE:
375		fprintf(fd, ":\n");
376		size -= sizeof (u_short);
377		n = msg->rip_nets;
378		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
379			if (size < sizeof (struct netinfo))
380				break;
381			fprintf(fd, "\tnet %s metric %d ticks %d\n",
382			     ipxdp_nettoa(n->rip_dst),
383			     ntohs(n->rip_metric),
384			     ntohs(n->rip_ticks));
385		}
386		break;
387
388	}
389}
390
391void
392dumpsappacket(fd, dir, source, cp, size)
393	FILE *fd;
394	char *dir;
395	struct sockaddr *source;
396	char *cp;
397	register int size;
398{
399	register struct sap_packet *msg = (struct sap_packet *)cp;
400	register struct sap_info *n;
401	struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
402
403	if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX)
404		fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)],
405		    dir, ipxdp_ntoa(&who->sipx_addr),
406		    ntohs(who->sipx_addr.x_port));
407	else {
408		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd),
409		    dir, ipxdp_ntoa(&who->sipx_addr),
410		    ntohs(who->sipx_addr.x_port));
411		fprintf(fd, "size=%d cp=%x packet=%x\n", size,
412			(u_int)cp, (u_int)packet);
413		return;
414	}
415	switch (ntohs(msg->sap_cmd)) {
416
417	case SAP_REQ:
418	case SAP_RESP:
419	case SAP_REQ_NEAR:
420	case SAP_RESP_NEAR:
421		fprintf(fd, ":\n");
422		size -= sizeof (u_short);
423		n = msg->sap;
424		for (; size > 0; n++, size -= sizeof (struct sap_info)) {
425			if (size < sizeof (struct sap_info))
426				break;
427			fprintf(fd, "  service %04X %-20.20s "
428				    "addr %s.%04X metric %d\n",
429			     ntohs(n->ServType),
430			     n->ServName,
431			     ipxdp_ntoa(&n->ipx),
432			     ntohs(n->ipx.x_port),
433			     ntohs(n->hops));
434		}
435		break;
436
437	}
438}
439
440void
441dumpsaptable(fd, sh)
442	FILE *fd;
443	struct sap_hash *sh;
444{
445	register struct sap_entry *sap;
446	struct sap_hash *hash;
447	int x = 0;
448
449	fprintf(fd, "------- SAP table dump. -------\n");
450	for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) {
451		fprintf(fd, "HASH %d\n", x);
452		sap = hash->forw;
453		for (; sap != (struct sap_entry *)hash; sap = sap->forw) {
454			fprintf(fd, "  service %04X %-20.20s "
455				    "addr %s.%04X %c metric %d\n",
456				     ntohs(sap->sap.ServType),
457				     sap->sap.ServName,
458				     ipxdp_ntoa(&sap->sap.ipx),
459				     ntohs(sap->sap.ipx.x_port),
460				     (sap->clone ? 'C' : ' '),
461				     ntohs(sap->sap.hops));
462		}
463	}
464	fprintf(fd, "\n");
465}
466
467void
468dumpriptable(fd)
469	FILE *fd;
470{
471	register struct rt_entry *rip;
472	struct rthash *hash;
473	int x;
474	struct rthash *rh = nethash;
475
476	fprintf(fd, "------- RIP table dump. -------\n");
477	x = 0;
478	fprintf(fd, "Network table.\n");
479
480	for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) {
481		fprintf(fd, "HASH %d\n", x);
482		rip = hash->rt_forw;
483		for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) {
484			fprintf(fd, "  dest %s\t",
485				ipxdp_ntoa(&satoipx_addr(rip->rt_dst)));
486			fprintf(fd, "%s metric %d, ticks %d\n",
487				ipxdp_ntoa(&satoipx_addr(rip->rt_router)),
488				rip->rt_metric,
489				rip->rt_ticks);
490		}
491	}
492	fprintf(fd, "\n");
493}
494
495union ipx_net_u net;
496
497char *
498ipxdp_nettoa(val)
499union ipx_net val;
500{
501	static char buf[100];
502	net.net_e = val;
503	(void)sprintf(buf, "%lx", ntohl(net.long_e));
504	return (buf);
505}
506
507
508char *
509ipxdp_ntoa(addr)
510struct ipx_addr *addr;
511{
512    static char buf[100];
513
514    (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
515	ipxdp_nettoa(addr->x_net),
516	addr->x_host.c_host[0], addr->x_host.c_host[1],
517	addr->x_host.c_host[2], addr->x_host.c_host[3],
518	addr->x_host.c_host[4], addr->x_host.c_host[5]);
519
520    return(buf);
521}
522