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