]> git.saurik.com Git - apple/network_cmds.git/blame - routed.tproj/trace.c
network_cmds-245.tar.gz
[apple/network_cmds.git] / routed.tproj / trace.c
CommitLineData
b7080c8e
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
2b484d24
A
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.
b7080c8e
A
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,
2b484d24
A
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."
b7080c8e
A
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
73FILE *ftrace = stdout;
74int traceactions = 0;
75#endif
76static struct timeval lastlog;
77static char *savetracename;
78
2b484d24
A
79static int iftraceinit();
80
b7080c8e
A
81traceinit(ifp)
82 register struct interface *ifp;
83{
b7080c8e
A
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
2b484d24 92
b7080c8e
A
93iftraceinit(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
113traceon(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
133traceoff()
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
155void
156sigtrace(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 */
176bumploglevel()
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
209trace(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
241traceaction(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
312tracenewmetric(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
335dumpif(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
350dumptrace(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
378dumppacket(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}