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