|
|
1.1 root 1: /*
2: * Copyright (c) 1983, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)trace.c 5.10 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Routing Table Management Daemon
26: */
27: #define RIPCMDS
28: #include "defs.h"
29: #include <sys/file.h>
30: #include <sys/stat.h>
31: #include <sys/signal.h>
32: #include "pathnames.h"
33:
34: #define NRECORDS 50 /* size of circular trace buffer */
35: #ifdef DEBUG
36: FILE *ftrace = stdout;
37: int traceactions = 0;
38: #endif
39: static struct timeval lastlog;
40: static char *savetracename;
41:
42: traceinit(ifp)
43: register struct interface *ifp;
44: {
45:
46: if (iftraceinit(ifp, &ifp->int_input) &&
47: iftraceinit(ifp, &ifp->int_output))
48: return;
49: tracehistory = 0;
50: fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
51: }
52:
53: static
54: iftraceinit(ifp, ifd)
55: struct interface *ifp;
56: register struct ifdebug *ifd;
57: {
58: register struct iftrace *t;
59:
60: ifd->ifd_records =
61: (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
62: if (ifd->ifd_records == 0)
63: return (0);
64: ifd->ifd_front = ifd->ifd_records;
65: ifd->ifd_count = 0;
66: for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
67: t->ift_size = 0;
68: t->ift_packet = 0;
69: }
70: ifd->ifd_if = ifp;
71: return (1);
72: }
73:
74: traceon(file)
75: char *file;
76: {
77: struct stat stbuf;
78:
79: if (ftrace != NULL)
80: return;
81: if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG)
82: return;
83: savetracename = file;
84: (void) gettimeofday(&now, (struct timezone *)NULL);
85: ftrace = fopen(file, "a");
86: if (ftrace == NULL)
87: return;
88: dup2(fileno(ftrace), 1);
89: dup2(fileno(ftrace), 2);
90: traceactions = 1;
91: fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec));
92: }
93:
94: traceoff()
95: {
96: if (!traceactions)
97: return;
98: if (ftrace != NULL) {
99: int fd = open(_PATH_DEVNULL, O_RDWR);
100:
101: fprintf(ftrace, "Tracing disabled %s\n",
102: ctime((time_t *)&now.tv_sec));
103: fflush(ftrace);
104: (void) dup2(fd, 1);
105: (void) dup2(fd, 2);
106: (void) close(fd);
107: fclose(ftrace);
108: ftrace = NULL;
109: }
110: traceactions = 0;
111: tracehistory = 0;
112: tracepackets = 0;
113: tracecontents = 0;
114: }
115:
116: sigtrace(s)
117: int s;
118: {
119:
120: if (s == SIGUSR2)
121: traceoff();
122: else if (ftrace == NULL && savetracename)
123: traceon(savetracename);
124: else
125: bumploglevel();
126: }
127:
128: /*
129: * Move to next higher level of tracing when -t option processed or
130: * SIGUSR1 is received. Successive levels are:
131: * traceactions
132: * traceactions + tracepackets
133: * traceactions + tracehistory (packets and contents after change)
134: * traceactions + tracepackets + tracecontents
135: */
136: bumploglevel()
137: {
138:
139: (void) gettimeofday(&now, (struct timezone *)NULL);
140: if (traceactions == 0) {
141: traceactions++;
142: if (ftrace)
143: fprintf(ftrace, "Tracing actions started %s\n",
144: ctime((time_t *)&now.tv_sec));
145: } else if (tracepackets == 0) {
146: tracepackets++;
147: tracehistory = 0;
148: tracecontents = 0;
149: if (ftrace)
150: fprintf(ftrace, "Tracing packets started %s\n",
151: ctime((time_t *)&now.tv_sec));
152: } else if (tracehistory == 0) {
153: tracehistory++;
154: if (ftrace)
155: fprintf(ftrace, "Tracing history started %s\n",
156: ctime((time_t *)&now.tv_sec));
157: } else {
158: tracepackets++;
159: tracecontents++;
160: tracehistory = 0;
161: if (ftrace)
162: fprintf(ftrace, "Tracing packet contents started %s\n",
163: ctime((time_t *)&now.tv_sec));
164: }
165: if (ftrace)
166: fflush(ftrace);
167: }
168:
169: trace(ifd, who, p, len, m)
170: register struct ifdebug *ifd;
171: struct sockaddr *who;
172: char *p;
173: int len, m;
174: {
175: register struct iftrace *t;
176:
177: if (ifd->ifd_records == 0)
178: return;
179: t = ifd->ifd_front++;
180: if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
181: ifd->ifd_front = ifd->ifd_records;
182: if (ifd->ifd_count < NRECORDS)
183: ifd->ifd_count++;
184: if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) {
185: free(t->ift_packet);
186: t->ift_packet = 0;
187: }
188: t->ift_stamp = now;
189: t->ift_who = *who;
190: if (len > 0 && t->ift_packet == 0) {
191: t->ift_packet = malloc(len);
192: if (t->ift_packet == 0)
193: len = 0;
194: }
195: if (len > 0)
196: bcopy(p, t->ift_packet, len);
197: t->ift_size = len;
198: t->ift_metric = m;
199: }
200:
201: traceaction(fd, action, rt)
202: FILE *fd;
203: char *action;
204: struct rt_entry *rt;
205: {
206: struct sockaddr_in *dst, *gate;
207: static struct bits {
208: int t_bits;
209: char *t_name;
210: } flagbits[] = {
211: { RTF_UP, "UP" },
212: { RTF_GATEWAY, "GATEWAY" },
213: { RTF_HOST, "HOST" },
214: { 0 }
215: }, statebits[] = {
216: { RTS_PASSIVE, "PASSIVE" },
217: { RTS_REMOTE, "REMOTE" },
218: { RTS_INTERFACE,"INTERFACE" },
219: { RTS_CHANGED, "CHANGED" },
220: { RTS_INTERNAL, "INTERNAL" },
221: { RTS_EXTERNAL, "EXTERNAL" },
222: { RTS_SUBNET, "SUBNET" },
223: { 0 }
224: };
225: register struct bits *p;
226: register int first;
227: char *cp;
228: struct interface *ifp;
229:
230: if (fd == NULL)
231: return;
232: if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
233: fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
234: lastlog = now;
235: }
236: fprintf(fd, "%s ", action);
237: dst = (struct sockaddr_in *)&rt->rt_dst;
238: gate = (struct sockaddr_in *)&rt->rt_router;
239: fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
240: fprintf(fd, "router %s, metric %d, flags",
241: inet_ntoa(gate->sin_addr), rt->rt_metric);
242: cp = " %s";
243: for (first = 1, p = flagbits; p->t_bits > 0; p++) {
244: if ((rt->rt_flags & p->t_bits) == 0)
245: continue;
246: fprintf(fd, cp, p->t_name);
247: if (first) {
248: cp = "|%s";
249: first = 0;
250: }
251: }
252: fprintf(fd, " state");
253: cp = " %s";
254: for (first = 1, p = statebits; p->t_bits > 0; p++) {
255: if ((rt->rt_state & p->t_bits) == 0)
256: continue;
257: fprintf(fd, cp, p->t_name);
258: if (first) {
259: cp = "|%s";
260: first = 0;
261: }
262: }
263: fprintf(fd, " timer %d\n", rt->rt_timer);
264: if (tracehistory && !tracepackets &&
265: (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
266: dumpif(fd, rt->rt_ifp);
267: fflush(fd);
268: if (ferror(fd))
269: traceoff();
270: }
271:
272: tracenewmetric(fd, rt, newmetric)
273: FILE *fd;
274: struct rt_entry *rt;
275: int newmetric;
276: {
277: struct sockaddr_in *dst, *gate;
278:
279: if (fd == NULL)
280: return;
281: if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) {
282: fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec));
283: lastlog = now;
284: }
285: dst = (struct sockaddr_in *)&rt->rt_dst;
286: gate = (struct sockaddr_in *)&rt->rt_router;
287: fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr));
288: fprintf(fd, "router %s, from %d to %d\n",
289: inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric);
290: fflush(fd);
291: if (ferror(fd))
292: traceoff();
293: }
294:
295: dumpif(fd, ifp)
296: FILE *fd;
297: register struct interface *ifp;
298: {
299: if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
300: fprintf(fd, "*** Packet history for interface %s ***\n",
301: ifp->int_name);
302: #ifdef notneeded
303: dumptrace(fd, "to", &ifp->int_output);
304: #endif
305: dumptrace(fd, "from", &ifp->int_input);
306: fprintf(fd, "*** end packet history ***\n");
307: }
308: }
309:
310: dumptrace(fd, dir, ifd)
311: FILE *fd;
312: char *dir;
313: register struct ifdebug *ifd;
314: {
315: register struct iftrace *t;
316: char *cp = !strcmp(dir, "to") ? "Output" : "Input";
317:
318: if (ifd->ifd_front == ifd->ifd_records &&
319: ifd->ifd_front->ift_size == 0) {
320: fprintf(fd, "%s: no packets.\n", cp);
321: fflush(fd);
322: return;
323: }
324: fprintf(fd, "%s trace:\n", cp);
325: t = ifd->ifd_front - ifd->ifd_count;
326: if (t < ifd->ifd_records)
327: t += NRECORDS;
328: for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
329: if (t >= ifd->ifd_records + NRECORDS)
330: t = ifd->ifd_records;
331: if (t->ift_size == 0)
332: continue;
333: dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size,
334: &t->ift_stamp);
335: }
336: }
337:
338: dumppacket(fd, dir, who, cp, size, stamp)
339: FILE *fd;
340: struct sockaddr_in *who; /* should be sockaddr */
341: char *dir, *cp;
342: register int size;
343: struct timeval *stamp;
344: {
345: register struct rip *msg = (struct rip *)cp;
346: register struct netinfo *n;
347:
348: if (fd == NULL)
349: return;
350: if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
351: fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
352: dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
353: ctime((time_t *)&stamp->tv_sec));
354: else {
355: fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd,
356: dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
357: fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet,
358: ctime((time_t *)&stamp->tv_sec));
359: fflush(fd);
360: return;
361: }
362: if (tracepackets && tracecontents == 0) {
363: fflush(fd);
364: return;
365: }
366: switch (msg->rip_cmd) {
367:
368: case RIPCMD_REQUEST:
369: case RIPCMD_RESPONSE:
370: size -= 4 * sizeof (char);
371: n = msg->rip_nets;
372: for (; size > 0; n++, size -= sizeof (struct netinfo)) {
373: if (size < sizeof (struct netinfo)) {
374: fprintf(fd, "(truncated record, len %d)\n",
375: size);
376: break;
377: }
378: if (sizeof(n->rip_dst.sa_family) > 1)
379: n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);
380:
381: switch ((int)n->rip_dst.sa_family) {
382:
383: case AF_INET:
384: fprintf(fd, "\tdst %s metric %d\n",
385: #define satosin(sa) ((struct sockaddr_in *)&sa)
386: inet_ntoa(satosin(n->rip_dst)->sin_addr),
387: ntohl(n->rip_metric));
388: break;
389:
390: default:
391: fprintf(fd, "\taf %d? metric %d\n",
392: n->rip_dst.sa_family,
393: ntohl(n->rip_metric));
394: break;
395: }
396: }
397: break;
398:
399: case RIPCMD_TRACEON:
400: fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
401: break;
402:
403: case RIPCMD_TRACEOFF:
404: break;
405: }
406: fflush(fd);
407: if (ferror(fd))
408: traceoff();
409: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.