10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org> 30f74e101Schristos * All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that the following conditions 70f74e101Schristos * are met: 80f74e101Schristos * 1. Redistributions of source code must retain the above copyright 90f74e101Schristos * notice, this list of conditions and the following disclaimer. 100f74e101Schristos * 2. Redistributions in binary form must reproduce the above copyright 110f74e101Schristos * notice, this list of conditions and the following disclaimer in the 120f74e101Schristos * documentation and/or other materials provided with the distribution. 130f74e101Schristos * 3. All advertising materials mentioning features or use of this software 140f74e101Schristos * must display the following acknowledgement: 150f74e101Schristos * This product includes software developed by Bruce M. Simpson. 160f74e101Schristos * 4. Neither the name of Bruce M. Simpson nor the names of co- 170f74e101Schristos * contributors may be used to endorse or promote products derived 180f74e101Schristos * from this software without specific prior written permission. 190f74e101Schristos * 200f74e101Schristos * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS 210f74e101Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 220f74e101Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 230f74e101Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS 240f74e101Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 250f74e101Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 260f74e101Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 270f74e101Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 280f74e101Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 290f74e101Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 300f74e101Schristos * POSSIBILITY OF SUCH DAMAGE. 310f74e101Schristos */ 320f74e101Schristos 3311b3aaa1Schristos #include <sys/cdefs.h> 340f74e101Schristos #ifndef lint 35*26ba0b50Schristos __RCSID("$NetBSD: print-aodv.c,v 1.10 2024/09/02 16:15:30 christos Exp $"); 360f74e101Schristos #endif 370f74e101Schristos 38dc860a36Sspz /* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */ 39dc860a36Sspz 40c74ad251Schristos #include <config.h> 410f74e101Schristos 42c74ad251Schristos #include "netdissect-stdinc.h" 430f74e101Schristos 44fdccd7e4Schristos #include "netdissect.h" 450f74e101Schristos #include "addrtoname.h" 46fdccd7e4Schristos #include "extract.h" 470f74e101Schristos 4872c96ff3Schristos /* 4972c96ff3Schristos * RFC 3561 5072c96ff3Schristos */ 51b3a00663Schristos struct aodv_rreq { 52c74ad251Schristos nd_uint8_t rreq_type; /* AODV message type (1) */ 53c74ad251Schristos nd_uint8_t rreq_flags; /* various flags */ 54c74ad251Schristos nd_uint8_t rreq_zero0; /* reserved, set to zero */ 55c74ad251Schristos nd_uint8_t rreq_hops; /* number of hops from originator */ 56c74ad251Schristos nd_uint32_t rreq_id; /* request ID */ 57c74ad251Schristos nd_ipv4 rreq_da; /* destination IPv4 address */ 58c74ad251Schristos nd_uint32_t rreq_ds; /* destination sequence number */ 59c74ad251Schristos nd_ipv4 rreq_oa; /* originator IPv4 address */ 60c74ad251Schristos nd_uint32_t rreq_os; /* originator sequence number */ 61b3a00663Schristos }; 62b3a00663Schristos struct aodv_rreq6 { 63c74ad251Schristos nd_uint8_t rreq_type; /* AODV message type (1) */ 64c74ad251Schristos nd_uint8_t rreq_flags; /* various flags */ 65c74ad251Schristos nd_uint8_t rreq_zero0; /* reserved, set to zero */ 66c74ad251Schristos nd_uint8_t rreq_hops; /* number of hops from originator */ 67c74ad251Schristos nd_uint32_t rreq_id; /* request ID */ 68c74ad251Schristos nd_ipv6 rreq_da; /* destination IPv6 address */ 69c74ad251Schristos nd_uint32_t rreq_ds; /* destination sequence number */ 70c74ad251Schristos nd_ipv6 rreq_oa; /* originator IPv6 address */ 71c74ad251Schristos nd_uint32_t rreq_os; /* originator sequence number */ 72b3a00663Schristos }; 73b3a00663Schristos struct aodv_rreq6_draft_01 { 74c74ad251Schristos nd_uint8_t rreq_type; /* AODV message type (16) */ 75c74ad251Schristos nd_uint8_t rreq_flags; /* various flags */ 76c74ad251Schristos nd_uint8_t rreq_zero0; /* reserved, set to zero */ 77c74ad251Schristos nd_uint8_t rreq_hops; /* number of hops from originator */ 78c74ad251Schristos nd_uint32_t rreq_id; /* request ID */ 79c74ad251Schristos nd_uint32_t rreq_ds; /* destination sequence number */ 80c74ad251Schristos nd_uint32_t rreq_os; /* originator sequence number */ 81c74ad251Schristos nd_ipv6 rreq_da; /* destination IPv6 address */ 82c74ad251Schristos nd_ipv6 rreq_oa; /* originator IPv6 address */ 83b3a00663Schristos }; 84b3a00663Schristos 85b3a00663Schristos #define RREQ_JOIN 0x80 /* join (reserved for multicast */ 86b3a00663Schristos #define RREQ_REPAIR 0x40 /* repair (reserved for multicast */ 87b3a00663Schristos #define RREQ_GRAT 0x20 /* gratuitous RREP */ 88b3a00663Schristos #define RREQ_DEST 0x10 /* destination only */ 89b3a00663Schristos #define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */ 90b3a00663Schristos #define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */ 91b3a00663Schristos 92b3a00663Schristos struct aodv_rrep { 93c74ad251Schristos nd_uint8_t rrep_type; /* AODV message type (2) */ 94c74ad251Schristos nd_uint8_t rrep_flags; /* various flags */ 95c74ad251Schristos nd_uint8_t rrep_ps; /* prefix size */ 96c74ad251Schristos nd_uint8_t rrep_hops; /* number of hops from o to d */ 97c74ad251Schristos nd_ipv4 rrep_da; /* destination IPv4 address */ 98c74ad251Schristos nd_uint32_t rrep_ds; /* destination sequence number */ 99c74ad251Schristos nd_ipv4 rrep_oa; /* originator IPv4 address */ 100c74ad251Schristos nd_uint32_t rrep_life; /* lifetime of this route */ 101b3a00663Schristos }; 102b3a00663Schristos struct aodv_rrep6 { 103c74ad251Schristos nd_uint8_t rrep_type; /* AODV message type (2) */ 104c74ad251Schristos nd_uint8_t rrep_flags; /* various flags */ 105c74ad251Schristos nd_uint8_t rrep_ps; /* prefix size */ 106c74ad251Schristos nd_uint8_t rrep_hops; /* number of hops from o to d */ 107c74ad251Schristos nd_ipv6 rrep_da; /* destination IPv6 address */ 108c74ad251Schristos nd_uint32_t rrep_ds; /* destination sequence number */ 109c74ad251Schristos nd_ipv6 rrep_oa; /* originator IPv6 address */ 110c74ad251Schristos nd_uint32_t rrep_life; /* lifetime of this route */ 111b3a00663Schristos }; 112b3a00663Schristos struct aodv_rrep6_draft_01 { 113c74ad251Schristos nd_uint8_t rrep_type; /* AODV message type (17) */ 114c74ad251Schristos nd_uint8_t rrep_flags; /* various flags */ 115c74ad251Schristos nd_uint8_t rrep_ps; /* prefix size */ 116c74ad251Schristos nd_uint8_t rrep_hops; /* number of hops from o to d */ 117c74ad251Schristos nd_uint32_t rrep_ds; /* destination sequence number */ 118c74ad251Schristos nd_ipv6 rrep_da; /* destination IPv6 address */ 119c74ad251Schristos nd_ipv6 rrep_oa; /* originator IPv6 address */ 120c74ad251Schristos nd_uint32_t rrep_life; /* lifetime of this route */ 121b3a00663Schristos }; 122b3a00663Schristos 123b3a00663Schristos #define RREP_REPAIR 0x80 /* repair (reserved for multicast */ 124b3a00663Schristos #define RREP_ACK 0x40 /* acknowledgement required */ 125b3a00663Schristos #define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */ 126b3a00663Schristos #define RREP_PREFIX_MASK 0x1F /* mask for prefix size */ 127b3a00663Schristos 128b3a00663Schristos struct rerr_unreach { 129c74ad251Schristos nd_ipv4 u_da; /* IPv4 address */ 130c74ad251Schristos nd_uint32_t u_ds; /* sequence number */ 131b3a00663Schristos }; 132b3a00663Schristos struct rerr_unreach6 { 133c74ad251Schristos nd_ipv6 u_da; /* IPv6 address */ 134c74ad251Schristos nd_uint32_t u_ds; /* sequence number */ 135b3a00663Schristos }; 136b3a00663Schristos struct rerr_unreach6_draft_01 { 137c74ad251Schristos nd_ipv6 u_da; /* IPv6 address */ 138c74ad251Schristos nd_uint32_t u_ds; /* sequence number */ 139b3a00663Schristos }; 140b3a00663Schristos 141b3a00663Schristos struct aodv_rerr { 142c74ad251Schristos nd_uint8_t rerr_type; /* AODV message type (3 or 18) */ 143c74ad251Schristos nd_uint8_t rerr_flags; /* various flags */ 144c74ad251Schristos nd_uint8_t rerr_zero0; /* reserved, set to zero */ 145c74ad251Schristos nd_uint8_t rerr_dc; /* destination count */ 146b3a00663Schristos }; 147b3a00663Schristos 148b3a00663Schristos #define RERR_NODELETE 0x80 /* don't delete the link */ 149b3a00663Schristos #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */ 150b3a00663Schristos 151b3a00663Schristos struct aodv_rrep_ack { 152c74ad251Schristos nd_uint8_t ra_type; 153c74ad251Schristos nd_uint8_t ra_zero0; 154b3a00663Schristos }; 155b3a00663Schristos 156b3a00663Schristos #define AODV_RREQ 1 /* route request */ 157b3a00663Schristos #define AODV_RREP 2 /* route response */ 158b3a00663Schristos #define AODV_RERR 3 /* error report */ 159b3a00663Schristos #define AODV_RREP_ACK 4 /* route response acknowledgement */ 160b3a00663Schristos 161b3a00663Schristos #define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */ 162b3a00663Schristos #define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */ 163b3a00663Schristos #define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */ 164b3a00663Schristos #define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */ 165b3a00663Schristos 166b3a00663Schristos struct aodv_ext { 167c74ad251Schristos nd_uint8_t type; /* extension type */ 168c74ad251Schristos nd_uint8_t length; /* extension length */ 169b3a00663Schristos }; 170b3a00663Schristos 171b3a00663Schristos struct aodv_hello { 172b3a00663Schristos struct aodv_ext eh; /* extension header */ 173c74ad251Schristos nd_uint32_t interval; /* expect my next hello in 174b3a00663Schristos * (n) ms 175b3a00663Schristos * NOTE: this is not aligned */ 176b3a00663Schristos }; 177b3a00663Schristos 178b3a00663Schristos #define AODV_EXT_HELLO 1 1790f74e101Schristos 1800f74e101Schristos static void 181b3a00663Schristos aodv_extension(netdissect_options *ndo, 182b3a00663Schristos const struct aodv_ext *ep, u_int length) 1830f74e101Schristos { 1840f74e101Schristos const struct aodv_hello *ah; 1850f74e101Schristos 186c74ad251Schristos ND_TCHECK_SIZE(ep); 187c74ad251Schristos switch (GET_U_1(ep->type)) { 1880f74e101Schristos case AODV_EXT_HELLO: 189ba2ff121Schristos ah = (const struct aodv_hello *)(const void *)ep; 190c74ad251Schristos ND_TCHECK_SIZE(ah); 191ba2ff121Schristos if (length < sizeof(struct aodv_hello)) 192ba2ff121Schristos goto trunc; 193c74ad251Schristos if (GET_U_1(ep->length) < 4) { 194c74ad251Schristos ND_PRINT("\n\text HELLO - bad length %u", 195c74ad251Schristos GET_U_1(ep->length)); 19672c96ff3Schristos break; 19772c96ff3Schristos } 198c74ad251Schristos ND_PRINT("\n\text HELLO %u ms", 199c74ad251Schristos GET_BE_U_4(ah->interval)); 2000f74e101Schristos break; 2010f74e101Schristos 2020f74e101Schristos default: 203c74ad251Schristos ND_PRINT("\n\text %u %u", GET_U_1(ep->type), 204c74ad251Schristos GET_U_1(ep->length)); 2050f74e101Schristos break; 2060f74e101Schristos } 207ba2ff121Schristos return; 208ba2ff121Schristos 209ba2ff121Schristos trunc: 210c74ad251Schristos nd_print_trunc(ndo); 2110f74e101Schristos } 2120f74e101Schristos 2130f74e101Schristos static void 214ba2ff121Schristos aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length) 2150f74e101Schristos { 2160f74e101Schristos u_int i; 217ba2ff121Schristos const struct aodv_rreq *ap = (const struct aodv_rreq *)dat; 2180f74e101Schristos 219c74ad251Schristos ND_TCHECK_SIZE(ap); 220ba2ff121Schristos if (length < sizeof(*ap)) 221ba2ff121Schristos goto trunc; 222c74ad251Schristos ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n" 223c74ad251Schristos "\tdst %s seq %u src %s seq %u", length, 224c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "", 225c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "", 226c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "", 227c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "", 228c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ", 229c74ad251Schristos GET_U_1(ap->rreq_hops), 230c74ad251Schristos GET_BE_U_4(ap->rreq_id), 231c74ad251Schristos GET_IPADDR_STRING(ap->rreq_da), 232c74ad251Schristos GET_BE_U_4(ap->rreq_ds), 233c74ad251Schristos GET_IPADDR_STRING(ap->rreq_oa), 234c74ad251Schristos GET_BE_U_4(ap->rreq_os)); 235ba2ff121Schristos i = length - sizeof(*ap); 2360f74e101Schristos if (i >= sizeof(struct aodv_ext)) 237ba2ff121Schristos aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); 238ba2ff121Schristos return; 239ba2ff121Schristos 240ba2ff121Schristos trunc: 241c74ad251Schristos nd_print_trunc(ndo); 2420f74e101Schristos } 2430f74e101Schristos 2440f74e101Schristos static void 245ba2ff121Schristos aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length) 2460f74e101Schristos { 2470f74e101Schristos u_int i; 248ba2ff121Schristos const struct aodv_rrep *ap = (const struct aodv_rrep *)dat; 2490f74e101Schristos 250c74ad251Schristos ND_TCHECK_SIZE(ap); 251ba2ff121Schristos if (length < sizeof(*ap)) 252ba2ff121Schristos goto trunc; 253c74ad251Schristos ND_PRINT(" rrep %u %s%sprefix %u hops %u\n" 254c74ad251Schristos "\tdst %s dseq %u src %s %u ms", length, 255c74ad251Schristos GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "", 256c74ad251Schristos GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ", 257c74ad251Schristos GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK, 258c74ad251Schristos GET_U_1(ap->rrep_hops), 259c74ad251Schristos GET_IPADDR_STRING(ap->rrep_da), 260c74ad251Schristos GET_BE_U_4(ap->rrep_ds), 261c74ad251Schristos GET_IPADDR_STRING(ap->rrep_oa), 262c74ad251Schristos GET_BE_U_4(ap->rrep_life)); 263ba2ff121Schristos i = length - sizeof(*ap); 2640f74e101Schristos if (i >= sizeof(struct aodv_ext)) 265ba2ff121Schristos aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); 266ba2ff121Schristos return; 267ba2ff121Schristos 268ba2ff121Schristos trunc: 269c74ad251Schristos nd_print_trunc(ndo); 2700f74e101Schristos } 2710f74e101Schristos 2720f74e101Schristos static void 273ba2ff121Schristos aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length) 2740f74e101Schristos { 275ba2ff121Schristos u_int i, dc; 276ba2ff121Schristos const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; 277ba2ff121Schristos const struct rerr_unreach *dp; 2780f74e101Schristos 279c74ad251Schristos ND_TCHECK_SIZE(ap); 280ba2ff121Schristos if (length < sizeof(*ap)) 281ba2ff121Schristos goto trunc; 282c74ad251Schristos ND_PRINT(" rerr %s [items %u] [%u]:", 283c74ad251Schristos GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "", 284c74ad251Schristos GET_U_1(ap->rerr_dc), length); 285fdccd7e4Schristos dp = (const struct rerr_unreach *)(dat + sizeof(*ap)); 286ba2ff121Schristos i = length - sizeof(*ap); 287c74ad251Schristos for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) { 288c74ad251Schristos ND_TCHECK_SIZE(dp); 289ba2ff121Schristos if (i < sizeof(*dp)) 290ba2ff121Schristos goto trunc; 291c74ad251Schristos ND_PRINT(" {%s}(%u)", GET_IPADDR_STRING(dp->u_da), 292c74ad251Schristos GET_BE_U_4(dp->u_ds)); 293ba2ff121Schristos dp++; 294ba2ff121Schristos i -= sizeof(*dp); 2950f74e101Schristos } 296ba2ff121Schristos return; 297ba2ff121Schristos 298ba2ff121Schristos trunc: 299c74ad251Schristos nd_print_trunc(ndo); 3000f74e101Schristos } 3010f74e101Schristos 3020f74e101Schristos static void 303ba2ff121Schristos aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length) 3040f74e101Schristos { 3050f74e101Schristos u_int i; 306ba2ff121Schristos const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat; 3070f74e101Schristos 308c74ad251Schristos ND_TCHECK_SIZE(ap); 309ba2ff121Schristos if (length < sizeof(*ap)) 310ba2ff121Schristos goto trunc; 311c74ad251Schristos ND_PRINT(" v6 rreq %u %s%s%s%s%shops %u id 0x%08x\n" 312c74ad251Schristos "\tdst %s seq %u src %s seq %u", length, 313c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "", 314c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "", 315c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "", 316c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "", 317c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ", 318c74ad251Schristos GET_U_1(ap->rreq_hops), 319c74ad251Schristos GET_BE_U_4(ap->rreq_id), 320c74ad251Schristos GET_IP6ADDR_STRING(ap->rreq_da), 321c74ad251Schristos GET_BE_U_4(ap->rreq_ds), 322c74ad251Schristos GET_IP6ADDR_STRING(ap->rreq_oa), 323c74ad251Schristos GET_BE_U_4(ap->rreq_os)); 324ba2ff121Schristos i = length - sizeof(*ap); 3250f74e101Schristos if (i >= sizeof(struct aodv_ext)) 326ba2ff121Schristos aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); 327ba2ff121Schristos return; 328ba2ff121Schristos 329ba2ff121Schristos trunc: 330c74ad251Schristos nd_print_trunc(ndo); 3310f74e101Schristos } 3320f74e101Schristos 3330f74e101Schristos static void 334ba2ff121Schristos aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length) 3350f74e101Schristos { 3360f74e101Schristos u_int i; 337ba2ff121Schristos const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat; 3380f74e101Schristos 339c74ad251Schristos ND_TCHECK_SIZE(ap); 340ba2ff121Schristos if (length < sizeof(*ap)) 341ba2ff121Schristos goto trunc; 342c74ad251Schristos ND_PRINT(" rrep %u %s%sprefix %u hops %u\n" 343c74ad251Schristos "\tdst %s dseq %u src %s %u ms", length, 344c74ad251Schristos GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "", 345c74ad251Schristos GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ", 346c74ad251Schristos GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK, 347c74ad251Schristos GET_U_1(ap->rrep_hops), 348c74ad251Schristos GET_IP6ADDR_STRING(ap->rrep_da), 349c74ad251Schristos GET_BE_U_4(ap->rrep_ds), 350c74ad251Schristos GET_IP6ADDR_STRING(ap->rrep_oa), 351c74ad251Schristos GET_BE_U_4(ap->rrep_life)); 352ba2ff121Schristos i = length - sizeof(*ap); 3530f74e101Schristos if (i >= sizeof(struct aodv_ext)) 354ba2ff121Schristos aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); 355ba2ff121Schristos return; 356ba2ff121Schristos 357ba2ff121Schristos trunc: 358c74ad251Schristos nd_print_trunc(ndo); 3590f74e101Schristos } 3600f74e101Schristos 3610f74e101Schristos static void 362ba2ff121Schristos aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length) 3630f74e101Schristos { 364ba2ff121Schristos u_int i, dc; 365ba2ff121Schristos const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; 366ba2ff121Schristos const struct rerr_unreach6 *dp6; 3670f74e101Schristos 368c74ad251Schristos ND_TCHECK_SIZE(ap); 369ba2ff121Schristos if (length < sizeof(*ap)) 370ba2ff121Schristos goto trunc; 371c74ad251Schristos ND_PRINT(" rerr %s [items %u] [%u]:", 372c74ad251Schristos GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "", 373c74ad251Schristos GET_U_1(ap->rerr_dc), length); 374fdccd7e4Schristos dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1); 375ba2ff121Schristos i = length - sizeof(*ap); 376c74ad251Schristos for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) { 377c74ad251Schristos ND_TCHECK_SIZE(dp6); 378ba2ff121Schristos if (i < sizeof(*dp6)) 379ba2ff121Schristos goto trunc; 380c74ad251Schristos ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da), 381c74ad251Schristos GET_BE_U_4(dp6->u_ds)); 382ba2ff121Schristos dp6++; 383ba2ff121Schristos i -= sizeof(*dp6); 3840f74e101Schristos } 385ba2ff121Schristos return; 386ba2ff121Schristos 387ba2ff121Schristos trunc: 388c74ad251Schristos nd_print_trunc(ndo); 3890f74e101Schristos } 3900f74e101Schristos 3910f74e101Schristos static void 392ba2ff121Schristos aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length) 3930f74e101Schristos { 3940f74e101Schristos u_int i; 395ba2ff121Schristos const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat; 3960f74e101Schristos 397c74ad251Schristos ND_TCHECK_SIZE(ap); 398ba2ff121Schristos if (length < sizeof(*ap)) 399ba2ff121Schristos goto trunc; 400c74ad251Schristos ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n" 401c74ad251Schristos "\tdst %s seq %u src %s seq %u", length, 402c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "", 403c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "", 404c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "", 405c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "", 406c74ad251Schristos GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ", 407c74ad251Schristos GET_U_1(ap->rreq_hops), 408c74ad251Schristos GET_BE_U_4(ap->rreq_id), 409c74ad251Schristos GET_IP6ADDR_STRING(ap->rreq_da), 410c74ad251Schristos GET_BE_U_4(ap->rreq_ds), 411c74ad251Schristos GET_IP6ADDR_STRING(ap->rreq_oa), 412c74ad251Schristos GET_BE_U_4(ap->rreq_os)); 413ba2ff121Schristos i = length - sizeof(*ap); 4140f74e101Schristos if (i >= sizeof(struct aodv_ext)) 415ba2ff121Schristos aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); 416ba2ff121Schristos return; 417ba2ff121Schristos 418ba2ff121Schristos trunc: 419c74ad251Schristos nd_print_trunc(ndo); 4200f74e101Schristos } 4210f74e101Schristos 4220f74e101Schristos static void 423ba2ff121Schristos aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length) 4240f74e101Schristos { 4250f74e101Schristos u_int i; 426ba2ff121Schristos const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat; 4270f74e101Schristos 428c74ad251Schristos ND_TCHECK_SIZE(ap); 429ba2ff121Schristos if (length < sizeof(*ap)) 430ba2ff121Schristos goto trunc; 431c74ad251Schristos ND_PRINT(" rrep %u %s%sprefix %u hops %u\n" 432c74ad251Schristos "\tdst %s dseq %u src %s %u ms", length, 433c74ad251Schristos GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "", 434c74ad251Schristos GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ", 435c74ad251Schristos GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK, 436c74ad251Schristos GET_U_1(ap->rrep_hops), 437c74ad251Schristos GET_IP6ADDR_STRING(ap->rrep_da), 438c74ad251Schristos GET_BE_U_4(ap->rrep_ds), 439c74ad251Schristos GET_IP6ADDR_STRING(ap->rrep_oa), 440c74ad251Schristos GET_BE_U_4(ap->rrep_life)); 441ba2ff121Schristos i = length - sizeof(*ap); 4420f74e101Schristos if (i >= sizeof(struct aodv_ext)) 443ba2ff121Schristos aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); 444ba2ff121Schristos return; 445ba2ff121Schristos 446ba2ff121Schristos trunc: 447c74ad251Schristos nd_print_trunc(ndo); 4480f74e101Schristos } 4490f74e101Schristos 4500f74e101Schristos static void 451ba2ff121Schristos aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length) 4520f74e101Schristos { 453ba2ff121Schristos u_int i, dc; 454ba2ff121Schristos const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; 455ba2ff121Schristos const struct rerr_unreach6_draft_01 *dp6; 4560f74e101Schristos 457c74ad251Schristos ND_TCHECK_SIZE(ap); 458ba2ff121Schristos if (length < sizeof(*ap)) 459ba2ff121Schristos goto trunc; 460c74ad251Schristos ND_PRINT(" rerr %s [items %u] [%u]:", 461c74ad251Schristos GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "", 462c74ad251Schristos GET_U_1(ap->rerr_dc), length); 463fdccd7e4Schristos dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1); 464ba2ff121Schristos i = length - sizeof(*ap); 465c74ad251Schristos for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) { 466c74ad251Schristos ND_TCHECK_SIZE(dp6); 467ba2ff121Schristos if (i < sizeof(*dp6)) 468ba2ff121Schristos goto trunc; 469c74ad251Schristos ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da), 470c74ad251Schristos GET_BE_U_4(dp6->u_ds)); 471ba2ff121Schristos dp6++; 472ba2ff121Schristos i -= sizeof(*dp6); 4730f74e101Schristos } 474ba2ff121Schristos return; 475ba2ff121Schristos 476ba2ff121Schristos trunc: 477c74ad251Schristos nd_print_trunc(ndo); 4780f74e101Schristos } 4790f74e101Schristos 4800f74e101Schristos void 481b3a00663Schristos aodv_print(netdissect_options *ndo, 482b3a00663Schristos const u_char *dat, u_int length, int is_ip6) 4830f74e101Schristos { 484ba2ff121Schristos uint8_t msg_type; 4850f74e101Schristos 486c74ad251Schristos ndo->ndo_protocol = "aodv"; 487ba2ff121Schristos /* 488ba2ff121Schristos * The message type is the first byte; make sure we have it 489ba2ff121Schristos * and then fetch it. 490ba2ff121Schristos */ 491c74ad251Schristos msg_type = GET_U_1(dat); 492c74ad251Schristos ND_PRINT(" aodv"); 4930f74e101Schristos 494ba2ff121Schristos switch (msg_type) { 4950f74e101Schristos 4960f74e101Schristos case AODV_RREQ: 4970f74e101Schristos if (is_ip6) 498ba2ff121Schristos aodv_v6_rreq(ndo, dat, length); 4990f74e101Schristos else 500ba2ff121Schristos aodv_rreq(ndo, dat, length); 5010f74e101Schristos break; 5020f74e101Schristos 5030f74e101Schristos case AODV_RREP: 5040f74e101Schristos if (is_ip6) 505ba2ff121Schristos aodv_v6_rrep(ndo, dat, length); 5060f74e101Schristos else 507ba2ff121Schristos aodv_rrep(ndo, dat, length); 5080f74e101Schristos break; 5090f74e101Schristos 5100f74e101Schristos case AODV_RERR: 5110f74e101Schristos if (is_ip6) 512ba2ff121Schristos aodv_v6_rerr(ndo, dat, length); 5130f74e101Schristos else 514ba2ff121Schristos aodv_rerr(ndo, dat, length); 5150f74e101Schristos break; 5160f74e101Schristos 5170f74e101Schristos case AODV_RREP_ACK: 518c74ad251Schristos ND_PRINT(" rrep-ack %u", length); 5190f74e101Schristos break; 5200f74e101Schristos 5210f74e101Schristos case AODV_V6_DRAFT_01_RREQ: 522ba2ff121Schristos aodv_v6_draft_01_rreq(ndo, dat, length); 5230f74e101Schristos break; 5240f74e101Schristos 5250f74e101Schristos case AODV_V6_DRAFT_01_RREP: 526ba2ff121Schristos aodv_v6_draft_01_rrep(ndo, dat, length); 5270f74e101Schristos break; 5280f74e101Schristos 5290f74e101Schristos case AODV_V6_DRAFT_01_RERR: 530ba2ff121Schristos aodv_v6_draft_01_rerr(ndo, dat, length); 5310f74e101Schristos break; 5320f74e101Schristos 5330f74e101Schristos case AODV_V6_DRAFT_01_RREP_ACK: 534c74ad251Schristos ND_PRINT(" rrep-ack %u", length); 5350f74e101Schristos break; 5360f74e101Schristos 5370f74e101Schristos default: 538c74ad251Schristos ND_PRINT(" type %u %u", msg_type, length); 5390f74e101Schristos } 5400f74e101Schristos } 541