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