nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | } |