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