trace.c revision 11820
186071Sache/*
286071Sache * Copyright (c) 1985, 1993
386071Sache *	The Regents of the University of California.  All rights reserved.
486071Sache *
586071Sache * Copyright (c) 1995 John Hay.  All rights reserved.
686071Sache *
786071Sache * This file includes significant work done at Cornell University by
886071Sache * Bill Nesheim.  That work included by permission.
986071Sache *
1086071Sache * Redistribution and use in source and binary forms, with or without
1186071Sache * modification, are permitted provided that the following conditions
1286071Sache * are met:
1386071Sache * 1. Redistributions of source code must retain the above copyright
1486071Sache *    notice, this list of conditions and the following disclaimer.
1586071Sache * 2. Redistributions in binary form must reproduce the above copyright
1686071Sache *    notice, this list of conditions and the following disclaimer in the
1786071Sache *    documentation and/or other materials provided with the distribution.
1886071Sache * 3. All advertising materials mentioning features or use of this software
1986071Sache *    must display the following acknowledgement:
2086071Sache *	This product includes software developed by the University of
2186071Sache *	California, Berkeley and its contributors.
2286071Sache * 4. Neither the name of the University nor the names of its contributors
2386071Sache *    may be used to endorse or promote products derived from this software
2486071Sache *    without specific prior written permission.
2586071Sache *
2686071Sache * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2786071Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2886071Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2986071Sache * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3086071Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3186071Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3286071Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3386071Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3486071Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3586071Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3686071Sache * SUCH DAMAGE.
3786071Sache *
3886071Sache *	$Id: trace.c,v 1.6 1995/10/11 18:57:33 jhay Exp $
3986071Sache */
4086071Sache
4186071Sache#ifndef lint
4286071Sachestatic char sccsid[] = "@(#)trace.c	8.1 (Berkeley) 6/5/93";
4386071Sache#endif /* not lint */
4486071Sache
4586071Sache/*
4686071Sache * Routing Table Management Daemon
4786071Sache */
4886071Sache#define	RIPCMDS
4986071Sache#define	SAPCMDS
5086071Sache#include <stdlib.h>
5186071Sache#include <unistd.h>
5286071Sache#include <sys/types.h>
5386071Sache#include <time.h>
5486071Sache#include "defs.h"
5586071Sache
5686071Sache#define	NRECORDS	50		/* size of circular trace buffer */
5786071Sache#ifdef DEBUG
5886071SacheFILE	*ftrace = stdout;
5986071Sacheint	tracing = 1;
6086071Sache#else DEBUG
6186071SacheFILE	*ftrace = NULL;
6286071Sacheint	tracing = 0;
6386071Sache#endif
6486071Sache
6586071Sachevoid dumpif(FILE *fd, struct interface *ifp);
6686071Sachevoid dumptrace(FILE *fd, char *dir, struct ifdebug *ifd);
6786071Sache
6886071Sachevoid
6986071Sachetraceinit(ifp)
7086071Sache	register struct interface *ifp;
7186071Sache{
7286071Sache	static int iftraceinit();
7386071Sache
7486071Sache	if (iftraceinit(ifp, &ifp->int_input) &&
7586071Sache	    iftraceinit(ifp, &ifp->int_output))
7686071Sache		return;
7786071Sache	tracing = 0;
7886071Sache	syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
7986071Sache}
8086071Sache
8186071Sachestatic int
8286071Sacheiftraceinit(ifp, ifd)
8386071Sache	struct interface *ifp;
8486071Sache	register struct ifdebug *ifd;
8586071Sache{
8686071Sache	register struct iftrace *t;
8786071Sache
8886071Sache	ifd->ifd_records =
8986071Sache	  (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
9086071Sache	if (ifd->ifd_records == 0)
9186071Sache		return (0);
9286071Sache	ifd->ifd_front = ifd->ifd_records;
9386071Sache	ifd->ifd_count = 0;
9486071Sache	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
9586071Sache		t->ift_size = 0;
9686071Sache		t->ift_packet = 0;
9786071Sache	}
9886071Sache	ifd->ifd_if = ifp;
9986071Sache	return (1);
10086071Sache}
10186071Sache
10286071Sachevoid
10386071Sachetraceon(file)
10486071Sache	char *file;
10586071Sache{
10686071Sache
10786071Sache	if (ftrace != NULL)
10886071Sache		return;
10986071Sache	ftrace = fopen(file, "a");
11086071Sache	if (ftrace == NULL)
11186071Sache		return;
11286071Sache	dup2(fileno(ftrace), 1);
11386071Sache	dup2(fileno(ftrace), 2);
11486071Sache	tracing = 1;
11586071Sache}
11686071Sache
11786071Sachevoid
11886071Sachetraceoff(void)
11986071Sache{
12086071Sache	if (!tracing)
12186071Sache		return;
12286071Sache	if (ftrace != NULL)
12386071Sache		fclose(ftrace);
12486071Sache	ftrace = NULL;
12586071Sache	tracing = 0;
12686071Sache}
12786071Sache
12886071Sachevoid
12986071Sachetrace(ifd, who, p, len, m)
13086071Sache	register struct ifdebug *ifd;
13186071Sache	struct sockaddr *who;
13286071Sache	char *p;
13386071Sache	int len, m;
13486071Sache{
13586071Sache	register struct iftrace *t;
13686071Sache
13786071Sache	if (ifd->ifd_records == 0)
13886071Sache		return;
13986071Sache	t = ifd->ifd_front++;
14086071Sache	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
14186071Sache		ifd->ifd_front = ifd->ifd_records;
14286071Sache	if (ifd->ifd_count < NRECORDS)
14386071Sache		ifd->ifd_count++;
14486071Sache	if (t->ift_size > 0 && t->ift_packet)
14586071Sache		free(t->ift_packet);
14686071Sache	t->ift_packet = 0;
14786071Sache	t->ift_stamp = time(0);
14886071Sache	t->ift_who = *who;
14986071Sache	if (len > 0) {
15086071Sache		t->ift_packet = malloc(len);
15186071Sache		if (t->ift_packet)
15286071Sache			bcopy(p, t->ift_packet, len);
15386071Sache		else
15486071Sache			len = 0;
15586071Sache	}
15686071Sache	t->ift_size = len;
15786071Sache	t->ift_metric = m;
15886071Sache}
15986071Sache
16086071Sachevoid
16186071Sachetraceaction(fd, action, rt)
16286071Sache	FILE *fd;
16386071Sache	char *action;
16486071Sache	struct rt_entry *rt;
16586071Sache{
16686071Sache	struct sockaddr_ipx *dst, *gate;
16786071Sache	static struct bits {
16886071Sache		int	t_bits;
16986071Sache		char	*t_name;
17086071Sache	} flagbits[] = {
17186071Sache		{ RTF_UP,	"UP" },
17286071Sache		{ RTF_GATEWAY,	"GATEWAY" },
17386071Sache		{ RTF_HOST,	"HOST" },
17486071Sache		{ 0 }
17586071Sache	}, statebits[] = {
17686071Sache		{ RTS_PASSIVE,	"PASSIVE" },
17786071Sache		{ RTS_REMOTE,	"REMOTE" },
17886071Sache		{ RTS_INTERFACE,"INTERFACE" },
17986071Sache		{ RTS_CHANGED,	"CHANGED" },
18086071Sache		{ 0 }
18186071Sache	};
18286071Sache	register struct bits *p;
18386071Sache	register int first;
18486071Sache	char *cp;
18586071Sache
18686071Sache	if (fd == NULL)
18786071Sache		return;
18886071Sache	fprintf(fd, "%s ", action);
18986071Sache	dst = (struct sockaddr_ipx *)&rt->rt_dst;
19086071Sache	gate = (struct sockaddr_ipx *)&rt->rt_router;
19186071Sache	fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr));
19286071Sache	fprintf(fd, "router %s, metric %d, ticks %d, flags",
19386071Sache	     ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
19486071Sache	cp = " %s";
19586071Sache	for (first = 1, p = flagbits; p->t_bits > 0; p++) {
19686071Sache		if ((rt->rt_flags & p->t_bits) == 0)
19786071Sache			continue;
19886071Sache		fprintf(fd, cp, p->t_name);
19986071Sache		if (first) {
20086071Sache			cp = "|%s";
20186071Sache			first = 0;
20286071Sache		}
20386071Sache	}
20486071Sache	fprintf(fd, " state");
20586071Sache	cp = " %s";
20686071Sache	for (first = 1, p = statebits; p->t_bits > 0; p++) {
20786071Sache		if ((rt->rt_state & p->t_bits) == 0)
20886071Sache			continue;
20986071Sache		fprintf(fd, cp, p->t_name);
21086071Sache		if (first) {
21186071Sache			cp = "|%s";
21286071Sache			first = 0;
21386071Sache		}
21486071Sache	}
21586071Sache	putc('\n', fd);
21686071Sache	if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
21786071Sache		dumpif(fd, rt->rt_ifp);
21886071Sache	fflush(fd);
21986071Sache}
22086071Sache
22186071Sachevoid
22286071Sachedumpif(fd, ifp)
22386071Sache	register struct interface *ifp;
22486071Sache	FILE *fd;
22586071Sache{
22686071Sache	if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
22786071Sache		fprintf(fd, "*** Packet history for interface %s ***\n",
22886071Sache			ifp->int_name);
22986071Sache		dumptrace(fd, "to", &ifp->int_output);
23086071Sache		dumptrace(fd, "from", &ifp->int_input);
23186071Sache		fprintf(fd, "*** end packet history ***\n");
23286071Sache	}
23386071Sache}
23486071Sache
23586071Sachevoid
23686071Sachedumptrace(fd, dir, ifd)
23786071Sache	FILE *fd;
23886071Sache	char *dir;
23986071Sache	register struct ifdebug *ifd;
24086071Sache{
24186071Sache	register struct iftrace *t;
24286071Sache	char *cp = !strcmp(dir, "to") ? "Output" : "Input";
24386071Sache
24486071Sache	if (ifd->ifd_front == ifd->ifd_records &&
24586071Sache	    ifd->ifd_front->ift_size == 0) {
24686071Sache		fprintf(fd, "%s: no packets.\n", cp);
24786071Sache		return;
24886071Sache	}
24986071Sache	fprintf(fd, "%s trace:\n", cp);
25086071Sache	t = ifd->ifd_front - ifd->ifd_count;
25186071Sache	if (t < ifd->ifd_records)
25286071Sache		t += NRECORDS;
25386071Sache	for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
25486071Sache		if (t >= ifd->ifd_records + NRECORDS)
25586071Sache			t = ifd->ifd_records;
25686071Sache		if (t->ift_size == 0)
25786071Sache			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
384union ipx_net_u net;
385
386char *
387ipxdp_nettoa(val)
388union ipx_net val;
389{
390	static char buf[100];
391	net.net_e = val;
392	(void)sprintf(buf, "%lx", ntohl(net.long_e));
393	return (buf);
394}
395
396
397char *
398ipxdp_ntoa(addr)
399struct ipx_addr *addr;
400{
401    static char buf[100];
402
403    (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
404	ipxdp_nettoa(addr->x_net),
405	addr->x_host.c_host[0], addr->x_host.c_host[1],
406	addr->x_host.c_host[2], addr->x_host.c_host[3],
407	addr->x_host.c_host[4], addr->x_host.c_host[5]);
408
409    return(buf);
410}
411