nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* |
2 | * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org> |
||
3 | * All rights reserved. |
||
4 | * |
||
5 | * Redistribution and use in source and binary forms, with or without |
||
6 | * modification, are permitted provided that the following conditions |
||
7 | * are met: |
||
8 | * 1. Redistributions of source code must retain the above copyright |
||
9 | * notice, this list of conditions and the following disclaimer. |
||
10 | * 2. Redistributions in binary form must reproduce the above copyright |
||
11 | * notice, this list of conditions and the following disclaimer in the |
||
12 | * documentation and/or other materials provided with the distribution. |
||
13 | * 3. All advertising materials mentioning features or use of this software |
||
14 | * must display the following acknowledgement: |
||
15 | * This product includes software developed by Bruce M. Simpson. |
||
16 | * 4. Neither the name of Bruce M. Simpson nor the names of co- |
||
17 | * contributors may be used to endorse or promote products derived |
||
18 | * from this software without specific prior written permission. |
||
19 | * |
||
20 | * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS |
||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS |
||
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
30 | * POSSIBILITY OF SUCH DAMAGE. |
||
31 | */ |
||
32 | |||
33 | #define NETDISSECT_REWORKED |
||
34 | #ifdef HAVE_CONFIG_H |
||
35 | #include "config.h" |
||
36 | #endif |
||
37 | |||
38 | #include <tcpdump-stdinc.h> |
||
39 | |||
40 | #include "interface.h" |
||
41 | #include "addrtoname.h" |
||
42 | #include "extract.h" /* must come after interface.h */ |
||
43 | |||
44 | |||
45 | struct aodv_rreq { |
||
46 | uint8_t rreq_type; /* AODV message type (1) */ |
||
47 | uint8_t rreq_flags; /* various flags */ |
||
48 | uint8_t rreq_zero0; /* reserved, set to zero */ |
||
49 | uint8_t rreq_hops; /* number of hops from originator */ |
||
50 | uint32_t rreq_id; /* request ID */ |
||
51 | uint32_t rreq_da; /* destination IPv4 address */ |
||
52 | uint32_t rreq_ds; /* destination sequence number */ |
||
53 | uint32_t rreq_oa; /* originator IPv4 address */ |
||
54 | uint32_t rreq_os; /* originator sequence number */ |
||
55 | }; |
||
56 | #ifdef INET6 |
||
57 | struct aodv_rreq6 { |
||
58 | uint8_t rreq_type; /* AODV message type (1) */ |
||
59 | uint8_t rreq_flags; /* various flags */ |
||
60 | uint8_t rreq_zero0; /* reserved, set to zero */ |
||
61 | uint8_t rreq_hops; /* number of hops from originator */ |
||
62 | uint32_t rreq_id; /* request ID */ |
||
63 | struct in6_addr rreq_da; /* destination IPv6 address */ |
||
64 | uint32_t rreq_ds; /* destination sequence number */ |
||
65 | struct in6_addr rreq_oa; /* originator IPv6 address */ |
||
66 | uint32_t rreq_os; /* originator sequence number */ |
||
67 | }; |
||
68 | struct aodv_rreq6_draft_01 { |
||
69 | uint8_t rreq_type; /* AODV message type (16) */ |
||
70 | uint8_t rreq_flags; /* various flags */ |
||
71 | uint8_t rreq_zero0; /* reserved, set to zero */ |
||
72 | uint8_t rreq_hops; /* number of hops from originator */ |
||
73 | uint32_t rreq_id; /* request ID */ |
||
74 | uint32_t rreq_ds; /* destination sequence number */ |
||
75 | uint32_t rreq_os; /* originator sequence number */ |
||
76 | struct in6_addr rreq_da; /* destination IPv6 address */ |
||
77 | struct in6_addr rreq_oa; /* originator IPv6 address */ |
||
78 | }; |
||
79 | #endif |
||
80 | |||
81 | #define RREQ_JOIN 0x80 /* join (reserved for multicast */ |
||
82 | #define RREQ_REPAIR 0x40 /* repair (reserved for multicast */ |
||
83 | #define RREQ_GRAT 0x20 /* gratuitous RREP */ |
||
84 | #define RREQ_DEST 0x10 /* destination only */ |
||
85 | #define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */ |
||
86 | #define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */ |
||
87 | |||
88 | struct aodv_rrep { |
||
89 | uint8_t rrep_type; /* AODV message type (2) */ |
||
90 | uint8_t rrep_flags; /* various flags */ |
||
91 | uint8_t rrep_ps; /* prefix size */ |
||
92 | uint8_t rrep_hops; /* number of hops from o to d */ |
||
93 | uint32_t rrep_da; /* destination IPv4 address */ |
||
94 | uint32_t rrep_ds; /* destination sequence number */ |
||
95 | uint32_t rrep_oa; /* originator IPv4 address */ |
||
96 | uint32_t rrep_life; /* lifetime of this route */ |
||
97 | }; |
||
98 | #ifdef INET6 |
||
99 | struct aodv_rrep6 { |
||
100 | uint8_t rrep_type; /* AODV message type (2) */ |
||
101 | uint8_t rrep_flags; /* various flags */ |
||
102 | uint8_t rrep_ps; /* prefix size */ |
||
103 | uint8_t rrep_hops; /* number of hops from o to d */ |
||
104 | struct in6_addr rrep_da; /* destination IPv6 address */ |
||
105 | uint32_t rrep_ds; /* destination sequence number */ |
||
106 | struct in6_addr rrep_oa; /* originator IPv6 address */ |
||
107 | uint32_t rrep_life; /* lifetime of this route */ |
||
108 | }; |
||
109 | struct aodv_rrep6_draft_01 { |
||
110 | uint8_t rrep_type; /* AODV message type (17) */ |
||
111 | uint8_t rrep_flags; /* various flags */ |
||
112 | uint8_t rrep_ps; /* prefix size */ |
||
113 | uint8_t rrep_hops; /* number of hops from o to d */ |
||
114 | uint32_t rrep_ds; /* destination sequence number */ |
||
115 | struct in6_addr rrep_da; /* destination IPv6 address */ |
||
116 | struct in6_addr rrep_oa; /* originator IPv6 address */ |
||
117 | uint32_t rrep_life; /* lifetime of this route */ |
||
118 | }; |
||
119 | #endif |
||
120 | |||
121 | #define RREP_REPAIR 0x80 /* repair (reserved for multicast */ |
||
122 | #define RREP_ACK 0x40 /* acknowledgement required */ |
||
123 | #define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */ |
||
124 | #define RREP_PREFIX_MASK 0x1F /* mask for prefix size */ |
||
125 | |||
126 | struct rerr_unreach { |
||
127 | uint32_t u_da; /* IPv4 address */ |
||
128 | uint32_t u_ds; /* sequence number */ |
||
129 | }; |
||
130 | #ifdef INET6 |
||
131 | struct rerr_unreach6 { |
||
132 | struct in6_addr u_da; /* IPv6 address */ |
||
133 | uint32_t u_ds; /* sequence number */ |
||
134 | }; |
||
135 | struct rerr_unreach6_draft_01 { |
||
136 | struct in6_addr u_da; /* IPv6 address */ |
||
137 | uint32_t u_ds; /* sequence number */ |
||
138 | }; |
||
139 | #endif |
||
140 | |||
141 | struct aodv_rerr { |
||
142 | uint8_t rerr_type; /* AODV message type (3 or 18) */ |
||
143 | uint8_t rerr_flags; /* various flags */ |
||
144 | uint8_t rerr_zero0; /* reserved, set to zero */ |
||
145 | uint8_t rerr_dc; /* destination count */ |
||
146 | }; |
||
147 | |||
148 | #define RERR_NODELETE 0x80 /* don't delete the link */ |
||
149 | #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */ |
||
150 | |||
151 | struct aodv_rrep_ack { |
||
152 | uint8_t ra_type; |
||
153 | uint8_t ra_zero0; |
||
154 | }; |
||
155 | |||
156 | #define AODV_RREQ 1 /* route request */ |
||
157 | #define AODV_RREP 2 /* route response */ |
||
158 | #define AODV_RERR 3 /* error report */ |
||
159 | #define AODV_RREP_ACK 4 /* route response acknowledgement */ |
||
160 | |||
161 | #define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */ |
||
162 | #define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */ |
||
163 | #define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */ |
||
164 | #define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */ |
||
165 | |||
166 | struct aodv_ext { |
||
167 | uint8_t type; /* extension type */ |
||
168 | uint8_t length; /* extension length */ |
||
169 | }; |
||
170 | |||
171 | struct aodv_hello { |
||
172 | struct aodv_ext eh; /* extension header */ |
||
173 | uint8_t interval[4]; /* expect my next hello in |
||
174 | * (n) ms |
||
175 | * NOTE: this is not aligned */ |
||
176 | }; |
||
177 | |||
178 | #define AODV_EXT_HELLO 1 |
||
179 | |||
180 | static void |
||
181 | aodv_extension(netdissect_options *ndo, |
||
182 | const struct aodv_ext *ep, u_int length) |
||
183 | { |
||
184 | const struct aodv_hello *ah; |
||
185 | |||
186 | switch (ep->type) { |
||
187 | case AODV_EXT_HELLO: |
||
188 | ah = (const struct aodv_hello *)(const void *)ep; |
||
189 | ND_TCHECK(*ah); |
||
190 | if (length < sizeof(struct aodv_hello)) |
||
191 | goto trunc; |
||
192 | ND_PRINT((ndo, "\n\text HELLO %ld ms", |
||
193 | (unsigned long)EXTRACT_32BITS(&ah->interval))); |
||
194 | break; |
||
195 | |||
196 | default: |
||
197 | ND_PRINT((ndo, "\n\text %u %u", ep->type, ep->length)); |
||
198 | break; |
||
199 | } |
||
200 | return; |
||
201 | |||
202 | trunc: |
||
203 | ND_PRINT((ndo, " [|hello]")); |
||
204 | } |
||
205 | |||
206 | static void |
||
207 | aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length) |
||
208 | { |
||
209 | u_int i; |
||
210 | const struct aodv_rreq *ap = (const struct aodv_rreq *)dat; |
||
211 | |||
212 | ND_TCHECK(*ap); |
||
213 | if (length < sizeof(*ap)) |
||
214 | goto trunc; |
||
215 | ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n" |
||
216 | "\tdst %s seq %lu src %s seq %lu", length, |
||
217 | ap->rreq_type & RREQ_JOIN ? "[J]" : "", |
||
218 | ap->rreq_type & RREQ_REPAIR ? "[R]" : "", |
||
219 | ap->rreq_type & RREQ_GRAT ? "[G]" : "", |
||
220 | ap->rreq_type & RREQ_DEST ? "[D]" : "", |
||
221 | ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", |
||
222 | ap->rreq_hops, |
||
223 | (unsigned long)EXTRACT_32BITS(&ap->rreq_id), |
||
224 | ipaddr_string(ndo, &ap->rreq_da), |
||
225 | (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), |
||
226 | ipaddr_string(ndo, &ap->rreq_oa), |
||
227 | (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); |
||
228 | i = length - sizeof(*ap); |
||
229 | if (i >= sizeof(struct aodv_ext)) |
||
230 | aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); |
||
231 | return; |
||
232 | |||
233 | trunc: |
||
234 | ND_PRINT((ndo, " [|rreq")); |
||
235 | } |
||
236 | |||
237 | static void |
||
238 | aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length) |
||
239 | { |
||
240 | u_int i; |
||
241 | const struct aodv_rrep *ap = (const struct aodv_rrep *)dat; |
||
242 | |||
243 | ND_TCHECK(*ap); |
||
244 | if (length < sizeof(*ap)) |
||
245 | goto trunc; |
||
246 | ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" |
||
247 | "\tdst %s dseq %lu src %s %lu ms", length, |
||
248 | ap->rrep_type & RREP_REPAIR ? "[R]" : "", |
||
249 | ap->rrep_type & RREP_ACK ? "[A] " : " ", |
||
250 | ap->rrep_ps & RREP_PREFIX_MASK, |
||
251 | ap->rrep_hops, |
||
252 | ipaddr_string(ndo, &ap->rrep_da), |
||
253 | (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), |
||
254 | ipaddr_string(ndo, &ap->rrep_oa), |
||
255 | (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); |
||
256 | i = length - sizeof(*ap); |
||
257 | if (i >= sizeof(struct aodv_ext)) |
||
258 | aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); |
||
259 | return; |
||
260 | |||
261 | trunc: |
||
262 | ND_PRINT((ndo, " [|rreq")); |
||
263 | } |
||
264 | |||
265 | static void |
||
266 | aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length) |
||
267 | { |
||
268 | u_int i, dc; |
||
269 | const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; |
||
270 | const struct rerr_unreach *dp; |
||
271 | |||
272 | ND_TCHECK(*ap); |
||
273 | if (length < sizeof(*ap)) |
||
274 | goto trunc; |
||
275 | ND_PRINT((ndo, " rerr %s [items %u] [%u]:", |
||
276 | ap->rerr_flags & RERR_NODELETE ? "[D]" : "", |
||
277 | ap->rerr_dc, length)); |
||
278 | dp = (struct rerr_unreach *)(dat + sizeof(*ap)); |
||
279 | i = length - sizeof(*ap); |
||
280 | for (dc = ap->rerr_dc; dc != 0; dc--) { |
||
281 | ND_TCHECK(*dp); |
||
282 | if (i < sizeof(*dp)) |
||
283 | goto trunc; |
||
284 | ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(ndo, &dp->u_da), |
||
285 | (unsigned long)EXTRACT_32BITS(&dp->u_ds))); |
||
286 | dp++; |
||
287 | i -= sizeof(*dp); |
||
288 | } |
||
289 | return; |
||
290 | |||
291 | trunc: |
||
292 | ND_PRINT((ndo, "[|rerr]")); |
||
293 | } |
||
294 | |||
295 | static void |
||
296 | #ifdef INET6 |
||
297 | aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length) |
||
298 | #else |
||
299 | aodv_v6_rreq(netdissect_options *ndo, const u_char *dat _U_, u_int length) |
||
300 | #endif |
||
301 | { |
||
302 | #ifdef INET6 |
||
303 | u_int i; |
||
304 | const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat; |
||
305 | |||
306 | ND_TCHECK(*ap); |
||
307 | if (length < sizeof(*ap)) |
||
308 | goto trunc; |
||
309 | ND_PRINT((ndo, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n" |
||
310 | "\tdst %s seq %lu src %s seq %lu", length, |
||
311 | ap->rreq_type & RREQ_JOIN ? "[J]" : "", |
||
312 | ap->rreq_type & RREQ_REPAIR ? "[R]" : "", |
||
313 | ap->rreq_type & RREQ_GRAT ? "[G]" : "", |
||
314 | ap->rreq_type & RREQ_DEST ? "[D]" : "", |
||
315 | ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", |
||
316 | ap->rreq_hops, |
||
317 | (unsigned long)EXTRACT_32BITS(&ap->rreq_id), |
||
318 | ip6addr_string(ndo, &ap->rreq_da), |
||
319 | (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), |
||
320 | ip6addr_string(ndo, &ap->rreq_oa), |
||
321 | (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); |
||
322 | i = length - sizeof(*ap); |
||
323 | if (i >= sizeof(struct aodv_ext)) |
||
324 | aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); |
||
325 | return; |
||
326 | |||
327 | trunc: |
||
328 | ND_PRINT((ndo, " [|rreq")); |
||
329 | #else |
||
330 | ND_PRINT((ndo, " v6 rreq %u", length)); |
||
331 | #endif |
||
332 | } |
||
333 | |||
334 | static void |
||
335 | #ifdef INET6 |
||
336 | aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length) |
||
337 | #else |
||
338 | aodv_v6_rrep(netdissect_options *ndo, const u_char *dat _U_, u_int length) |
||
339 | #endif |
||
340 | { |
||
341 | #ifdef INET6 |
||
342 | u_int i; |
||
343 | const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat; |
||
344 | |||
345 | ND_TCHECK(*ap); |
||
346 | if (length < sizeof(*ap)) |
||
347 | goto trunc; |
||
348 | ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" |
||
349 | "\tdst %s dseq %lu src %s %lu ms", length, |
||
350 | ap->rrep_type & RREP_REPAIR ? "[R]" : "", |
||
351 | ap->rrep_type & RREP_ACK ? "[A] " : " ", |
||
352 | ap->rrep_ps & RREP_PREFIX_MASK, |
||
353 | ap->rrep_hops, |
||
354 | ip6addr_string(ndo, &ap->rrep_da), |
||
355 | (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), |
||
356 | ip6addr_string(ndo, &ap->rrep_oa), |
||
357 | (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); |
||
358 | i = length - sizeof(*ap); |
||
359 | if (i >= sizeof(struct aodv_ext)) |
||
360 | aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); |
||
361 | return; |
||
362 | |||
363 | trunc: |
||
364 | ND_PRINT((ndo, " [|rreq")); |
||
365 | #else |
||
366 | ND_PRINT((ndo, " rrep %u", length)); |
||
367 | #endif |
||
368 | } |
||
369 | |||
370 | static void |
||
371 | #ifdef INET6 |
||
372 | aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length) |
||
373 | #else |
||
374 | aodv_v6_rerr(netdissect_options *ndo, const u_char *dat _U_, u_int length) |
||
375 | #endif |
||
376 | { |
||
377 | #ifdef INET6 |
||
378 | u_int i, dc; |
||
379 | const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; |
||
380 | const struct rerr_unreach6 *dp6; |
||
381 | |||
382 | ND_TCHECK(*ap); |
||
383 | if (length < sizeof(*ap)) |
||
384 | goto trunc; |
||
385 | ND_PRINT((ndo, " rerr %s [items %u] [%u]:", |
||
386 | ap->rerr_flags & RERR_NODELETE ? "[D]" : "", |
||
387 | ap->rerr_dc, length)); |
||
388 | dp6 = (struct rerr_unreach6 *)(void *)(ap + 1); |
||
389 | i = length - sizeof(*ap); |
||
390 | for (dc = ap->rerr_dc; dc != 0; dc--) { |
||
391 | ND_TCHECK(*dp6); |
||
392 | if (i < sizeof(*dp6)) |
||
393 | goto trunc; |
||
394 | ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), |
||
395 | (unsigned long)EXTRACT_32BITS(&dp6->u_ds))); |
||
396 | dp6++; |
||
397 | i -= sizeof(*dp6); |
||
398 | } |
||
399 | return; |
||
400 | |||
401 | trunc: |
||
402 | ND_PRINT((ndo, "[|rerr]")); |
||
403 | #else |
||
404 | ND_PRINT((ndo, " rerr %u", length)); |
||
405 | #endif |
||
406 | } |
||
407 | |||
408 | static void |
||
409 | #ifdef INET6 |
||
410 | aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length) |
||
411 | #else |
||
412 | aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat _U_, u_int length) |
||
413 | #endif |
||
414 | { |
||
415 | #ifdef INET6 |
||
416 | u_int i; |
||
417 | const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat; |
||
418 | |||
419 | ND_TCHECK(*ap); |
||
420 | if (length < sizeof(*ap)) |
||
421 | goto trunc; |
||
422 | ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n" |
||
423 | "\tdst %s seq %lu src %s seq %lu", length, |
||
424 | ap->rreq_type & RREQ_JOIN ? "[J]" : "", |
||
425 | ap->rreq_type & RREQ_REPAIR ? "[R]" : "", |
||
426 | ap->rreq_type & RREQ_GRAT ? "[G]" : "", |
||
427 | ap->rreq_type & RREQ_DEST ? "[D]" : "", |
||
428 | ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", |
||
429 | ap->rreq_hops, |
||
430 | (unsigned long)EXTRACT_32BITS(&ap->rreq_id), |
||
431 | ip6addr_string(ndo, &ap->rreq_da), |
||
432 | (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), |
||
433 | ip6addr_string(ndo, &ap->rreq_oa), |
||
434 | (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); |
||
435 | i = length - sizeof(*ap); |
||
436 | if (i >= sizeof(struct aodv_ext)) |
||
437 | aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); |
||
438 | return; |
||
439 | |||
440 | trunc: |
||
441 | ND_PRINT((ndo, " [|rreq")); |
||
442 | #else |
||
443 | ND_PRINT((ndo, " rreq %u", length)); |
||
444 | #endif |
||
445 | } |
||
446 | |||
447 | static void |
||
448 | #ifdef INET6 |
||
449 | aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length) |
||
450 | #else |
||
451 | aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat _U_, u_int length) |
||
452 | #endif |
||
453 | { |
||
454 | #ifdef INET6 |
||
455 | u_int i; |
||
456 | const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat; |
||
457 | |||
458 | ND_TCHECK(*ap); |
||
459 | if (length < sizeof(*ap)) |
||
460 | goto trunc; |
||
461 | ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" |
||
462 | "\tdst %s dseq %lu src %s %lu ms", length, |
||
463 | ap->rrep_type & RREP_REPAIR ? "[R]" : "", |
||
464 | ap->rrep_type & RREP_ACK ? "[A] " : " ", |
||
465 | ap->rrep_ps & RREP_PREFIX_MASK, |
||
466 | ap->rrep_hops, |
||
467 | ip6addr_string(ndo, &ap->rrep_da), |
||
468 | (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), |
||
469 | ip6addr_string(ndo, &ap->rrep_oa), |
||
470 | (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); |
||
471 | i = length - sizeof(*ap); |
||
472 | if (i >= sizeof(struct aodv_ext)) |
||
473 | aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); |
||
474 | return; |
||
475 | |||
476 | trunc: |
||
477 | ND_PRINT((ndo, " [|rreq")); |
||
478 | #else |
||
479 | ND_PRINT((ndo, " rrep %u", length)); |
||
480 | #endif |
||
481 | } |
||
482 | |||
483 | static void |
||
484 | #ifdef INET6 |
||
485 | aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length) |
||
486 | #else |
||
487 | aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat _U_, u_int length) |
||
488 | #endif |
||
489 | { |
||
490 | #ifdef INET6 |
||
491 | u_int i, dc; |
||
492 | const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; |
||
493 | const struct rerr_unreach6_draft_01 *dp6; |
||
494 | |||
495 | ND_TCHECK(*ap); |
||
496 | if (length < sizeof(*ap)) |
||
497 | goto trunc; |
||
498 | ND_PRINT((ndo, " rerr %s [items %u] [%u]:", |
||
499 | ap->rerr_flags & RERR_NODELETE ? "[D]" : "", |
||
500 | ap->rerr_dc, length)); |
||
501 | dp6 = (struct rerr_unreach6_draft_01 *)(void *)(ap + 1); |
||
502 | i = length - sizeof(*ap); |
||
503 | for (dc = ap->rerr_dc; dc != 0; dc--) { |
||
504 | ND_TCHECK(*dp6); |
||
505 | if (i < sizeof(*dp6)) |
||
506 | goto trunc; |
||
507 | ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), |
||
508 | (unsigned long)EXTRACT_32BITS(&dp6->u_ds))); |
||
509 | dp6++; |
||
510 | i -= sizeof(*dp6); |
||
511 | } |
||
512 | return; |
||
513 | |||
514 | trunc: |
||
515 | ND_PRINT((ndo, "[|rerr]")); |
||
516 | #else |
||
517 | ND_PRINT((ndo, " rerr %u", length)); |
||
518 | #endif |
||
519 | } |
||
520 | |||
521 | void |
||
522 | aodv_print(netdissect_options *ndo, |
||
523 | const u_char *dat, u_int length, int is_ip6) |
||
524 | { |
||
525 | uint8_t msg_type; |
||
526 | |||
527 | /* |
||
528 | * The message type is the first byte; make sure we have it |
||
529 | * and then fetch it. |
||
530 | */ |
||
531 | ND_TCHECK(*dat); |
||
532 | msg_type = *dat; |
||
533 | ND_PRINT((ndo, " aodv")); |
||
534 | |||
535 | switch (msg_type) { |
||
536 | |||
537 | case AODV_RREQ: |
||
538 | if (is_ip6) |
||
539 | aodv_v6_rreq(ndo, dat, length); |
||
540 | else |
||
541 | aodv_rreq(ndo, dat, length); |
||
542 | break; |
||
543 | |||
544 | case AODV_RREP: |
||
545 | if (is_ip6) |
||
546 | aodv_v6_rrep(ndo, dat, length); |
||
547 | else |
||
548 | aodv_rrep(ndo, dat, length); |
||
549 | break; |
||
550 | |||
551 | case AODV_RERR: |
||
552 | if (is_ip6) |
||
553 | aodv_v6_rerr(ndo, dat, length); |
||
554 | else |
||
555 | aodv_rerr(ndo, dat, length); |
||
556 | break; |
||
557 | |||
558 | case AODV_RREP_ACK: |
||
559 | ND_PRINT((ndo, " rrep-ack %u", length)); |
||
560 | break; |
||
561 | |||
562 | case AODV_V6_DRAFT_01_RREQ: |
||
563 | aodv_v6_draft_01_rreq(ndo, dat, length); |
||
564 | break; |
||
565 | |||
566 | case AODV_V6_DRAFT_01_RREP: |
||
567 | aodv_v6_draft_01_rrep(ndo, dat, length); |
||
568 | break; |
||
569 | |||
570 | case AODV_V6_DRAFT_01_RERR: |
||
571 | aodv_v6_draft_01_rerr(ndo, dat, length); |
||
572 | break; |
||
573 | |||
574 | case AODV_V6_DRAFT_01_RREP_ACK: |
||
575 | ND_PRINT((ndo, " rrep-ack %u", length)); |
||
576 | break; |
||
577 | |||
578 | default: |
||
579 | ND_PRINT((ndo, " type %u %u", msg_type, length)); |
||
580 | } |
||
581 | return; |
||
582 | |||
583 | trunc: |
||
584 | ND_PRINT((ndo, " [|aodv]")); |
||
585 | } |