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#include <sys/cdefs.h> 34#ifndef lint 35#if 0 36static const char rcsid[] _U_ = 37 "@(#) Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.11 2004-03-24 00:30:19 guy Exp (LBL)"; 38#else 39__RCSID("$NetBSD: print-aodv.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 40#endif 41#endif 42 43#ifdef HAVE_CONFIG_H 44#include "config.h" 45#endif 46 47#include <tcpdump-stdinc.h> 48 49#include <stddef.h> 50#include <stdio.h> 51#include <ctype.h> 52#include <string.h> 53 54#include "interface.h" 55#include "addrtoname.h" 56#include "extract.h" /* must come after interface.h */ 57 58#include "aodv.h" 59 60static void 61aodv_extension(const struct aodv_ext *ep, u_int length) 62{ 63 u_int i; 64 const struct aodv_hello *ah; 65 66 switch (ep->type) { 67 case AODV_EXT_HELLO: 68 if (snapend < (u_char *) ep) { 69 printf(" [|hello]"); 70 return; 71 } 72 i = min(length, (u_int)(snapend - (u_char *)ep)); 73 if (i < sizeof(struct aodv_hello)) { 74 printf(" [|hello]"); 75 return; 76 } 77 i -= sizeof(struct aodv_hello); 78 ah = (void *)ep; 79 printf("\n\text HELLO %ld ms", 80 (unsigned long)EXTRACT_32BITS(&ah->interval)); 81 break; 82 83 default: 84 printf("\n\text %u %u", ep->type, ep->length); 85 break; 86 } 87} 88 89static void 90aodv_rreq(const union aodv *ap, const u_char *dat, u_int length) 91{ 92 u_int i; 93 94 if (snapend < dat) { 95 printf(" [|aodv]"); 96 return; 97 } 98 i = min(length, (u_int)(snapend - dat)); 99 if (i < sizeof(ap->rreq)) { 100 printf(" [|rreq]"); 101 return; 102 } 103 i -= sizeof(ap->rreq); 104 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n" 105 "\tdst %s seq %lu src %s seq %lu", length, 106 ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "", 107 ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "", 108 ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "", 109 ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "", 110 ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", 111 ap->rreq.rreq_hops, 112 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id), 113 ipaddr_string(&ap->rreq.rreq_da), 114 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds), 115 ipaddr_string(&ap->rreq.rreq_oa), 116 (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os)); 117 if (i >= sizeof(struct aodv_ext)) 118 aodv_extension((void *)(&ap->rreq + 1), i); 119} 120 121static void 122aodv_rrep(const union aodv *ap, const u_char *dat, u_int length) 123{ 124 u_int i; 125 126 if (snapend < dat) { 127 printf(" [|aodv]"); 128 return; 129 } 130 i = min(length, (u_int)(snapend - dat)); 131 if (i < sizeof(ap->rrep)) { 132 printf(" [|rrep]"); 133 return; 134 } 135 i -= sizeof(ap->rrep); 136 printf(" rrep %u %s%sprefix %u hops %u\n" 137 "\tdst %s dseq %lu src %s %lu ms", length, 138 ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "", 139 ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ", 140 ap->rrep.rrep_ps & RREP_PREFIX_MASK, 141 ap->rrep.rrep_hops, 142 ipaddr_string(&ap->rrep.rrep_da), 143 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds), 144 ipaddr_string(&ap->rrep.rrep_oa), 145 (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life)); 146 if (i >= sizeof(struct aodv_ext)) 147 aodv_extension((void *)(&ap->rrep + 1), i); 148} 149 150static void 151aodv_rerr(const union aodv *ap, const u_char *dat, u_int length) 152{ 153 u_int i; 154 const struct rerr_unreach *dp = NULL; 155 int n, trunc; 156 157 if (snapend < dat) { 158 printf(" [|aodv]"); 159 return; 160 } 161 i = min(length, (u_int)(snapend - dat)); 162 if (i < offsetof(struct aodv_rerr, r)) { 163 printf(" [|rerr]"); 164 return; 165 } 166 i -= offsetof(struct aodv_rerr, r); 167 dp = &ap->rerr.r.dest[0]; 168 n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]); 169 printf(" rerr %s [items %u] [%u]:", 170 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", 171 ap->rerr.rerr_dc, length); 172 trunc = n - (i/sizeof(ap->rerr.r.dest[0])); 173 for (; i >= sizeof(ap->rerr.r.dest[0]); 174 ++dp, i -= sizeof(ap->rerr.r.dest[0])) { 175 printf(" {%s}(%ld)", ipaddr_string(&dp->u_da), 176 (unsigned long)EXTRACT_32BITS(&dp->u_ds)); 177 } 178 if (trunc) 179 printf("[|rerr]"); 180} 181 182static void 183#ifdef INET6 184aodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length) 185#else 186aodv_v6_rreq(const union aodv *ap _U_, const u_char *dat _U_, u_int length) 187#endif 188{ 189#ifdef INET6 190 u_int i; 191 192 if (snapend < dat) { 193 printf(" [|aodv]"); 194 return; 195 } 196 i = min(length, (u_int)(snapend - dat)); 197 if (i < sizeof(ap->rreq6)) { 198 printf(" [|rreq6]"); 199 return; 200 } 201 i -= sizeof(ap->rreq6); 202 printf(" v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n" 203 "\tdst %s seq %lu src %s seq %lu", length, 204 ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "", 205 ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "", 206 ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "", 207 ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "", 208 ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", 209 ap->rreq6.rreq_hops, 210 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id), 211 ip6addr_string(&ap->rreq6.rreq_da), 212 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds), 213 ip6addr_string(&ap->rreq6.rreq_oa), 214 (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os)); 215 if (i >= sizeof(struct aodv_ext)) 216 aodv_extension((void *)(&ap->rreq6 + 1), i); 217#else 218 printf(" v6 rreq %u", length); 219#endif 220} 221 222static void 223#ifdef INET6 224aodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length) 225#else 226aodv_v6_rrep(const union aodv *ap _U_, const u_char *dat _U_, u_int length) 227#endif 228{ 229#ifdef INET6 230 u_int i; 231 232 if (snapend < dat) { 233 printf(" [|aodv]"); 234 return; 235 } 236 i = min(length, (u_int)(snapend - dat)); 237 if (i < sizeof(ap->rrep6)) { 238 printf(" [|rrep6]"); 239 return; 240 } 241 i -= sizeof(ap->rrep6); 242 printf(" rrep %u %s%sprefix %u hops %u\n" 243 "\tdst %s dseq %lu src %s %lu ms", length, 244 ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "", 245 ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ", 246 ap->rrep6.rrep_ps & RREP_PREFIX_MASK, 247 ap->rrep6.rrep_hops, 248 ip6addr_string(&ap->rrep6.rrep_da), 249 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds), 250 ip6addr_string(&ap->rrep6.rrep_oa), 251 (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life)); 252 if (i >= sizeof(struct aodv_ext)) 253 aodv_extension((void *)(&ap->rrep6 + 1), i); 254#else 255 printf(" rrep %u", length); 256#endif 257} 258 259static void 260#ifdef INET6 261aodv_v6_rerr(const union aodv *ap, u_int length) 262#else 263aodv_v6_rerr(const union aodv *ap _U_, u_int length) 264#endif 265{ 266#ifdef INET6 267 const struct rerr_unreach6 *dp6 = NULL; 268 int i, j, n, trunc; 269 270 i = length - offsetof(struct aodv_rerr, r); 271 j = sizeof(ap->rerr.r.dest6[0]); 272 dp6 = &ap->rerr.r.dest6[0]; 273 n = ap->rerr.rerr_dc * j; 274 printf(" rerr %s [items %u] [%u]:", 275 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", 276 ap->rerr.rerr_dc, length); 277 trunc = n - (i/j); 278 for (; i -= j >= 0; ++dp6) { 279 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da), 280 (unsigned long)EXTRACT_32BITS(&dp6->u_ds)); 281 } 282 if (trunc) 283 printf("[|rerr]"); 284#else 285 printf(" rerr %u", length); 286#endif 287} 288 289static void 290#ifdef INET6 291aodv_v6_draft_01_rreq(const union aodv *ap, const u_char *dat, u_int length) 292#else 293aodv_v6_draft_01_rreq(const union aodv *ap _U_, const u_char *dat _U_, 294 u_int length) 295#endif 296{ 297#ifdef INET6 298 u_int i; 299 300 if (snapend < dat) { 301 printf(" [|aodv]"); 302 return; 303 } 304 i = min(length, (u_int)(snapend - dat)); 305 if (i < sizeof(ap->rreq6_draft_01)) { 306 printf(" [|rreq6]"); 307 return; 308 } 309 i -= sizeof(ap->rreq6_draft_01); 310 printf(" rreq %u %s%s%s%s%shops %u id 0x%08lx\n" 311 "\tdst %s seq %lu src %s seq %lu", length, 312 ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "", 313 ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "", 314 ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "", 315 ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "", 316 ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", 317 ap->rreq6_draft_01.rreq_hops, 318 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id), 319 ip6addr_string(&ap->rreq6_draft_01.rreq_da), 320 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds), 321 ip6addr_string(&ap->rreq6_draft_01.rreq_oa), 322 (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os)); 323 if (i >= sizeof(struct aodv_ext)) 324 aodv_extension((void *)(&ap->rreq6_draft_01 + 1), i); 325#else 326 printf(" rreq %u", length); 327#endif 328} 329 330static void 331#ifdef INET6 332aodv_v6_draft_01_rrep(const union aodv *ap, const u_char *dat, u_int length) 333#else 334aodv_v6_draft_01_rrep(const union aodv *ap _U_, const u_char *dat _U_, 335 u_int length) 336#endif 337{ 338#ifdef INET6 339 u_int i; 340 341 if (snapend < dat) { 342 printf(" [|aodv]"); 343 return; 344 } 345 i = min(length, (u_int)(snapend - dat)); 346 if (i < sizeof(ap->rrep6_draft_01)) { 347 printf(" [|rrep6]"); 348 return; 349 } 350 i -= sizeof(ap->rrep6_draft_01); 351 printf(" rrep %u %s%sprefix %u hops %u\n" 352 "\tdst %s dseq %lu src %s %lu ms", length, 353 ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "", 354 ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ", 355 ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK, 356 ap->rrep6_draft_01.rrep_hops, 357 ip6addr_string(&ap->rrep6_draft_01.rrep_da), 358 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds), 359 ip6addr_string(&ap->rrep6_draft_01.rrep_oa), 360 (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life)); 361 if (i >= sizeof(struct aodv_ext)) 362 aodv_extension((void *)(&ap->rrep6_draft_01 + 1), i); 363#else 364 printf(" rrep %u", length); 365#endif 366} 367 368static void 369#ifdef INET6 370aodv_v6_draft_01_rerr(const union aodv *ap, u_int length) 371#else 372aodv_v6_draft_01_rerr(const union aodv *ap _U_, u_int length) 373#endif 374{ 375#ifdef INET6 376 const struct rerr_unreach6_draft_01 *dp6 = NULL; 377 int i, j, n, trunc; 378 379 i = length - offsetof(struct aodv_rerr, r); 380 j = sizeof(ap->rerr.r.dest6_draft_01[0]); 381 dp6 = &ap->rerr.r.dest6_draft_01[0]; 382 n = ap->rerr.rerr_dc * j; 383 printf(" rerr %s [items %u] [%u]:", 384 ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", 385 ap->rerr.rerr_dc, length); 386 trunc = n - (i/j); 387 for (; i -= j >= 0; ++dp6) { 388 printf(" {%s}(%ld)", ip6addr_string(&dp6->u_da), 389 (unsigned long)EXTRACT_32BITS(&dp6->u_ds)); 390 } 391 if (trunc) 392 printf("[|rerr]"); 393#else 394 printf(" rerr %u", length); 395#endif 396} 397 398void 399aodv_print(const u_char *dat, u_int length, int is_ip6) 400{ 401 const union aodv *ap; 402 403 ap = (union aodv *)dat; 404 if (snapend < dat) { 405 printf(" [|aodv]"); 406 return; 407 } 408 if (min(length, (u_int)(snapend - dat)) < sizeof(ap->rrep_ack)) { 409 printf(" [|aodv]"); 410 return; 411 } 412 printf(" aodv"); 413 414 switch (ap->rerr.rerr_type) { 415 416 case AODV_RREQ: 417 if (is_ip6) 418 aodv_v6_rreq(ap, dat, length); 419 else 420 aodv_rreq(ap, dat, length); 421 break; 422 423 case AODV_RREP: 424 if (is_ip6) 425 aodv_v6_rrep(ap, dat, length); 426 else 427 aodv_rrep(ap, dat, length); 428 break; 429 430 case AODV_RERR: 431 if (is_ip6) 432 aodv_v6_rerr(ap, length); 433 else 434 aodv_rerr(ap, dat, length); 435 break; 436 437 case AODV_RREP_ACK: 438 printf(" rrep-ack %u", length); 439 break; 440 441 case AODV_V6_DRAFT_01_RREQ: 442 aodv_v6_draft_01_rreq(ap, dat, length); 443 break; 444 445 case AODV_V6_DRAFT_01_RREP: 446 aodv_v6_draft_01_rrep(ap, dat, length); 447 break; 448 449 case AODV_V6_DRAFT_01_RERR: 450 aodv_v6_draft_01_rerr(ap, length); 451 break; 452 453 case AODV_V6_DRAFT_01_RREP_ACK: 454 printf(" rrep-ack %u", length); 455 break; 456 457 default: 458 printf(" %u %u", ap->rreq.rreq_type, length); 459 } 460} 461