trace.c revision 27244
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.4 1997/02/22 16:01:04 peter 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
222traceactionlog(action, rt)
223	char *action;
224	struct rt_entry *rt;
225{
226	struct sockaddr_ipx *dst, *gate;
227	static struct bits {
228		int	t_bits;
229		char	*t_name;
230	} flagbits[] = {
231		{ RTF_UP,	"UP" },
232		{ RTF_GATEWAY,	"GATEWAY" },
233		{ RTF_HOST,	"HOST" },
234		{ 0 }
235	}, statebits[] = {
236		{ RTS_PASSIVE,	"PASSIVE" },
237		{ RTS_REMOTE,	"REMOTE" },
238		{ RTS_INTERFACE,"INTERFACE" },
239		{ RTS_CHANGED,	"CHANGED" },
240		{ 0 }
241	};
242	register struct bits *p;
243	register int first;
244	char *cp;
245	char *lstr, *olstr;
246
247	dst = (struct sockaddr_ipx *)&rt->rt_dst;
248	gate = (struct sockaddr_ipx *)&rt->rt_router;
249	asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr));
250	olstr = lstr;
251	asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags",
252	     olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
253	free(olstr);
254	olstr = lstr;
255	cp = "%s %s";
256	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
257		if ((rt->rt_flags & p->t_bits) == 0)
258			continue;
259		asprintf(&lstr, cp, olstr, p->t_name);
260		free(olstr);
261		olstr = lstr;
262		if (first) {
263			cp = "%s|%s";
264			first = 0;
265		}
266	}
267	asprintf(&lstr, "%s state", olstr);
268	free(olstr);
269	olstr = lstr;
270	cp = "%s %s";
271	for (first = 1, p = statebits; p->t_bits > 0; p++) {
272		if ((rt->rt_state & p->t_bits) == 0)
273			continue;
274		asprintf(&lstr, cp, olstr, p->t_name);
275		free(olstr);
276		olstr = lstr;
277		if (first) {
278			cp = "%s|%s";
279			first = 0;
280		}
281	}
282	syslog(LOG_DEBUG, lstr);
283	free(lstr);
284}
285
286void
287tracesapactionlog(action, sap)
288	char *action;
289	struct sap_entry *sap;
290{
291	syslog(LOG_DEBUG, "%-12.12s  service %04X %-20.20s "
292		    "addr %s.%04X %c metric %d\n",
293		     action,
294		     ntohs(sap->sap.ServType),
295		     sap->sap.ServName,
296		     ipxdp_ntoa(&sap->sap.ipx),
297		     ntohs(sap->sap.ipx.x_port),
298		     (sap->clone ? 'C' : ' '),
299		     ntohs(sap->sap.hops));
300}
301
302void
303dumpif(fd, ifp)
304	register struct interface *ifp;
305	FILE *fd;
306{
307	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
308		fprintf(fd, "*** Packet history for interface %s ***\n",
309			ifp->int_name);
310		dumptrace(fd, "to", &ifp->int_output);
311		dumptrace(fd, "from", &ifp->int_input);
312		fprintf(fd, "*** end packet history ***\n");
313	}
314}
315
316void
317dumptrace(fd, dir, ifd)
318	FILE *fd;
319	char *dir;
320	register struct ifdebug *ifd;
321{
322	register struct iftrace *t;
323	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
324
325	if (ifd->ifd_front == ifd->ifd_records &&
326	    ifd->ifd_front->ift_size == 0) {
327		fprintf(fd, "%s: no packets.\n", cp);
328		return;
329	}
330	fprintf(fd, "%s trace:\n", cp);
331	t = ifd->ifd_front - ifd->ifd_count;
332	if (t < ifd->ifd_records)
333		t += NRECORDS;
334	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
335		if (t >= ifd->ifd_records + NRECORDS)
336			t = ifd->ifd_records;
337		if (t->ift_size == 0)
338			continue;
339		fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
340			t->ift_metric);
341		dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
342	}
343}
344
345void
346dumppacket(fd, dir, source, cp, size)
347	FILE *fd;
348	char *dir;
349	struct sockaddr *source;
350	char *cp;
351	register int size;
352{
353	register struct rip *msg = (struct rip *)cp;
354	register struct netinfo *n;
355	struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
356
357	if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
358		fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
359		    dir, ipxdp_ntoa(&who->sipx_addr),
360		    ntohs(who->sipx_addr.x_port));
361	else {
362		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
363		    dir, ipxdp_ntoa(&who->sipx_addr),
364		    ntohs(who->sipx_addr.x_port));
365		fprintf(fd, "size=%d cp=%x packet=%x\n", size,
366			(u_int)cp, (u_int)packet);
367		return;
368	}
369	switch (ntohs(msg->rip_cmd)) {
370
371	case RIPCMD_REQUEST:
372	case RIPCMD_RESPONSE:
373		fprintf(fd, ":\n");
374		size -= sizeof (u_short);
375		n = msg->rip_nets;
376		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
377			if (size < sizeof (struct netinfo))
378				break;
379			fprintf(fd, "\tnet %s metric %d ticks %d\n",
380			     ipxdp_nettoa(n->rip_dst),
381			     ntohs(n->rip_metric),
382			     ntohs(n->rip_ticks));
383		}
384		break;
385
386	}
387}
388
389void
390dumpsappacket(fd, dir, source, cp, size)
391	FILE *fd;
392	char *dir;
393	struct sockaddr *source;
394	char *cp;
395	register int size;
396{
397	register struct sap_packet *msg = (struct sap_packet *)cp;
398	register struct sap_info *n;
399	struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
400
401	if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX)
402		fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)],
403		    dir, ipxdp_ntoa(&who->sipx_addr),
404		    ntohs(who->sipx_addr.x_port));
405	else {
406		fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd),
407		    dir, ipxdp_ntoa(&who->sipx_addr),
408		    ntohs(who->sipx_addr.x_port));
409		fprintf(fd, "size=%d cp=%x packet=%x\n", size,
410			(u_int)cp, (u_int)packet);
411		return;
412	}
413	switch (ntohs(msg->sap_cmd)) {
414
415	case SAP_REQ:
416	case SAP_RESP:
417	case SAP_REQ_NEAR:
418	case SAP_RESP_NEAR:
419		fprintf(fd, ":\n");
420		size -= sizeof (u_short);
421		n = msg->sap;
422		for (; size > 0; n++, size -= sizeof (struct sap_info)) {
423			if (size < sizeof (struct sap_info))
424				break;
425			fprintf(fd, "  service %04X %-20.20s "
426				    "addr %s.%04X metric %d\n",
427			     ntohs(n->ServType),
428			     n->ServName,
429			     ipxdp_ntoa(&n->ipx),
430			     ntohs(n->ipx.x_port),
431			     ntohs(n->hops));
432		}
433		break;
434
435	}
436}
437
438void
439dumpsaptable(fd, sh)
440	FILE *fd;
441	struct sap_hash *sh;
442{
443	register struct sap_entry *sap;
444	struct sap_hash *hash;
445	int x = 0;
446
447	fprintf(fd, "------- SAP table dump. -------\n");
448	for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) {
449		fprintf(fd, "HASH %d\n", x);
450		sap = hash->forw;
451		for (; sap != (struct sap_entry *)hash; sap = sap->forw) {
452			fprintf(fd, "  service %04X %-20.20s "
453				    "addr %s.%04X %c metric %d\n",
454				     ntohs(sap->sap.ServType),
455				     sap->sap.ServName,
456				     ipxdp_ntoa(&sap->sap.ipx),
457				     ntohs(sap->sap.ipx.x_port),
458				     (sap->clone ? 'C' : ' '),
459				     ntohs(sap->sap.hops));
460		}
461	}
462	fprintf(fd, "\n");
463}
464
465void
466dumpriptable(fd)
467	FILE *fd;
468{
469	register struct rt_entry *rip;
470	struct rthash *hash;
471	int x;
472	struct rthash *rh = nethash;
473
474	fprintf(fd, "------- RIP table dump. -------\n");
475	x = 0;
476	fprintf(fd, "Network table.\n");
477
478	for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) {
479		fprintf(fd, "HASH %d\n", x);
480		rip = hash->rt_forw;
481		for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) {
482			fprintf(fd, "  dest %s\t",
483				ipxdp_ntoa(&satoipx_addr(rip->rt_dst)));
484			fprintf(fd, "%s metric %d, ticks %d\n",
485				ipxdp_ntoa(&satoipx_addr(rip->rt_router)),
486				rip->rt_metric,
487				rip->rt_ticks);
488		}
489	}
490	fprintf(fd, "\n");
491}
492
493union ipx_net_u net;
494
495char *
496ipxdp_nettoa(val)
497union ipx_net val;
498{
499	static char buf[100];
500	net.net_e = val;
501	(void)sprintf(buf, "%lx", ntohl(net.long_e));
502	return (buf);
503}
504
505
506char *
507ipxdp_ntoa(addr)
508struct ipx_addr *addr;
509{
510    static char buf[100];
511
512    (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
513	ipxdp_nettoa(addr->x_net),
514	addr->x_host.c_host[0], addr->x_host.c_host[1],
515	addr->x_host.c_host[2], addr->x_host.c_host[3],
516	addr->x_host.c_host[4], addr->x_host.c_host[5]);
517
518    return(buf);
519}
520