]> The Tcpdump Group git mirrors - tcpdump/blob - print-aodv.c
NDOize safeputs() and safeputchar()
[tcpdump] / print-aodv.c
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 /* for offsetof */
41 #include <stddef.h>
42
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "extract.h" /* must come after interface.h */
46
47
48 struct aodv_rreq {
49 u_int8_t rreq_type; /* AODV message type (1) */
50 u_int8_t rreq_flags; /* various flags */
51 u_int8_t rreq_zero0; /* reserved, set to zero */
52 u_int8_t rreq_hops; /* number of hops from originator */
53 u_int32_t rreq_id; /* request ID */
54 u_int32_t rreq_da; /* destination IPv4 address */
55 u_int32_t rreq_ds; /* destination sequence number */
56 u_int32_t rreq_oa; /* originator IPv4 address */
57 u_int32_t rreq_os; /* originator sequence number */
58 };
59 #ifdef INET6
60 struct aodv_rreq6 {
61 u_int8_t rreq_type; /* AODV message type (1) */
62 u_int8_t rreq_flags; /* various flags */
63 u_int8_t rreq_zero0; /* reserved, set to zero */
64 u_int8_t rreq_hops; /* number of hops from originator */
65 u_int32_t rreq_id; /* request ID */
66 struct in6_addr rreq_da; /* destination IPv6 address */
67 u_int32_t rreq_ds; /* destination sequence number */
68 struct in6_addr rreq_oa; /* originator IPv6 address */
69 u_int32_t rreq_os; /* originator sequence number */
70 };
71 struct aodv_rreq6_draft_01 {
72 u_int8_t rreq_type; /* AODV message type (16) */
73 u_int8_t rreq_flags; /* various flags */
74 u_int8_t rreq_zero0; /* reserved, set to zero */
75 u_int8_t rreq_hops; /* number of hops from originator */
76 u_int32_t rreq_id; /* request ID */
77 u_int32_t rreq_ds; /* destination sequence number */
78 u_int32_t rreq_os; /* originator sequence number */
79 struct in6_addr rreq_da; /* destination IPv6 address */
80 struct in6_addr rreq_oa; /* originator IPv6 address */
81 };
82 #endif
83
84 #define RREQ_JOIN 0x80 /* join (reserved for multicast */
85 #define RREQ_REPAIR 0x40 /* repair (reserved for multicast */
86 #define RREQ_GRAT 0x20 /* gratuitous RREP */
87 #define RREQ_DEST 0x10 /* destination only */
88 #define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */
89 #define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */
90
91 struct aodv_rrep {
92 u_int8_t rrep_type; /* AODV message type (2) */
93 u_int8_t rrep_flags; /* various flags */
94 u_int8_t rrep_ps; /* prefix size */
95 u_int8_t rrep_hops; /* number of hops from o to d */
96 u_int32_t rrep_da; /* destination IPv4 address */
97 u_int32_t rrep_ds; /* destination sequence number */
98 u_int32_t rrep_oa; /* originator IPv4 address */
99 u_int32_t rrep_life; /* lifetime of this route */
100 };
101 #ifdef INET6
102 struct aodv_rrep6 {
103 u_int8_t rrep_type; /* AODV message type (2) */
104 u_int8_t rrep_flags; /* various flags */
105 u_int8_t rrep_ps; /* prefix size */
106 u_int8_t rrep_hops; /* number of hops from o to d */
107 struct in6_addr rrep_da; /* destination IPv6 address */
108 u_int32_t rrep_ds; /* destination sequence number */
109 struct in6_addr rrep_oa; /* originator IPv6 address */
110 u_int32_t rrep_life; /* lifetime of this route */
111 };
112 struct aodv_rrep6_draft_01 {
113 u_int8_t rrep_type; /* AODV message type (17) */
114 u_int8_t rrep_flags; /* various flags */
115 u_int8_t rrep_ps; /* prefix size */
116 u_int8_t rrep_hops; /* number of hops from o to d */
117 u_int32_t rrep_ds; /* destination sequence number */
118 struct in6_addr rrep_da; /* destination IPv6 address */
119 struct in6_addr rrep_oa; /* originator IPv6 address */
120 u_int32_t rrep_life; /* lifetime of this route */
121 };
122 #endif
123
124 #define RREP_REPAIR 0x80 /* repair (reserved for multicast */
125 #define RREP_ACK 0x40 /* acknowledgement required */
126 #define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */
127 #define RREP_PREFIX_MASK 0x1F /* mask for prefix size */
128
129 struct rerr_unreach {
130 u_int32_t u_da; /* IPv4 address */
131 u_int32_t u_ds; /* sequence number */
132 };
133 #ifdef INET6
134 struct rerr_unreach6 {
135 struct in6_addr u_da; /* IPv6 address */
136 u_int32_t u_ds; /* sequence number */
137 };
138 struct rerr_unreach6_draft_01 {
139 struct in6_addr u_da; /* IPv6 address */
140 u_int32_t u_ds; /* sequence number */
141 };
142 #endif
143
144 struct aodv_rerr {
145 u_int8_t rerr_type; /* AODV message type (3 or 18) */
146 u_int8_t rerr_flags; /* various flags */
147 u_int8_t rerr_zero0; /* reserved, set to zero */
148 u_int8_t rerr_dc; /* destination count */
149 union {
150 struct rerr_unreach dest[1];
151 #ifdef INET6
152 struct rerr_unreach6 dest6[1];
153 struct rerr_unreach6_draft_01 dest6_draft_01[1];
154 #endif
155 } r;
156 };
157
158 #define RERR_NODELETE 0x80 /* don't delete the link */
159 #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */
160
161 struct aodv_rrep_ack {
162 u_int8_t ra_type;
163 u_int8_t ra_zero0;
164 };
165
166 union aodv {
167 struct aodv_rreq rreq;
168 struct aodv_rrep rrep;
169 struct aodv_rerr rerr;
170 struct aodv_rrep_ack rrep_ack;
171 #ifdef INET6
172 struct aodv_rreq6 rreq6;
173 struct aodv_rreq6_draft_01 rreq6_draft_01;
174 struct aodv_rrep6 rrep6;
175 struct aodv_rrep6_draft_01 rrep6_draft_01;
176 #endif
177 };
178
179 #define AODV_RREQ 1 /* route request */
180 #define AODV_RREP 2 /* route response */
181 #define AODV_RERR 3 /* error report */
182 #define AODV_RREP_ACK 4 /* route response acknowledgement */
183
184 #define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */
185 #define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */
186 #define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */
187 #define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */
188
189 struct aodv_ext {
190 u_int8_t type; /* extension type */
191 u_int8_t length; /* extension length */
192 };
193
194 struct aodv_hello {
195 struct aodv_ext eh; /* extension header */
196 u_int8_t interval[4]; /* expect my next hello in
197 * (n) ms
198 * NOTE: this is not aligned */
199 };
200
201 #define AODV_EXT_HELLO 1
202
203 static void
204 aodv_extension(netdissect_options *ndo,
205 const struct aodv_ext *ep, u_int length)
206 {
207 u_int i;
208 const struct aodv_hello *ah;
209
210 switch (ep->type) {
211 case AODV_EXT_HELLO:
212 if (ndo->ndo_snapend < (u_char *) ep) {
213 ND_PRINT((ndo, " [|hello]"));
214 return;
215 }
216 i = min(length, (u_int)(ndo->ndo_snapend - (u_char *)ep));
217 if (i < sizeof(struct aodv_hello)) {
218 ND_PRINT((ndo, " [|hello]"));
219 return;
220 }
221 i -= sizeof(struct aodv_hello);
222 ah = (void *)ep;
223 ND_PRINT((ndo, "\n\text HELLO %ld ms",
224 (unsigned long)EXTRACT_32BITS(&ah->interval)));
225 break;
226
227 default:
228 ND_PRINT((ndo, "\n\text %u %u", ep->type, ep->length));
229 break;
230 }
231 }
232
233 static void
234 aodv_rreq(netdissect_options *ndo,
235 const union aodv *ap, const u_char *dat, u_int length)
236 {
237 u_int i;
238
239 if (ndo->ndo_snapend < dat) {
240 ND_PRINT((ndo, " [|aodv]"));
241 return;
242 }
243 i = min(length, (u_int)(ndo->ndo_snapend - dat));
244 if (i < sizeof(ap->rreq)) {
245 ND_PRINT((ndo, " [|rreq]"));
246 return;
247 }
248 i -= sizeof(ap->rreq);
249 ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
250 "\tdst %s seq %lu src %s seq %lu", length,
251 ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "",
252 ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "",
253 ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "",
254 ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "",
255 ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
256 ap->rreq.rreq_hops,
257 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id),
258 ipaddr_string(&ap->rreq.rreq_da),
259 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds),
260 ipaddr_string(&ap->rreq.rreq_oa),
261 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os)));
262 if (i >= sizeof(struct aodv_ext))
263 aodv_extension(ndo, (void *)(&ap->rreq + 1), i);
264 }
265
266 static void
267 aodv_rrep(netdissect_options *ndo,
268 const union aodv *ap, const u_char *dat, u_int length)
269 {
270 u_int i;
271
272 if (ndo->ndo_snapend < dat) {
273 ND_PRINT((ndo, " [|aodv]"));
274 return;
275 }
276 i = min(length, (u_int)(ndo->ndo_snapend - dat));
277 if (i < sizeof(ap->rrep)) {
278 ND_PRINT((ndo, " [|rrep]"));
279 return;
280 }
281 i -= sizeof(ap->rrep);
282 ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
283 "\tdst %s dseq %lu src %s %lu ms", length,
284 ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "",
285 ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ",
286 ap->rrep.rrep_ps & RREP_PREFIX_MASK,
287 ap->rrep.rrep_hops,
288 ipaddr_string(&ap->rrep.rrep_da),
289 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds),
290 ipaddr_string(&ap->rrep.rrep_oa),
291 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life)));
292 if (i >= sizeof(struct aodv_ext))
293 aodv_extension(ndo, (void *)(&ap->rrep + 1), i);
294 }
295
296 static void
297 aodv_rerr(netdissect_options *ndo,
298 const union aodv *ap, const u_char *dat, u_int length)
299 {
300 u_int i;
301 const struct rerr_unreach *dp = NULL;
302 int n, trunc;
303
304 if (ndo->ndo_snapend < dat) {
305 ND_PRINT((ndo, " [|aodv]"));
306 return;
307 }
308 i = min(length, (u_int)(ndo->ndo_snapend - dat));
309 if (i < offsetof(struct aodv_rerr, r)) {
310 ND_PRINT((ndo, " [|rerr]"));
311 return;
312 }
313 i -= offsetof(struct aodv_rerr, r);
314 dp = &ap->rerr.r.dest[0];
315 n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]);
316 ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
317 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
318 ap->rerr.rerr_dc, length));
319 trunc = n - (i/sizeof(ap->rerr.r.dest[0]));
320 for (; i >= sizeof(ap->rerr.r.dest[0]);
321 ++dp, i -= sizeof(ap->rerr.r.dest[0])) {
322 ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(&dp->u_da),
323 (unsigned long)EXTRACT_32BITS(&dp->u_ds)));
324 }
325 if (trunc)
326 ND_PRINT((ndo, "[|rerr]"));
327 }
328
329 static void
330 #ifdef INET6
331 aodv_v6_rreq(netdissect_options *ndo,
332 const union aodv *ap, const u_char *dat, u_int length)
333 #else
334 aodv_v6_rreq(netdissect_options *ndo,
335 const union aodv *ap _U_, const u_char *dat _U_, u_int length)
336 #endif
337 {
338 #ifdef INET6
339 u_int i;
340
341 if (ndo->ndo_snapend < dat) {
342 ND_PRINT((ndo, " [|aodv]"));
343 return;
344 }
345 i = min(length, (u_int)(ndo->ndo_snapend - dat));
346 if (i < sizeof(ap->rreq6)) {
347 ND_PRINT((ndo, " [|rreq6]"));
348 return;
349 }
350 i -= sizeof(ap->rreq6);
351 ND_PRINT((ndo, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
352 "\tdst %s seq %lu src %s seq %lu", length,
353 ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "",
354 ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "",
355 ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "",
356 ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "",
357 ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
358 ap->rreq6.rreq_hops,
359 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id),
360 ip6addr_string(&ap->rreq6.rreq_da),
361 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds),
362 ip6addr_string(&ap->rreq6.rreq_oa),
363 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os)));
364 if (i >= sizeof(struct aodv_ext))
365 aodv_extension(ndo, (void *)(&ap->rreq6 + 1), i);
366 #else
367 ND_PRINT((ndo, " v6 rreq %u", length));
368 #endif
369 }
370
371 static void
372 #ifdef INET6
373 aodv_v6_rrep(netdissect_options *ndo,
374 const union aodv *ap, const u_char *dat, u_int length)
375 #else
376 aodv_v6_rrep(netdissect_options *ndo,
377 const union aodv *ap _U_, const u_char *dat _U_, u_int length)
378 #endif
379 {
380 #ifdef INET6
381 u_int i;
382
383 if (ndo->ndo_snapend < dat) {
384 ND_PRINT((ndo, " [|aodv]"));
385 return;
386 }
387 i = min(length, (u_int)(ndo->ndo_snapend - dat));
388 if (i < sizeof(ap->rrep6)) {
389 ND_PRINT((ndo, " [|rrep6]"));
390 return;
391 }
392 i -= sizeof(ap->rrep6);
393 ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
394 "\tdst %s dseq %lu src %s %lu ms", length,
395 ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "",
396 ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ",
397 ap->rrep6.rrep_ps & RREP_PREFIX_MASK,
398 ap->rrep6.rrep_hops,
399 ip6addr_string(&ap->rrep6.rrep_da),
400 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds),
401 ip6addr_string(&ap->rrep6.rrep_oa),
402 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life)));
403 if (i >= sizeof(struct aodv_ext))
404 aodv_extension(ndo, (void *)(&ap->rrep6 + 1), i);
405 #else
406 ND_PRINT((ndo, " rrep %u", length));
407 #endif
408 }
409
410 static void
411 #ifdef INET6
412 aodv_v6_rerr(netdissect_options *ndo,
413 const union aodv *ap, u_int length)
414 #else
415 aodv_v6_rerr(netdissect_options *ndo,
416 const union aodv *ap _U_, u_int length)
417 #endif
418 {
419 #ifdef INET6
420 const struct rerr_unreach6 *dp6 = NULL;
421 int i, j, n, trunc;
422
423 i = length - offsetof(struct aodv_rerr, r);
424 j = sizeof(ap->rerr.r.dest6[0]);
425 dp6 = &ap->rerr.r.dest6[0];
426 n = ap->rerr.rerr_dc * j;
427 ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
428 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
429 ap->rerr.rerr_dc, length));
430 trunc = n - (i/j);
431 for (; i -= j >= 0; ++dp6) {
432 ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(&dp6->u_da),
433 (unsigned long)EXTRACT_32BITS(&dp6->u_ds)));
434 }
435 if (trunc)
436 ND_PRINT((ndo, "[|rerr]"));
437 #else
438 ND_PRINT((ndo, " rerr %u", length));
439 #endif
440 }
441
442 static void
443 #ifdef INET6
444 aodv_v6_draft_01_rreq(netdissect_options *ndo,
445 const union aodv *ap, const u_char *dat, u_int length)
446 #else
447 aodv_v6_draft_01_rreq(netdissect_options *ndo,
448 const union aodv *ap _U_, const u_char *dat _U_,
449 u_int length)
450 #endif
451 {
452 #ifdef INET6
453 u_int i;
454
455 if (ndo->ndo_snapend < dat) {
456 ND_PRINT((ndo, " [|aodv]"));
457 return;
458 }
459 i = min(length, (u_int)(ndo->ndo_snapend - dat));
460 if (i < sizeof(ap->rreq6_draft_01)) {
461 ND_PRINT((ndo, " [|rreq6]"));
462 return;
463 }
464 i -= sizeof(ap->rreq6_draft_01);
465 ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n"
466 "\tdst %s seq %lu src %s seq %lu", length,
467 ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "",
468 ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "",
469 ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "",
470 ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "",
471 ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ",
472 ap->rreq6_draft_01.rreq_hops,
473 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id),
474 ip6addr_string(&ap->rreq6_draft_01.rreq_da),
475 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds),
476 ip6addr_string(&ap->rreq6_draft_01.rreq_oa),
477 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os)));
478 if (i >= sizeof(struct aodv_ext))
479 aodv_extension(ndo, (void *)(&ap->rreq6_draft_01 + 1), i);
480 #else
481 ND_PRINT((ndo, " rreq %u", length));
482 #endif
483 }
484
485 static void
486 #ifdef INET6
487 aodv_v6_draft_01_rrep(netdissect_options *ndo,
488 const union aodv *ap, const u_char *dat, u_int length)
489 #else
490 aodv_v6_draft_01_rrep(netdissect_options *ndo,
491 const union aodv *ap _U_, const u_char *dat _U_,
492 u_int length)
493 #endif
494 {
495 #ifdef INET6
496 u_int i;
497
498 if (ndo->ndo_snapend < dat) {
499 ND_PRINT((ndo, " [|aodv]"));
500 return;
501 }
502 i = min(length, (u_int)(ndo->ndo_snapend - dat));
503 if (i < sizeof(ap->rrep6_draft_01)) {
504 ND_PRINT((ndo, " [|rrep6]"));
505 return;
506 }
507 i -= sizeof(ap->rrep6_draft_01);
508 ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n"
509 "\tdst %s dseq %lu src %s %lu ms", length,
510 ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "",
511 ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ",
512 ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK,
513 ap->rrep6_draft_01.rrep_hops,
514 ip6addr_string(&ap->rrep6_draft_01.rrep_da),
515 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds),
516 ip6addr_string(&ap->rrep6_draft_01.rrep_oa),
517 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life)));
518 if (i >= sizeof(struct aodv_ext))
519 aodv_extension(ndo, (void *)(&ap->rrep6_draft_01 + 1), i);
520 #else
521 ND_PRINT((ndo, " rrep %u", length));
522 #endif
523 }
524
525 static void
526 #ifdef INET6
527 aodv_v6_draft_01_rerr(netdissect_options *ndo,
528 const union aodv *ap, u_int length)
529 #else
530 aodv_v6_draft_01_rerr(netdissect_options *ndo,
531 const union aodv *ap _U_, u_int length)
532 #endif
533 {
534 #ifdef INET6
535 const struct rerr_unreach6_draft_01 *dp6 = NULL;
536 int i, j, n, trunc;
537
538 i = length - offsetof(struct aodv_rerr, r);
539 j = sizeof(ap->rerr.r.dest6_draft_01[0]);
540 dp6 = &ap->rerr.r.dest6_draft_01[0];
541 n = ap->rerr.rerr_dc * j;
542 ND_PRINT((ndo, " rerr %s [items %u] [%u]:",
543 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "",
544 ap->rerr.rerr_dc, length));
545 trunc = n - (i/j);
546 for (; i -= j >= 0; ++dp6) {
547 ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(&dp6->u_da),
548 (unsigned long)EXTRACT_32BITS(&dp6->u_ds)));
549 }
550 if (trunc)
551 ND_PRINT((ndo, "[|rerr]"));
552 #else
553 ND_PRINT((ndo, " rerr %u", length));
554 #endif
555 }
556
557 void
558 aodv_print(netdissect_options *ndo,
559 const u_char *dat, u_int length, int is_ip6)
560 {
561 const union aodv *ap;
562
563 ap = (union aodv *)dat;
564 if (ndo->ndo_snapend < dat) {
565 ND_PRINT((ndo, " [|aodv]"));
566 return;
567 }
568 if (min(length, (u_int)(ndo->ndo_snapend - dat)) < sizeof(ap->rrep_ack)) {
569 ND_PRINT((ndo, " [|aodv]"));
570 return;
571 }
572 ND_PRINT((ndo, " aodv"));
573
574 switch (ap->rerr.rerr_type) {
575
576 case AODV_RREQ:
577 if (is_ip6)
578 aodv_v6_rreq(ndo, ap, dat, length);
579 else
580 aodv_rreq(ndo, ap, dat, length);
581 break;
582
583 case AODV_RREP:
584 if (is_ip6)
585 aodv_v6_rrep(ndo, ap, dat, length);
586 else
587 aodv_rrep(ndo, ap, dat, length);
588 break;
589
590 case AODV_RERR:
591 if (is_ip6)
592 aodv_v6_rerr(ndo, ap, length);
593 else
594 aodv_rerr(ndo, ap, dat, length);
595 break;
596
597 case AODV_RREP_ACK:
598 ND_PRINT((ndo, " rrep-ack %u", length));
599 break;
600
601 case AODV_V6_DRAFT_01_RREQ:
602 aodv_v6_draft_01_rreq(ndo, ap, dat, length);
603 break;
604
605 case AODV_V6_DRAFT_01_RREP:
606 aodv_v6_draft_01_rrep(ndo, ap, dat, length);
607 break;
608
609 case AODV_V6_DRAFT_01_RERR:
610 aodv_v6_draft_01_rerr(ndo, ap, length);
611 break;
612
613 case AODV_V6_DRAFT_01_RREP_ACK:
614 ND_PRINT((ndo, " rrep-ack %u", length));
615 break;
616
617 default:
618 ND_PRINT((ndo, " %u %u", ap->rreq.rreq_type, length));
619 }
620 }