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 uint8_t rreq_type; /* AODV message type (1) */ 50 uint8_t rreq_flags; /* various flags */ 51 uint8_t rreq_zero0; /* reserved, set to zero */ 52 uint8_t rreq_hops; /* number of hops from originator */ 53 uint32_t rreq_id; /* request ID */ 54 uint32_t rreq_da; /* destination IPv4 address */ 55 uint32_t rreq_ds; /* destination sequence number */ 56 uint32_t rreq_oa; /* originator IPv4 address */ 57 uint32_t rreq_os; /* originator sequence number */ 58 }; 59 #ifdef INET6 60 struct aodv_rreq6 { 61 uint8_t rreq_type; /* AODV message type (1) */ 62 uint8_t rreq_flags; /* various flags */ 63 uint8_t rreq_zero0; /* reserved, set to zero */ 64 uint8_t rreq_hops; /* number of hops from originator */ 65 uint32_t rreq_id; /* request ID */ 66 struct in6_addr rreq_da; /* destination IPv6 address */ 67 uint32_t rreq_ds; /* destination sequence number */ 68 struct in6_addr rreq_oa; /* originator IPv6 address */ 69 uint32_t rreq_os; /* originator sequence number */ 70 }; 71 struct aodv_rreq6_draft_01 { 72 uint8_t rreq_type; /* AODV message type (16) */ 73 uint8_t rreq_flags; /* various flags */ 74 uint8_t rreq_zero0; /* reserved, set to zero */ 75 uint8_t rreq_hops; /* number of hops from originator */ 76 uint32_t rreq_id; /* request ID */ 77 uint32_t rreq_ds; /* destination sequence number */ 78 uint32_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 uint8_t rrep_type; /* AODV message type (2) */ 93 uint8_t rrep_flags; /* various flags */ 94 uint8_t rrep_ps; /* prefix size */ 95 uint8_t rrep_hops; /* number of hops from o to d */ 96 uint32_t rrep_da; /* destination IPv4 address */ 97 uint32_t rrep_ds; /* destination sequence number */ 98 uint32_t rrep_oa; /* originator IPv4 address */ 99 uint32_t rrep_life; /* lifetime of this route */ 100 }; 101 #ifdef INET6 102 struct aodv_rrep6 { 103 uint8_t rrep_type; /* AODV message type (2) */ 104 uint8_t rrep_flags; /* various flags */ 105 uint8_t rrep_ps; /* prefix size */ 106 uint8_t rrep_hops; /* number of hops from o to d */ 107 struct in6_addr rrep_da; /* destination IPv6 address */ 108 uint32_t rrep_ds; /* destination sequence number */ 109 struct in6_addr rrep_oa; /* originator IPv6 address */ 110 uint32_t rrep_life; /* lifetime of this route */ 111 }; 112 struct aodv_rrep6_draft_01 { 113 uint8_t rrep_type; /* AODV message type (17) */ 114 uint8_t rrep_flags; /* various flags */ 115 uint8_t rrep_ps; /* prefix size */ 116 uint8_t rrep_hops; /* number of hops from o to d */ 117 uint32_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 uint32_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 uint32_t u_da; /* IPv4 address */ 131 uint32_t u_ds; /* sequence number */ 132 }; 133 #ifdef INET6 134 struct rerr_unreach6 { 135 struct in6_addr u_da; /* IPv6 address */ 136 uint32_t u_ds; /* sequence number */ 137 }; 138 struct rerr_unreach6_draft_01 { 139 struct in6_addr u_da; /* IPv6 address */ 140 uint32_t u_ds; /* sequence number */ 141 }; 142 #endif 143 144 struct aodv_rerr { 145 uint8_t rerr_type; /* AODV message type (3 or 18) */ 146 uint8_t rerr_flags; /* various flags */ 147 uint8_t rerr_zero0; /* reserved, set to zero */ 148 uint8_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 uint8_t ra_type; 163 uint8_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 uint8_t type; /* extension type */ 191 uint8_t length; /* extension length */ 192 }; 193 194 struct aodv_hello { 195 struct aodv_ext eh; /* extension header */ 196 uint8_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(ndo, &ap->rreq.rreq_da), 259 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds), 260 ipaddr_string(ndo, &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(ndo, &ap->rrep.rrep_da), 289 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds), 290 ipaddr_string(ndo, &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(ndo, &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(ndo, &ap->rreq6.rreq_da), 361 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds), 362 ip6addr_string(ndo, &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(ndo, &ap->rrep6.rrep_da), 400 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds), 401 ip6addr_string(ndo, &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(ndo, &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(ndo, &ap->rreq6_draft_01.rreq_da), 475 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds), 476 ip6addr_string(ndo, &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(ndo, &ap->rrep6_draft_01.rrep_da), 515 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds), 516 ip6addr_string(ndo, &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(ndo, &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 } 621