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