xref: /titanic_50/usr/src/cmd/cmd-inet/usr.lib/in.ripngd/trace.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
32*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.1	*/
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate  * Routing Table Management Daemon
39*7c478bd9Sstevel@tonic-gate  */
40*7c478bd9Sstevel@tonic-gate #include "defs.h"
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #define	NRECORDS	50		/* size of circular trace buffer */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate boolean_t	tracepackets;		/* watch packets as they go by */
45*7c478bd9Sstevel@tonic-gate int		tracing;		/* bitmask: */
46*7c478bd9Sstevel@tonic-gate FILE		*ftrace;		/* output trace file */
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate static int	iftraceinit(struct interface *ifp, struct ifdebug *ifd);
49*7c478bd9Sstevel@tonic-gate static void	dumpif(FILE *fp, struct interface *ifp);
50*7c478bd9Sstevel@tonic-gate static void	dumptrace(FILE *fp, char *dir, struct ifdebug *ifd);
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate void
traceinit(struct interface * ifp)53*7c478bd9Sstevel@tonic-gate traceinit(struct interface *ifp)
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	if (iftraceinit(ifp, &ifp->int_input) &&
56*7c478bd9Sstevel@tonic-gate 	    iftraceinit(ifp, &ifp->int_output))
57*7c478bd9Sstevel@tonic-gate 		return;
58*7c478bd9Sstevel@tonic-gate 	tracing = 0;
59*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "traceinit: can't init %s\n",
60*7c478bd9Sstevel@tonic-gate 	    (ifp->int_name != NULL) ? ifp->int_name : "(noname)");
61*7c478bd9Sstevel@tonic-gate }
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static int
iftraceinit(struct interface * ifp,struct ifdebug * ifd)64*7c478bd9Sstevel@tonic-gate iftraceinit(struct interface *ifp, struct ifdebug *ifd)
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate 	struct iftrace *t;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 	ifd->ifd_records = (struct iftrace *)
69*7c478bd9Sstevel@tonic-gate 	    malloc((size_t)NRECORDS * sizeof (struct iftrace));
70*7c478bd9Sstevel@tonic-gate 	if (ifd->ifd_records == NULL)
71*7c478bd9Sstevel@tonic-gate 		return (0);
72*7c478bd9Sstevel@tonic-gate 	ifd->ifd_front = ifd->ifd_records;
73*7c478bd9Sstevel@tonic-gate 	ifd->ifd_count = 0;
74*7c478bd9Sstevel@tonic-gate 	for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
75*7c478bd9Sstevel@tonic-gate 		t->ift_size = 0;
76*7c478bd9Sstevel@tonic-gate 		t->ift_packet = NULL;
77*7c478bd9Sstevel@tonic-gate 	}
78*7c478bd9Sstevel@tonic-gate 	ifd->ifd_if = ifp;
79*7c478bd9Sstevel@tonic-gate 	return (1);
80*7c478bd9Sstevel@tonic-gate }
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate void
traceon(char * file)83*7c478bd9Sstevel@tonic-gate traceon(char *file)
84*7c478bd9Sstevel@tonic-gate {
85*7c478bd9Sstevel@tonic-gate 	struct stat stbuf;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	if (ftrace != NULL)
88*7c478bd9Sstevel@tonic-gate 		return;
89*7c478bd9Sstevel@tonic-gate 	if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
90*7c478bd9Sstevel@tonic-gate 		return;
91*7c478bd9Sstevel@tonic-gate 	ftrace = fopen(file, "a");
92*7c478bd9Sstevel@tonic-gate 	if (ftrace == NULL)
93*7c478bd9Sstevel@tonic-gate 		return;
94*7c478bd9Sstevel@tonic-gate 	(void) dup2(fileno(ftrace), 1);
95*7c478bd9Sstevel@tonic-gate 	(void) dup2(fileno(ftrace), 2);
96*7c478bd9Sstevel@tonic-gate }
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate void
traceonfp(FILE * fp)99*7c478bd9Sstevel@tonic-gate traceonfp(FILE *fp)
100*7c478bd9Sstevel@tonic-gate {
101*7c478bd9Sstevel@tonic-gate 	if (ftrace != NULL)
102*7c478bd9Sstevel@tonic-gate 		return;
103*7c478bd9Sstevel@tonic-gate 	ftrace = fp;
104*7c478bd9Sstevel@tonic-gate 	if (ftrace == NULL)
105*7c478bd9Sstevel@tonic-gate 		return;
106*7c478bd9Sstevel@tonic-gate 	(void) dup2(fileno(ftrace), 1);
107*7c478bd9Sstevel@tonic-gate 	(void) dup2(fileno(ftrace), 2);
108*7c478bd9Sstevel@tonic-gate }
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate void
trace(struct ifdebug * ifd,struct sockaddr_in6 * who,char * p,int len,int m)111*7c478bd9Sstevel@tonic-gate trace(struct ifdebug *ifd, struct sockaddr_in6 *who, char *p, int len, int m)
112*7c478bd9Sstevel@tonic-gate {
113*7c478bd9Sstevel@tonic-gate 	struct iftrace *t;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	if (ifd->ifd_records == 0)
116*7c478bd9Sstevel@tonic-gate 		return;
117*7c478bd9Sstevel@tonic-gate 	t = ifd->ifd_front++;
118*7c478bd9Sstevel@tonic-gate 	if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
119*7c478bd9Sstevel@tonic-gate 		ifd->ifd_front = ifd->ifd_records;
120*7c478bd9Sstevel@tonic-gate 	if (ifd->ifd_count < NRECORDS)
121*7c478bd9Sstevel@tonic-gate 		ifd->ifd_count++;
122*7c478bd9Sstevel@tonic-gate 	if (t->ift_size > 0 && t->ift_size < len && t->ift_packet != NULL) {
123*7c478bd9Sstevel@tonic-gate 		free(t->ift_packet);
124*7c478bd9Sstevel@tonic-gate 		t->ift_packet = NULL;
125*7c478bd9Sstevel@tonic-gate 	}
126*7c478bd9Sstevel@tonic-gate 	(void) time(&t->ift_stamp);
127*7c478bd9Sstevel@tonic-gate 	t->ift_who = *who;
128*7c478bd9Sstevel@tonic-gate 	if (len > 0 && t->ift_packet == NULL) {
129*7c478bd9Sstevel@tonic-gate 		t->ift_packet = (char *)malloc((size_t)len);
130*7c478bd9Sstevel@tonic-gate 		if (t->ift_packet == NULL)
131*7c478bd9Sstevel@tonic-gate 			len = 0;
132*7c478bd9Sstevel@tonic-gate 	}
133*7c478bd9Sstevel@tonic-gate 	if (len > 0)
134*7c478bd9Sstevel@tonic-gate 		bcopy(p, t->ift_packet, len);
135*7c478bd9Sstevel@tonic-gate 	t->ift_size = len;
136*7c478bd9Sstevel@tonic-gate 	t->ift_metric = m;
137*7c478bd9Sstevel@tonic-gate }
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate void
traceaction(FILE * fp,char * action,struct rt_entry * rt)140*7c478bd9Sstevel@tonic-gate traceaction(FILE *fp, char *action, struct rt_entry *rt)
141*7c478bd9Sstevel@tonic-gate {
142*7c478bd9Sstevel@tonic-gate 	static struct bits {
143*7c478bd9Sstevel@tonic-gate 		ulong_t	t_bits;
144*7c478bd9Sstevel@tonic-gate 		char	*t_name;
145*7c478bd9Sstevel@tonic-gate 	} flagbits[] = {
146*7c478bd9Sstevel@tonic-gate 		/* BEGIN CSTYLED */
147*7c478bd9Sstevel@tonic-gate 		{ RTF_UP,		"UP" },
148*7c478bd9Sstevel@tonic-gate 		{ RTF_GATEWAY,		"GATEWAY" },
149*7c478bd9Sstevel@tonic-gate 		{ RTF_HOST,		"HOST" },
150*7c478bd9Sstevel@tonic-gate 		{ 0,			NULL }
151*7c478bd9Sstevel@tonic-gate 		/* END CSTYLED */
152*7c478bd9Sstevel@tonic-gate 	}, statebits[] = {
153*7c478bd9Sstevel@tonic-gate 		/* BEGIN CSTYLED */
154*7c478bd9Sstevel@tonic-gate 		{ RTS_INTERFACE,	"INTERFACE" },
155*7c478bd9Sstevel@tonic-gate 		{ RTS_CHANGED,		"CHANGED" },
156*7c478bd9Sstevel@tonic-gate 		{ RTS_PRIVATE,		"PRIVATE" },
157*7c478bd9Sstevel@tonic-gate 		{ 0,			NULL }
158*7c478bd9Sstevel@tonic-gate 		/* END CSTYLED */
159*7c478bd9Sstevel@tonic-gate 	};
160*7c478bd9Sstevel@tonic-gate 	struct bits *p;
161*7c478bd9Sstevel@tonic-gate 	boolean_t first;
162*7c478bd9Sstevel@tonic-gate 	char c;
163*7c478bd9Sstevel@tonic-gate 	time_t t;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	if (fp == NULL)
166*7c478bd9Sstevel@tonic-gate 		return;
167*7c478bd9Sstevel@tonic-gate 	(void) time(&t);
168*7c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%.15s %s ", ctime(&t) + 4, action);
169*7c478bd9Sstevel@tonic-gate 	if (rt != NULL) {
170*7c478bd9Sstevel@tonic-gate 		char buf1[INET6_ADDRSTRLEN];
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "prefix %s/%d ",
173*7c478bd9Sstevel@tonic-gate 		    inet_ntop(AF_INET6, (void *)&rt->rt_dst, buf1,
174*7c478bd9Sstevel@tonic-gate 			sizeof (buf1)),
175*7c478bd9Sstevel@tonic-gate 		    rt->rt_prefix_length);
176*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "via %s metric %d",
177*7c478bd9Sstevel@tonic-gate 		    inet_ntop(AF_INET6, (void *)&rt->rt_router, buf1,
178*7c478bd9Sstevel@tonic-gate 			sizeof (buf1)),
179*7c478bd9Sstevel@tonic-gate 		    rt->rt_metric);
180*7c478bd9Sstevel@tonic-gate 		if (rt->rt_ifp != NULL) {
181*7c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, " if %s",
182*7c478bd9Sstevel@tonic-gate 			    (rt->rt_ifp->int_name != NULL) ?
183*7c478bd9Sstevel@tonic-gate 				rt->rt_ifp->int_name : "(noname)");
184*7c478bd9Sstevel@tonic-gate 		}
185*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, " state");
186*7c478bd9Sstevel@tonic-gate 		c = ' ';
187*7c478bd9Sstevel@tonic-gate 		for (first = _B_TRUE, p = statebits; p->t_bits > 0; p++) {
188*7c478bd9Sstevel@tonic-gate 			if ((rt->rt_state & p->t_bits) == 0)
189*7c478bd9Sstevel@tonic-gate 				continue;
190*7c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "%c%s", c, p->t_name);
191*7c478bd9Sstevel@tonic-gate 			if (first) {
192*7c478bd9Sstevel@tonic-gate 				c = '|';
193*7c478bd9Sstevel@tonic-gate 				first = _B_FALSE;
194*7c478bd9Sstevel@tonic-gate 			}
195*7c478bd9Sstevel@tonic-gate 		}
196*7c478bd9Sstevel@tonic-gate 		if (first)
197*7c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, " 0");
198*7c478bd9Sstevel@tonic-gate 		if (rt->rt_flags & (RTF_UP | RTF_GATEWAY)) {
199*7c478bd9Sstevel@tonic-gate 			c = ' ';
200*7c478bd9Sstevel@tonic-gate 			for (first = _B_TRUE, p = flagbits; p->t_bits > 0;
201*7c478bd9Sstevel@tonic-gate 			    p++) {
202*7c478bd9Sstevel@tonic-gate 				if ((rt->rt_flags & p->t_bits) == 0)
203*7c478bd9Sstevel@tonic-gate 					continue;
204*7c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "%c%s", c, p->t_name);
205*7c478bd9Sstevel@tonic-gate 				if (first) {
206*7c478bd9Sstevel@tonic-gate 					c = '|';
207*7c478bd9Sstevel@tonic-gate 					first = _B_FALSE;
208*7c478bd9Sstevel@tonic-gate 				}
209*7c478bd9Sstevel@tonic-gate 			}
210*7c478bd9Sstevel@tonic-gate 		}
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', fp);
213*7c478bd9Sstevel@tonic-gate 	if (!tracepackets && rt != NULL && rt->rt_ifp != NULL)
214*7c478bd9Sstevel@tonic-gate 		dumpif(fp, rt->rt_ifp);
215*7c478bd9Sstevel@tonic-gate 	(void) fflush(fp);
216*7c478bd9Sstevel@tonic-gate }
217*7c478bd9Sstevel@tonic-gate 
218*7c478bd9Sstevel@tonic-gate static void
dumpif(FILE * fp,struct interface * ifp)219*7c478bd9Sstevel@tonic-gate dumpif(FILE *fp, struct interface *ifp)
220*7c478bd9Sstevel@tonic-gate {
221*7c478bd9Sstevel@tonic-gate 	if (ifp->int_input.ifd_count != 0 || ifp->int_output.ifd_count != 0) {
222*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "*** Packet history for interface %s ***\n",
223*7c478bd9Sstevel@tonic-gate 		    (ifp->int_name != NULL) ? ifp->int_name : "(noname)");
224*7c478bd9Sstevel@tonic-gate 		dumptrace(fp, "to", &ifp->int_output);
225*7c478bd9Sstevel@tonic-gate 		dumptrace(fp, "from", &ifp->int_input);
226*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "*** end packet history ***\n");
227*7c478bd9Sstevel@tonic-gate 	}
228*7c478bd9Sstevel@tonic-gate 	(void) fflush(fp);
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate static void
dumptrace(FILE * fp,char * dir,struct ifdebug * ifd)232*7c478bd9Sstevel@tonic-gate dumptrace(FILE *fp, char *dir, struct ifdebug *ifd)
233*7c478bd9Sstevel@tonic-gate {
234*7c478bd9Sstevel@tonic-gate 	struct iftrace *t;
235*7c478bd9Sstevel@tonic-gate 	char *cp = (strcmp(dir, "to") != 0) ? "Output" : "Input";
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	if (ifd->ifd_front == ifd->ifd_records &&
238*7c478bd9Sstevel@tonic-gate 	    ifd->ifd_front->ift_size == 0) {
239*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%s: no packets.\n", cp);
240*7c478bd9Sstevel@tonic-gate 		(void) fflush(fp);
241*7c478bd9Sstevel@tonic-gate 		return;
242*7c478bd9Sstevel@tonic-gate 	}
243*7c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "%s trace:\n", cp);
244*7c478bd9Sstevel@tonic-gate 	t = ifd->ifd_front - ifd->ifd_count;
245*7c478bd9Sstevel@tonic-gate 	if (t < ifd->ifd_records)
246*7c478bd9Sstevel@tonic-gate 		t += NRECORDS;
247*7c478bd9Sstevel@tonic-gate 	for (; ifd->ifd_count; ifd->ifd_count--, t++) {
248*7c478bd9Sstevel@tonic-gate 		if (t >= ifd->ifd_records + NRECORDS)
249*7c478bd9Sstevel@tonic-gate 			t = ifd->ifd_records;
250*7c478bd9Sstevel@tonic-gate 		if (t->ift_size == 0)
251*7c478bd9Sstevel@tonic-gate 			continue;
252*7c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
253*7c478bd9Sstevel@tonic-gate 		    t->ift_metric);
254*7c478bd9Sstevel@tonic-gate 		dumppacket(fp, dir, (struct sockaddr_in6 *)&t->ift_who,
255*7c478bd9Sstevel@tonic-gate 		    t->ift_packet, t->ift_size);
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
260*7c478bd9Sstevel@tonic-gate void
dumppacket(FILE * fp,char * dir,struct sockaddr_in6 * who,char * cp,int size)261*7c478bd9Sstevel@tonic-gate dumppacket(FILE *fp, char *dir, struct sockaddr_in6 *who, char *cp, int size)
262*7c478bd9Sstevel@tonic-gate {
263*7c478bd9Sstevel@tonic-gate 	/* XXX Output contents of the RIP packet */
264*7c478bd9Sstevel@tonic-gate }
265