1 /*
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This file includes significant work done at Cornell University by
6 * Bill Nesheim. That work included by permission.
7 *
8 * %sccs.include.redist.c%
9 */
10
11 #ifndef lint
12 static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 06/05/93";
13 #endif /* not lint */
14
15 /*
16 * Routing Table Management Daemon
17 */
18 #define RIPCMDS
19 #include <stdlib.h>
20 #include "defs.h"
21
22 #define NRECORDS 50 /* size of circular trace buffer */
23 #ifdef DEBUG
24 FILE *ftrace = stdout;
25 int tracing = 1;
26 #else DEBUG
27 FILE *ftrace = NULL;
28 int tracing = 0;
29 #endif
30
31 char *xns_ntoa();
32
traceinit(ifp)33 traceinit(ifp)
34 register struct interface *ifp;
35 {
36 static int iftraceinit();
37
38 if (iftraceinit(ifp, &ifp->int_input) &&
39 iftraceinit(ifp, &ifp->int_output))
40 return;
41 tracing = 0;
42 syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
43 }
44
45 static
46 iftraceinit(ifp, ifd)
47 struct interface *ifp;
48 register struct ifdebug *ifd;
49 {
50 register struct iftrace *t;
51
52 ifd->ifd_records =
53 (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
54 if (ifd->ifd_records == 0)
55 return (0);
56 ifd->ifd_front = ifd->ifd_records;
57 ifd->ifd_count = 0;
58 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
59 t->ift_size = 0;
60 t->ift_packet = 0;
61 }
62 ifd->ifd_if = ifp;
63 return (1);
64 }
65
traceon(file)66 traceon(file)
67 char *file;
68 {
69
70 if (ftrace != NULL)
71 return;
72 ftrace = fopen(file, "a");
73 if (ftrace == NULL)
74 return;
75 dup2(fileno(ftrace), 1);
76 dup2(fileno(ftrace), 2);
77 tracing = 1;
78 }
79
traceoff()80 traceoff()
81 {
82 if (!tracing)
83 return;
84 if (ftrace != NULL)
85 fclose(ftrace);
86 ftrace = NULL;
87 tracing = 0;
88 }
89
trace(ifd,who,p,len,m)90 trace(ifd, who, p, len, m)
91 register struct ifdebug *ifd;
92 struct sockaddr *who;
93 char *p;
94 int len, m;
95 {
96 register struct iftrace *t;
97
98 if (ifd->ifd_records == 0)
99 return;
100 t = ifd->ifd_front++;
101 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
102 ifd->ifd_front = ifd->ifd_records;
103 if (ifd->ifd_count < NRECORDS)
104 ifd->ifd_count++;
105 if (t->ift_size > 0 && t->ift_packet)
106 free(t->ift_packet);
107 t->ift_packet = 0;
108 t->ift_stamp = time(0);
109 t->ift_who = *who;
110 if (len > 0) {
111 t->ift_packet = malloc(len);
112 if (t->ift_packet)
113 bcopy(p, t->ift_packet, len);
114 else
115 len = 0;
116 }
117 t->ift_size = len;
118 t->ift_metric = m;
119 }
120
traceaction(fd,action,rt)121 traceaction(fd, action, rt)
122 FILE *fd;
123 char *action;
124 struct rt_entry *rt;
125 {
126 struct sockaddr_ns *dst, *gate;
127 static struct bits {
128 int t_bits;
129 char *t_name;
130 } flagbits[] = {
131 { RTF_UP, "UP" },
132 { RTF_GATEWAY, "GATEWAY" },
133 { RTF_HOST, "HOST" },
134 { 0 }
135 }, statebits[] = {
136 { RTS_PASSIVE, "PASSIVE" },
137 { RTS_REMOTE, "REMOTE" },
138 { RTS_INTERFACE,"INTERFACE" },
139 { RTS_CHANGED, "CHANGED" },
140 { 0 }
141 };
142 register struct bits *p;
143 register int first;
144 char *cp;
145 struct interface *ifp;
146
147 if (fd == NULL)
148 return;
149 fprintf(fd, "%s ", action);
150 dst = (struct sockaddr_ns *)&rt->rt_dst;
151 gate = (struct sockaddr_ns *)&rt->rt_router;
152 fprintf(fd, "dst %s, ", xns_ntoa(&dst->sns_addr));
153 fprintf(fd, "router %s, metric %d, flags",
154 xns_ntoa(&gate->sns_addr), rt->rt_metric);
155 cp = " %s";
156 for (first = 1, p = flagbits; p->t_bits > 0; p++) {
157 if ((rt->rt_flags & p->t_bits) == 0)
158 continue;
159 fprintf(fd, cp, p->t_name);
160 if (first) {
161 cp = "|%s";
162 first = 0;
163 }
164 }
165 fprintf(fd, " state");
166 cp = " %s";
167 for (first = 1, p = statebits; p->t_bits > 0; p++) {
168 if ((rt->rt_state & p->t_bits) == 0)
169 continue;
170 fprintf(fd, cp, p->t_name);
171 if (first) {
172 cp = "|%s";
173 first = 0;
174 }
175 }
176 putc('\n', fd);
177 if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
178 dumpif(fd, rt->rt_ifp);
179 fflush(fd);
180 }
181
dumpif(fd,ifp)182 dumpif(fd, ifp)
183 register struct interface *ifp;
184 FILE *fd;
185 {
186 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
187 fprintf(fd, "*** Packet history for interface %s ***\n",
188 ifp->int_name);
189 dumptrace(fd, "to", &ifp->int_output);
190 dumptrace(fd, "from", &ifp->int_input);
191 fprintf(fd, "*** end packet history ***\n");
192 }
193 }
194
dumptrace(fd,dir,ifd)195 dumptrace(fd, dir, ifd)
196 FILE *fd;
197 char *dir;
198 register struct ifdebug *ifd;
199 {
200 register struct iftrace *t;
201 char *cp = !strcmp(dir, "to") ? "Output" : "Input";
202
203 if (ifd->ifd_front == ifd->ifd_records &&
204 ifd->ifd_front->ift_size == 0) {
205 fprintf(fd, "%s: no packets.\n", cp);
206 return;
207 }
208 fprintf(fd, "%s trace:\n", cp);
209 t = ifd->ifd_front - ifd->ifd_count;
210 if (t < ifd->ifd_records)
211 t += NRECORDS;
212 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
213 if (t >= ifd->ifd_records + NRECORDS)
214 t = ifd->ifd_records;
215 if (t->ift_size == 0)
216 continue;
217 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
218 t->ift_metric);
219 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
220 }
221 }
222
dumppacket(fd,dir,who,cp,size)223 dumppacket(fd, dir, who, cp, size)
224 FILE *fd;
225 struct sockaddr_ns *who; /* should be sockaddr */
226 char *dir, *cp;
227 register int size;
228 {
229 register struct rip *msg = (struct rip *)cp;
230 register struct netinfo *n;
231 char *xns_nettoa();
232
233 if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
234 fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
235 dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
236 else {
237 fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
238 dir, xns_ntoa(&who->sns_addr), ntohs(who->sns_addr.x_port));
239 fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
240 return;
241 }
242 switch (ntohs(msg->rip_cmd)) {
243
244 case RIPCMD_REQUEST:
245 case RIPCMD_RESPONSE:
246 fprintf(fd, ":\n");
247 size -= sizeof (u_short);
248 n = msg->rip_nets;
249 for (; size > 0; n++, size -= sizeof (struct netinfo)) {
250 if (size < sizeof (struct netinfo))
251 break;
252 fprintf(fd, "\tnet %s metric %d\n",
253 xns_nettoa(n->rip_dst),
254 ntohs(n->rip_metric));
255 }
256 break;
257
258 }
259 }
260
261 union ns_net_u net;
262
263 char *
xns_nettoa(val)264 xns_nettoa(val)
265 union ns_net val;
266 {
267 static char buf[100];
268 net.net_e = val;
269 (void)sprintf(buf, "%lx", ntohl(net.long_e));
270 return (buf);
271 }
272
273
274 char *
xns_ntoa(addr)275 xns_ntoa(addr)
276 struct ns_addr *addr;
277 {
278 static char buf[100];
279
280 (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
281 xns_nettoa(addr->x_net),
282 addr->x_host.c_host[0], addr->x_host.c_host[1],
283 addr->x_host.c_host[2], addr->x_host.c_host[3],
284 addr->x_host.c_host[4], addr->x_host.c_host[5]);
285
286 return(buf);
287 }
288