xref: /openbsd-src/usr.sbin/tcpdump/print-dvmrp.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: print-dvmrp.c,v 1.6 2009/10/27 23:59:55 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 1995, 1996
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #include <sys/param.h>
25 #include <sys/time.h>
26 #include <sys/socket.h>
27 
28 #include <netinet/in.h>
29 #include <netinet/in_systm.h>
30 #include <netinet/ip.h>
31 #include <netinet/ip_var.h>
32 #include <netinet/udp.h>
33 #include <netinet/udp_var.h>
34 #include <netinet/tcp.h>
35 
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 
41 #include "interface.h"
42 #include "addrtoname.h"
43 
44 /*
45  * DVMRP message types and flag values shamelessly stolen from
46  * mrouted/dvmrp.h.
47  */
48 #define DVMRP_PROBE		1	/* for finding neighbors */
49 #define DVMRP_REPORT		2	/* for reporting some or all routes */
50 #define DVMRP_ASK_NEIGHBORS	3	/* sent by mapper, asking for a list */
51 					/*
52 					 * of this router's neighbors
53 					 */
54 #define DVMRP_NEIGHBORS		4	/* response to such a request */
55 #define DVMRP_ASK_NEIGHBORS2	5	/* as above, want new format reply */
56 #define DVMRP_NEIGHBORS2	6
57 #define DVMRP_PRUNE		7	/* prune message */
58 #define DVMRP_GRAFT		8	/* graft message */
59 #define DVMRP_GRAFT_ACK		9	/* graft acknowledgement */
60 
61 /*
62  * 'flags' byte values in DVMRP_NEIGHBORS2 reply.
63  */
64 #define DVMRP_NF_TUNNEL		0x01	/* neighbors reached via tunnel */
65 #define DVMRP_NF_SRCRT		0x02	/* tunnel uses IP source routing */
66 #define DVMRP_NF_DOWN		0x10	/* kernel state of interface */
67 #define DVMRP_NF_DISABLED	0x20	/* administratively disabled */
68 #define DVMRP_NF_QUERIER	0x40	/* I am the subnet's querier */
69 
70 static void print_probe(const u_char *, const u_char *, u_int);
71 static void print_report(const u_char *, const u_char *, u_int);
72 static void print_neighbors(const u_char *, const u_char *, u_int);
73 static void print_neighbors2(const u_char *, const u_char *, u_int);
74 static void print_prune(const u_char *, const u_char *, u_int);
75 static void print_graft(const u_char *, const u_char *, u_int);
76 static void print_graft_ack(const u_char *, const u_char *, u_int);
77 
78 static u_int32_t target_level;
79 
80 void
81 dvmrp_print(register const u_char *bp, register u_int len)
82 {
83 	register const u_char *ep;
84 	register u_char type;
85 
86 	ep = (const u_char *)snapend;
87 	if (bp >= ep)
88 		return;
89 
90 	type = bp[1];
91 	bp += 8;
92 	/*
93 	 * Skip IGMP header
94 	 */
95 
96 	len -= 8;
97 
98 	switch (type) {
99 
100 	case DVMRP_PROBE:
101 		printf(" Probe");
102 		if (vflag)
103 			print_probe(bp, ep, len);
104 		break;
105 
106 	case DVMRP_REPORT:
107 		printf(" Report");
108 		if (vflag)
109 			print_report(bp, ep, len);
110 		break;
111 
112 	case DVMRP_ASK_NEIGHBORS:
113 		printf(" Ask-neighbors(old)");
114 		break;
115 
116 	case DVMRP_NEIGHBORS:
117 		printf(" Neighbors(old)");
118 		print_neighbors(bp, ep, len);
119 		break;
120 
121 	case DVMRP_ASK_NEIGHBORS2:
122 		printf(" Ask-neighbors2");
123 		break;
124 
125 	case DVMRP_NEIGHBORS2:
126 		printf(" Neighbors2");
127 		/*
128 		 * extract version and capabilities from IGMP group
129 		 * address field
130 		 */
131 		bp -= 4;
132 		target_level = (bp[0] << 24) | (bp[1] << 16) |
133 		    (bp[2] << 8) | bp[3];
134 		bp += 4;
135 		print_neighbors2(bp, ep, len);
136 		break;
137 
138 	case DVMRP_PRUNE:
139 		printf(" Prune");
140 		print_prune(bp, ep, len);
141 		break;
142 
143 	case DVMRP_GRAFT:
144 		printf(" Graft");
145 		print_graft(bp, ep, len);
146 		break;
147 
148 	case DVMRP_GRAFT_ACK:
149 		printf(" Graft-ACK");
150 		print_graft_ack(bp, ep, len);
151 		break;
152 
153 	default:
154 		printf(" [type %d]", type);
155 		break;
156 	}
157 }
158 
159 static void
160 print_report(register const u_char *bp, register const u_char *ep,
161     register u_int len)
162 {
163 	register u_int32_t mask, origin;
164 	register int metric, i, width, done;
165 
166 	while (len > 0) {
167 		if (len < 3) {
168 			printf(" [|]");
169 			return;
170 		}
171 		mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2];
172 		width = 1;
173 		if (bp[0])
174 			width = 2;
175 		if (bp[1])
176 			width = 3;
177 		if (bp[2])
178 			width = 4;
179 
180 		printf("\n\tMask %s", intoa(htonl(mask)));
181 		bp += 3;
182 		len -= 3;
183 		do {
184 			if (bp + width + 1 > ep) {
185 				printf(" [|]");
186 				return;
187 			}
188 			if (len < width + 1) {
189 				printf("\n\t  [Truncated Report]");
190 				return;
191 			}
192 			origin = 0;
193 			for (i = 0; i < width; ++i)
194 				origin = origin << 8 | *bp++;
195 			for ( ; i < 4; ++i)
196 				origin <<= 8;
197 
198 			metric = *bp++;
199 			done = metric & 0x80;
200 			metric &= 0x7f;
201 			printf("\n\t  %s metric %d", intoa(htonl(origin)),
202 				metric);
203 			len -= width + 1;
204 		} while (!done);
205 	}
206 }
207 
208 #define GET_ADDR(to) (memcpy((char *)to, (char *)bp, 4), bp += 4)
209 
210 static void
211 print_probe(register const u_char *bp, register const u_char *ep,
212     register u_int len)
213 {
214 	register u_int32_t genid;
215 	u_char neighbor[4];
216 
217 	if ((len < 4) || ((bp + 4) > ep)) {
218 		/* { (ctags) */
219 		printf(" [|}");
220 		return;
221 	}
222 	genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
223 	bp += 4;
224 	len -= 4;
225 	printf("\n\tgenid %u", genid);
226 
227 	while ((len > 0) && (bp < ep)) {
228 		if ((len < 4) || ((bp + 4) > ep)) {
229 			printf(" [|]");
230 			return;
231 		}
232 		GET_ADDR(neighbor);
233 		len -= 4;
234 		printf("\n\tneighbor %s", ipaddr_string(neighbor));
235 	}
236 }
237 
238 static void
239 print_neighbors(register const u_char *bp, register const u_char *ep,
240     register u_int len)
241 {
242 	u_char laddr[4], neighbor[4];
243 	register u_char metric;
244 	register u_char thresh;
245 	register int ncount;
246 
247 	while (len > 0 && bp < ep) {
248 		if (len < 7 || (bp + 7) >= ep) {
249 			printf(" [|]");
250 			return;
251 		}
252 		GET_ADDR(laddr);
253 		metric = *bp++;
254 		thresh = *bp++;
255 		ncount = *bp++;
256 		len -= 7;
257 		while (--ncount >= 0 && (len >= 4) && (bp + 4) < ep) {
258 			GET_ADDR(neighbor);
259 			printf(" [%s ->", ipaddr_string(laddr));
260 			printf(" %s, (%d/%d)]",
261 				   ipaddr_string(neighbor), metric, thresh);
262 			len -= 4;
263 		}
264 	}
265 }
266 
267 static void
268 print_neighbors2(register const u_char *bp, register const u_char *ep,
269     register u_int len)
270 {
271 	u_char laddr[4], neighbor[4];
272 	register u_char metric, thresh, flags;
273 	register int ncount;
274 
275 	printf(" (v %d.%d):",
276 	       (int)target_level & 0xff,
277 	       (int)(target_level >> 8) & 0xff);
278 
279 	while (len > 0 && bp < ep) {
280 		if (len < 8 || (bp + 8) >= ep) {
281 			printf(" [|]");
282 			return;
283 		}
284 		GET_ADDR(laddr);
285 		metric = *bp++;
286 		thresh = *bp++;
287 		flags = *bp++;
288 		ncount = *bp++;
289 		len -= 8;
290 		while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) {
291 			GET_ADDR(neighbor);
292 			printf(" [%s -> ", ipaddr_string(laddr));
293 			printf("%s (%d/%d", ipaddr_string(neighbor),
294 				     metric, thresh);
295 			if (flags & DVMRP_NF_TUNNEL)
296 				printf("/tunnel");
297 			if (flags & DVMRP_NF_SRCRT)
298 				printf("/srcrt");
299 			if (flags & DVMRP_NF_QUERIER)
300 				printf("/querier");
301 			if (flags & DVMRP_NF_DISABLED)
302 				printf("/disabled");
303 			if (flags & DVMRP_NF_DOWN)
304 				printf("/down");
305 			printf(")]");
306 			len -= 4;
307 		}
308 		if (ncount != -1) {
309 			printf(" [|]");
310 			return;
311 		}
312 	}
313 }
314 
315 static void
316 print_prune(register const u_char *bp, register const u_char *ep,
317     register u_int len)
318 {
319 	union a {
320 		u_char b[4];
321 		u_int32_t i;
322 	} prune_timer;
323 
324 	if (len < 12 || (bp + 12) > ep) {
325 		printf(" [|]");
326 		return;
327 	}
328 	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
329 	bp += 8;
330 	GET_ADDR(prune_timer.b);
331 	printf(" timer %d", (int)ntohl(prune_timer.i));
332 }
333 
334 static void
335 print_graft(register const u_char *bp, register const u_char *ep,
336     register u_int len)
337 {
338 
339 	if (len < 8 || (bp + 8) > ep) {
340 		printf(" [|]");
341 		return;
342 	}
343 	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
344 }
345 
346 static void
347 print_graft_ack(register const u_char *bp, register const u_char *ep,
348     register u_int len)
349 {
350 
351 	if (len < 8 || (bp + 8) > ep) {
352 		printf(" [|]");
353 		return;
354 	}
355 	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
356 }
357