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