Fix mbuf handling for unsupported operations
[unix-history] / usr / src / sbin / routed / trace.c
CommitLineData
f036a54d 1#ifndef lint
b7e4f8be 2static char sccsid[] = "@(#)trace.c 4.6 (Berkeley) %G%";
f036a54d
SL
3#endif
4
5/*
6 * Routing Table Management Daemon
7 */
8#define RIPCMDS
7fe7fe74 9#include "defs.h"
f036a54d
SL
10
11#define NRECORDS 50 /* size of circular trace buffer */
12#ifdef DEBUG
13FILE *ftrace = stdout;
14int tracing = 1;
15#endif
16
17traceinit(ifp)
18 register struct interface *ifp;
19{
20
21 if (iftraceinit(ifp, &ifp->int_input) &&
22 iftraceinit(ifp, &ifp->int_output))
23 return;
24 tracing = 0;
25 fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name);
26}
27
28static
29iftraceinit(ifp, ifd)
30 struct interface *ifp;
31 register struct ifdebug *ifd;
32{
33 register struct iftrace *t;
34
35 ifd->ifd_records =
36 (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
37 if (ifd->ifd_records == 0)
38 return (0);
39 ifd->ifd_front = ifd->ifd_records;
b7e4f8be 40 ifd->ifd_count = 0;
f036a54d
SL
41 for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
42 t->ift_size = 0;
43 t->ift_packet = 0;
44 }
45 ifd->ifd_if = ifp;
46 return (1);
47}
48
49traceon(file)
50 char *file;
51{
52
53 if (ftrace != NULL)
54 return;
55 ftrace = fopen(file, "a");
56 if (ftrace == NULL)
57 return;
58 dup2(fileno(ftrace), 1);
59 dup2(fileno(ftrace), 2);
60 tracing = 1;
61}
62
63traceoff()
64{
65 if (!tracing)
66 return;
67 if (ftrace != NULL)
68 fclose(ftrace);
69 ftrace = NULL;
70 tracing = 0;
71}
72
73trace(ifd, who, p, len, m)
74 register struct ifdebug *ifd;
75 struct sockaddr *who;
76 char *p;
77 int len, m;
78{
79 register struct iftrace *t;
80
81 if (ifd->ifd_records == 0)
82 return;
83 t = ifd->ifd_front++;
84 if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
85 ifd->ifd_front = ifd->ifd_records;
b7e4f8be
MK
86 if (ifd->ifd_count < NRECORDS)
87 ifd->ifd_count++;
f036a54d
SL
88 if (t->ift_size > 0 && t->ift_packet)
89 free(t->ift_packet);
90 t->ift_packet = 0;
91 t->ift_stamp = time(0);
92 t->ift_who = *who;
93 if (len > 0) {
94 t->ift_packet = malloc(len);
95 if (t->ift_packet)
96 bcopy(p, t->ift_packet, len);
97 else
98 len = 0;
99 }
100 t->ift_size = len;
101 t->ift_metric = m;
102}
103
104traceaction(fd, action, rt)
105 FILE *fd;
106 char *action;
107 struct rt_entry *rt;
108{
109 struct sockaddr_in *dst, *gate;
110 static struct bits {
111 int t_bits;
112 char *t_name;
113 } flagbits[] = {
114 { RTF_UP, "UP" },
115 { RTF_GATEWAY, "GATEWAY" },
116 { RTF_HOST, "HOST" },
117 { 0 }
118 }, statebits[] = {
119 { RTS_PASSIVE, "PASSIVE" },
120 { RTS_REMOTE, "REMOTE" },
121 { RTS_INTERFACE,"INTERFACE" },
122 { RTS_CHANGED, "CHANGED" },
123 { 0 }
124 };
125 register struct bits *p;
126 register int first;
127 char *cp;
128 struct interface *ifp;
129
130 if (fd == NULL)
131 return;
132 fprintf(fd, "%s ", action);
133 dst = (struct sockaddr_in *)&rt->rt_dst;
134 gate = (struct sockaddr_in *)&rt->rt_router;
2513c24a
SL
135 fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr));
136 fprintf(fd, "router %s, metric %d, flags",
137 inet_ntoa(gate->sin_addr), rt->rt_metric);
f036a54d
SL
138 cp = " %s";
139 for (first = 1, p = flagbits; p->t_bits > 0; p++) {
140 if ((rt->rt_flags & p->t_bits) == 0)
141 continue;
142 fprintf(fd, cp, p->t_name);
143 if (first) {
144 cp = "|%s";
145 first = 0;
146 }
147 }
148 fprintf(fd, " state");
149 cp = " %s";
150 for (first = 1, p = statebits; p->t_bits > 0; p++) {
151 if ((rt->rt_state & p->t_bits) == 0)
152 continue;
153 fprintf(fd, cp, p->t_name);
154 if (first) {
155 cp = "|%s";
156 first = 0;
157 }
158 }
159 putc('\n', fd);
d5568f13 160 if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
f036a54d
SL
161 dumpif(fd, rt->rt_ifp);
162 fflush(fd);
163}
164
165dumpif(fd, ifp)
166 register struct interface *ifp;
167{
b7e4f8be
MK
168 if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
169 fprintf(fd, "*** Packet history for interface %s ***\n",
170 ifp->int_name);
171 dumptrace(fd, "to", &ifp->int_output);
172 dumptrace(fd, "from", &ifp->int_input);
173 fprintf(fd, "*** end packet history ***\n");
174 }
f036a54d
SL
175}
176
177dumptrace(fd, dir, ifd)
178 FILE *fd;
179 char *dir;
180 register struct ifdebug *ifd;
181{
182 register struct iftrace *t;
183 char *cp = !strcmp(dir, "to") ? "Output" : "Input";
184
185 if (ifd->ifd_front == ifd->ifd_records &&
186 ifd->ifd_front->ift_size == 0) {
187 fprintf(fd, "%s: no packets.\n", cp);
188 return;
189 }
190 fprintf(fd, "%s trace:\n", cp);
b7e4f8be
MK
191 t = ifd->ifd_front - ifd->ifd_count;
192 if (t < ifd->ifd_records)
193 t += NRECORDS;
194 for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
195 if (t >= ifd->ifd_records + NRECORDS)
196 t = ifd->ifd_records;
f036a54d
SL
197 if (t->ift_size == 0)
198 continue;
199 fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
200 t->ift_metric);
201 dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
202 }
203}
204
205dumppacket(fd, dir, who, cp, size)
206 FILE *fd;
207 struct sockaddr_in *who; /* should be sockaddr */
208 char *dir, *cp;
209 register int size;
210{
211 register struct rip *msg = (struct rip *)cp;
212 register struct netinfo *n;
213
214 if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
2513c24a
SL
215 fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd],
216 dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
f036a54d
SL
217 else {
218 fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd,
2513c24a 219 dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port));
f036a54d
SL
220 fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet);
221 return;
222 }
223 switch (msg->rip_cmd) {
224
225 case RIPCMD_REQUEST:
226 case RIPCMD_RESPONSE:
227 fprintf(fd, ":\n");
228 size -= 4 * sizeof (char);
229 n = msg->rip_nets;
230 for (; size > 0; n++, size -= sizeof (struct netinfo)) {
231 if (size < sizeof (struct netinfo))
232 break;
2513c24a
SL
233 fprintf(fd, "\tdst %s metric %d\n",
234#define satosin(sa) ((struct sockaddr_in *)&sa)
235 inet_ntoa(satosin(n->rip_dst)->sin_addr),
236 ntohl(n->rip_metric));
f036a54d
SL
237 }
238 break;
239
240 case RIPCMD_TRACEON:
241 fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile);
242 break;
243
244 case RIPCMD_TRACEOFF:
245 fprintf(fd, "\n");
246 break;
247 }
248}