print-dvmrp.c revision 26180
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#ifndef lint
23static const char rcsid[] =
24    "@(#) $Header: print-dvmrp.c,v 1.13 96/12/10 23:16:30 leres Exp $ (LBL)";
25#endif
26
27#include <sys/param.h>
28#include <sys/time.h>
29#include <sys/socket.h>
30
31#include <netinet/in.h>
32#include <netinet/in_systm.h>
33#include <netinet/ip.h>
34#include <netinet/ip_var.h>
35#include <netinet/udp.h>
36#include <netinet/udp_var.h>
37#include <netinet/tcp.h>
38#include <netinet/tcpip.h>
39
40#include <stdio.h>
41#include <string.h>
42#include <stdlib.h>
43#include <unistd.h>
44
45#include "interface.h"
46#include "addrtoname.h"
47
48/*
49 * DVMRP message types and flag values shamelessly stolen from
50 * mrouted/dvmrp.h.
51 */
52#define DVMRP_PROBE		1	/* for finding neighbors */
53#define DVMRP_REPORT		2	/* for reporting some or all routes */
54#define DVMRP_ASK_NEIGHBORS	3	/* sent by mapper, asking for a list */
55					/*
56					 * of this router's neighbors
57					 */
58#define DVMRP_NEIGHBORS		4	/* response to such a request */
59#define DVMRP_ASK_NEIGHBORS2	5	/* as above, want new format reply */
60#define DVMRP_NEIGHBORS2	6
61#define DVMRP_PRUNE		7	/* prune message */
62#define DVMRP_GRAFT		8	/* graft message */
63#define DVMRP_GRAFT_ACK		9	/* graft acknowledgement */
64
65/*
66 * 'flags' byte values in DVMRP_NEIGHBORS2 reply.
67 */
68#define DVMRP_NF_TUNNEL		0x01	/* neighbors reached via tunnel */
69#define DVMRP_NF_SRCRT		0x02	/* tunnel uses IP source routing */
70#define DVMRP_NF_DOWN		0x10	/* kernel state of interface */
71#define DVMRP_NF_DISABLED	0x20	/* administratively disabled */
72#define DVMRP_NF_QUERIER	0x40	/* I am the subnet's querier */
73
74static void print_probe(const u_char *, const u_char *, u_int);
75static void print_report(const u_char *, const u_char *, u_int);
76static void print_neighbors(const u_char *, const u_char *, u_int);
77static void print_neighbors2(const u_char *, const u_char *, u_int);
78static void print_prune(const u_char *, const u_char *, u_int);
79static void print_graft(const u_char *, const u_char *, u_int);
80static void print_graft_ack(const u_char *, const u_char *, u_int);
81
82static u_int32_t target_level;
83
84void
85dvmrp_print(register const u_char *bp, register u_int len)
86{
87	register const u_char *ep;
88	register u_char type;
89
90	ep = (const u_char *)snapend;
91	if (bp >= ep)
92		return;
93
94	type = bp[1];
95	bp += 8;
96	/*
97	 * Skip IGMP header
98	 */
99
100	len -= 8;
101
102	switch (type) {
103
104	case DVMRP_PROBE:
105		printf(" Probe");
106		if (vflag)
107			print_probe(bp, ep, len);
108		break;
109
110	case DVMRP_REPORT:
111		printf(" Report");
112		if (vflag)
113			print_report(bp, ep, len);
114		break;
115
116	case DVMRP_ASK_NEIGHBORS:
117		printf(" Ask-neighbors(old)");
118		break;
119
120	case DVMRP_NEIGHBORS:
121		printf(" Neighbors(old)");
122		print_neighbors(bp, ep, len);
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		target_level = (bp[0] << 24) | (bp[1] << 16) |
137		    (bp[2] << 8) | bp[3];
138		bp += 4;
139		print_neighbors2(bp, ep, len);
140		break;
141
142	case DVMRP_PRUNE:
143		printf(" Prune");
144		print_prune(bp, ep, len);
145		break;
146
147	case DVMRP_GRAFT:
148		printf(" Graft");
149		print_graft(bp, ep, len);
150		break;
151
152	case DVMRP_GRAFT_ACK:
153		printf(" Graft-ACK");
154		print_graft_ack(bp, ep, len);
155		break;
156
157	default:
158		printf(" [type %d]", type);
159		break;
160	}
161}
162
163static void
164print_report(register const u_char *bp, register const u_char *ep,
165    register u_int len)
166{
167	register u_int32_t mask, origin;
168	register int metric, i, width, done;
169
170	while (len > 0) {
171		if (len < 3) {
172			printf(" [|]");
173			return;
174		}
175		mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2];
176		width = 1;
177		if (bp[0])
178			width = 2;
179		if (bp[1])
180			width = 3;
181		if (bp[2])
182			width = 4;
183
184		printf("\n\tMask %s", intoa(htonl(mask)));
185		bp += 3;
186		len -= 3;
187		do {
188			if (bp + width + 1 > ep) {
189				printf(" [|]");
190				return;
191			}
192			if (len < width + 1) {
193				printf("\n\t  [Truncated Report]");
194				return;
195			}
196			origin = 0;
197			for (i = 0; i < width; ++i)
198				origin = origin << 8 | *bp++;
199			for ( ; i < 4; ++i)
200				origin <<= 8;
201
202			metric = *bp++;
203			done = metric & 0x80;
204			metric &= 0x7f;
205			printf("\n\t  %s metric %d", intoa(htonl(origin)),
206				metric);
207			len -= width + 1;
208		} while (!done);
209	}
210}
211
212#define GET_ADDR(to) (memcpy((char *)to, (char *)bp, 4), bp += 4)
213
214static void
215print_probe(register const u_char *bp, register const u_char *ep,
216    register u_int len)
217{
218	register u_int32_t genid;
219	u_char neighbor[4];
220
221	if ((len < 4) || ((bp + 4) > ep)) {
222		/* { (ctags) */
223		printf(" [|}");
224		return;
225	}
226	genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
227	bp += 4;
228	len -= 4;
229	printf("\n\tgenid %u", genid);
230
231	while ((len > 0) && (bp < ep)) {
232		if ((len < 4) || ((bp + 4) > ep)) {
233			printf(" [|]");
234			return;
235		}
236		GET_ADDR(neighbor);
237		len -= 4;
238		printf("\n\tneighbor %s", ipaddr_string(neighbor));
239	}
240}
241
242static void
243print_neighbors(register const u_char *bp, register const u_char *ep,
244    register u_int len)
245{
246	u_char laddr[4], neighbor[4];
247	register u_char metric;
248	register u_char thresh;
249	register int ncount;
250
251	while (len > 0 && bp < ep) {
252		if (len < 7 || (bp + 7) >= ep) {
253			printf(" [|]");
254			return;
255		}
256		GET_ADDR(laddr);
257		metric = *bp++;
258		thresh = *bp++;
259		ncount = *bp++;
260		len -= 7;
261		while (--ncount >= 0 && (len >= 4) && (bp + 4) < ep) {
262			GET_ADDR(neighbor);
263			printf(" [%s ->", ipaddr_string(laddr));
264			printf(" %s, (%d/%d)]",
265				   ipaddr_string(neighbor), metric, thresh);
266			len -= 4;
267		}
268	}
269}
270
271static void
272print_neighbors2(register const u_char *bp, register const u_char *ep,
273    register u_int len)
274{
275	u_char laddr[4], neighbor[4];
276	register u_char metric, thresh, flags;
277	register int ncount;
278
279	printf(" (v %d.%d):",
280	       (int)target_level & 0xff,
281	       (int)(target_level >> 8) & 0xff);
282
283	while (len > 0 && bp < ep) {
284		if (len < 8 || (bp + 8) >= ep) {
285			printf(" [|]");
286			return;
287		}
288		GET_ADDR(laddr);
289		metric = *bp++;
290		thresh = *bp++;
291		flags = *bp++;
292		ncount = *bp++;
293		len -= 8;
294		while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) {
295			GET_ADDR(neighbor);
296			printf(" [%s -> ", ipaddr_string(laddr));
297			printf("%s (%d/%d", ipaddr_string(neighbor),
298				     metric, thresh);
299			if (flags & DVMRP_NF_TUNNEL)
300				printf("/tunnel");
301			if (flags & DVMRP_NF_SRCRT)
302				printf("/srcrt");
303			if (flags & DVMRP_NF_QUERIER)
304				printf("/querier");
305			if (flags & DVMRP_NF_DISABLED)
306				printf("/disabled");
307			if (flags & DVMRP_NF_DOWN)
308				printf("/down");
309			printf(")]");
310			len -= 4;
311		}
312		if (ncount != -1) {
313			printf(" [|]");
314			return;
315		}
316	}
317}
318
319static void
320print_prune(register const u_char *bp, register const u_char *ep,
321    register u_int len)
322{
323	union a {
324		u_char b[4];
325		u_int32_t i;
326	} prune_timer;
327
328	if (len < 12 || (bp + 12) > ep) {
329		printf(" [|]");
330		return;
331	}
332	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
333	bp += 8;
334	GET_ADDR(prune_timer.b);
335	printf(" timer %d", (int)ntohl(prune_timer.i));
336}
337
338static void
339print_graft(register const u_char *bp, register const u_char *ep,
340    register u_int len)
341{
342
343	if (len < 8 || (bp + 8) > ep) {
344		printf(" [|]");
345		return;
346	}
347	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
348}
349
350static void
351print_graft_ack(register const u_char *bp, register const u_char *ep,
352    register u_int len)
353{
354
355	if (len < 8 || (bp + 8) > ep) {
356		printf(" [|]");
357		return;
358	}
359	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
360}
361