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