]> git.saurik.com Git - apple/network_cmds.git/blob - routed.tproj/trace.c
network_cmds-176.tar.gz
[apple/network_cmds.git] / routed.tproj / trace.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Copyright (c) 1983, 1988, 1993
27 * The Regents of the University of California. All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgment:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * @(#)defs.h 8.1 (Berkeley) 6/5/93
58 */
59
60
61 /*
62 * Routing Table Management Daemon
63 */
64 #define RIPCMDS
65 #include "defs.h"
66 #include <sys/stat.h>
67 #include <sys/signal.h>
68 #include <fcntl.h>
69 #include <stdlib.h>
70 #include "pathnames.h"
71
72 #define NRECORDS 50 /* size of circular trace buffer */
73 #ifdef DEBUG
74 FILE *ftrace = stdout;
75 int traceactions = 0;
76 #endif
77 static struct timeval lastlog;
78 static char *savetracename;
79
80 traceinit(ifp)
81 register struct interface *ifp;
82 {
83 static int iftraceinit();
84
85 if (iftraceinit(ifp, &ifp->int_input) &&
86 iftraceinit(ifp, &ifp->int_output))
87 return;
88 tracehistory = 0;
89 fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
90 }
91
92 static
93 iftraceinit(ifp, ifd)
94 struct interface *ifp;
95 register struct ifdebug *ifd;
96 {
97 register struct iftrace *t;
98
99 ifd->ifd_records =
100 (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
101 if (ifd->ifd_records == 0)
102 return (0);
103 ifd->ifd_front = ifd->ifd_records;
104 ifd->ifd_count = 0;
105 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
106 t->ift_size = 0;
107 t->ift_packet = 0;
108 }
109 ifd->ifd_if = ifp;
110 return (1);
111 }
112
113 traceon(file)
114 char *file;
115 {
116 struct stat stbuf;
117
118 if (ftrace != NULL)
119 return;
120 if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
121 return;
122 savetracename = file;
123 (void) gettimeofday(&now, (struct timezone *)NULL);
124 ftrace = fopen(file, "a");
125 if (ftrace == NULL)
126 return;
127 dup2(fileno(ftrace), 1);
128 dup2(fileno(ftrace), 2);
129 traceactions = 1;
130 fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
131 }
132
133 traceoff()
134 {
135 if (!traceactions)
136 return;
137 if (ftrace != NULL) {
138 int fd = open(_PATH_DEVNULL, O_RDWR);
139
140 fprintf(ftrace, "Tracing disabled %s\n",
141 ctime((time_t *)&now.tv_sec));
142 fflush(ftrace);
143 (void) dup2(fd, 1);
144 (void) dup2(fd, 2);
145 (void) close(fd);
146 fclose(ftrace);
147 ftrace = NULL;
148 }
149 traceactions = 0;
150 tracehistory = 0;
151 tracepackets = 0;
152 tracecontents = 0;
153 }
154
155 void
156 sigtrace(s)
157 int s;
158 {
159
160 if (s == SIGUSR2)
161 traceoff();
162 else if (ftrace == NULL && savetracename)
163 traceon(savetracename);
164 else
165 bumploglevel();
166 }
167
168 /*
169 * Move to next higher level of tracing when -t option processed or
170 * SIGUSR1 is received. Successive levels are:
171 * traceactions
172 * traceactions + tracepackets
173 * traceactions + tracehistory (packets and contents after change)
174 * traceactions + tracepackets + tracecontents
175 */
176 bumploglevel()
177 {
178
179 (void) gettimeofday(&now, (struct timezone *)NULL);
180 if (traceactions == 0) {
181 traceactions++;
182 if (ftrace)
183 fprintf(ftrace, "Tracing actions started %s\n",
184 ctime((time_t *)&now.tv_sec));
185 } else if (tracepackets == 0) {
186 tracepackets++;
187 tracehistory = 0;
188 tracecontents = 0;
189 if (ftrace)
190 fprintf(ftrace, "Tracing packets started %s\n",
191 ctime((time_t *)&now.tv_sec));
192 } else if (tracehistory == 0) {
193 tracehistory++;
194 if (ftrace)
195 fprintf(ftrace, "Tracing history started %s\n",
196 ctime((time_t *)&now.tv_sec));
197 } else {
198 tracepackets++;
199 tracecontents++;
200 tracehistory = 0;
201 if (ftrace)
202 fprintf(ftrace, "Tracing packet contents started %s\n",
203 ctime((time_t *)&now.tv_sec));
204 }
205 if (ftrace)
206 fflush(ftrace);
207 }
208
209 trace(ifd, who, p, len, m)
210 register struct ifdebug *ifd;
211 struct sockaddr *who;
212 char *p;
213 int len, m;
214 {
215 register struct iftrace *t;
216
217 if (ifd->ifd_records == 0)
218 return;
219 t = ifd->ifd_front++;
220 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
221 ifd->ifd_front = ifd->ifd_records;
222 if (ifd->ifd_count < NRECORDS)
223 ifd->ifd_count++;
224 if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
225 free(t->ift_packet);
226 t->ift_packet = 0;
227 }
228 t->ift_stamp = now;
229 t->ift_who = *who;
230 if (len > 0 && t->ift_packet == 0) {
231 t->ift_packet = malloc(len);
232 if (t->ift_packet == 0)
233 len = 0;
234 }
235 if (len > 0)
236 memmove(t->ift_packet, p, len);
237 t->ift_size = len;
238 t->ift_metric = m;
239 }
240
241 traceaction(fd, action, rt)
242 FILE *fd;
243 char *action;
244 struct rt_entry *rt;
245 {
246 struct sockaddr_in *dst, *gate;
247 static struct bits {
248 int t_bits;
249 char *t_name;
250 } flagbits[] = {
251 { RTF_UP, "UP" },
252 { RTF_GATEWAY, "GATEWAY" },
253 { RTF_HOST, "HOST" },
254 { 0 }
255 }, statebits[] = {
256 { RTS_PASSIVE, "PASSIVE" },
257 { RTS_REMOTE, "REMOTE" },
258 { RTS_INTERFACE,"INTERFACE" },
259 { RTS_CHANGED, "CHANGED" },
260 { RTS_INTERNAL, "INTERNAL" },
261 { RTS_EXTERNAL, "EXTERNAL" },
262 { RTS_SUBNET, "SUBNET" },
263 { 0 }
264 };
265 register struct bits *p;
266 register int first;
267 char *cp;
268 struct interface *ifp;
269
270 if (fd == NULL)
271 return;
272 if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
273 fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
274 lastlog = now;
275 }
276 fprintf(fd, "%s ", action);
277 dst = (struct sockaddr_in *)&rt->rt_dst;
278 gate = (struct sockaddr_in *)&rt->rt_router;
279 fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
280 fprintf(fd, "router %s, metric %d, flags",
281 inet_ntoa(gate->sin_addr), rt->rt_metric);
282 cp = " %s";
283 for (first = 1, p = flagbits; p->t_bits > 0; p++) {
284 if ((rt->rt_flags & p->t_bits) == 0)
285 continue;
286 fprintf(fd, cp, p->t_name);
287 if (first) {
288 cp = "|%s";
289 first = 0;
290 }
291 }
292 fprintf(fd, " state");
293 cp = " %s";
294 for (first = 1, p = statebits; p->t_bits > 0; p++) {
295 if ((rt->rt_state & p->t_bits) == 0)
296 continue;
297 fprintf(fd, cp, p->t_name);
298 if (first) {
299 cp = "|%s";
300 first = 0;
301 }
302 }
303 fprintf(fd, " timer %d\n", rt->rt_timer);
304 if (tracehistory && !tracepackets &&
305 (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
306 dumpif(fd, rt->rt_ifp);
307 fflush(fd);
308 if (ferror(fd))
309 traceoff();
310 }
311
312 tracenewmetric(fd, rt, newmetric)
313 FILE *fd;
314 struct rt_entry *rt;
315 int newmetric;
316 {
317 struct sockaddr_in *dst, *gate;
318
319 if (fd == NULL)
320 return;
321 if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
322 fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
323 lastlog = now;
324 }
325 dst = (struct sockaddr_in *)&rt->rt_dst;
326 gate = (struct sockaddr_in *)&rt->rt_router;
327 fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
328 fprintf(fd, "router %s, from %d to %d\n",
329 inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
330 fflush(fd);
331 if (ferror(fd))
332 traceoff();
333 }
334
335 dumpif(fd, ifp)
336 FILE *fd;
337 register struct interface *ifp;
338 {
339 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
340 fprintf(fd, "*** Packet history for interface %s ***\n",
341 ifp->int_name);
342 #ifdef notneeded
343 dumptrace(fd, "to", &ifp->int_output);
344 #endif
345 dumptrace(fd, "from", &ifp->int_input);
346 fprintf(fd, "*** end packet history ***\n");
347 }
348 }
349
350 dumptrace(fd, dir, ifd)
351 FILE *fd;
352 char *dir;
353 register struct ifdebug *ifd;
354 {
355 register struct iftrace *t;
356 char *cp = !strcmp(dir, "to") ? "Output" : "Input";
357
358 if (ifd->ifd_front == ifd->ifd_records &&
359 ifd->ifd_front->ift_size == 0) {
360 fprintf(fd, "%s: no packets.\n", cp);
361 fflush(fd);
362 return;
363 }
364 fprintf(fd, "%s trace:\n", cp);
365 t = ifd->ifd_front - ifd->ifd_count;
366 if (t < ifd->ifd_records)
367 t += NRECORDS;
368 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
369 if (t >= ifd->ifd_records + NRECORDS)
370 t = ifd->ifd_records;
371 if (t->ift_size == 0)
372 continue;
373 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
374 &t->ift_stamp);
375 }
376 }
377
378 dumppacket(fd, dir, who, cp, size, stamp)
379 FILE *fd;
380 struct sockaddr_in *who; /* should be sockaddr */
381 char *dir, *cp;
382 register int size;
383 struct timeval *stamp;
384 {
385 register struct rip *msg = (struct rip *)cp;
386 register struct netinfo *n;
387
388 if (fd == NULL)
389 return;
390 if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
391 fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
392 dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
393 ctime((time_t *)&stamp->tv_sec));
394 else {
395 fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
396 dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
397 fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
398 ctime((time_t *)&stamp->tv_sec));
399 fflush(fd);
400 return;
401 }
402 if (tracepackets && tracecontents == 0) {
403 fflush(fd);
404 return;
405 }
406 switch (msg->rip_cmd) {
407
408 case RIPCMD_REQUEST:
409 case RIPCMD_RESPONSE:
410 size -= 4 * sizeof (char);
411 n = msg->rip_nets;
412 for (; size > 0; n++, size -= sizeof (struct netinfo)) {
413 if (size < sizeof (struct netinfo)) {
414 fprintf(fd, "(truncated record, len %d)\n",
415 size);
416 break;
417 }
418 if (sizeof(n->rip_dst.sa_family) > 1)
419 n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
420
421 switch ((int)n->rip_dst.sa_family) {
422
423 case AF_INET:
424 fprintf(fd, "\tdst %s metric %d\n",
425 #define satosin(sa) ((struct sockaddr_in *)&sa)
426 inet_ntoa(satosin(n->rip_dst)->sin_addr),
427 ntohl(n->rip_metric));
428 break;
429
430 default:
431 fprintf(fd, "\taf %d? metric %d\n",
432 n->rip_dst.sa_family,
433 ntohl(n->rip_metric));
434 break;
435 }
436 }
437 break;
438
439 case RIPCMD_TRACEON:
440 fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
441 break;
442
443 case RIPCMD_TRACEOFF:
444 break;
445 }
446 fflush(fd);
447 if (ferror(fd))
448 traceoff();
449 }