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