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