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 36 static 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 60 static void 61 aodv_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 89 static void 90 aodv_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 121 static void 122 aodv_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 150 static void 151 aodv_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 182 static void 183 #ifdef INET6 184 aodv_v6_rreq(const union aodv *ap, const u_char *dat, u_int length) 185 #else 186 aodv_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 222 static void 223 #ifdef INET6 224 aodv_v6_rrep(const union aodv *ap, const u_char *dat, u_int length) 225 #else 226 aodv_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 259 static void 260 #ifdef INET6 261 aodv_v6_rerr(const union aodv *ap, u_int length) 262 #else 263 aodv_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 289 static void 290 #ifdef INET6 291 aodv_v6_draft_01_rreq(const union aodv *ap, const u_char *dat, u_int length) 292 #else 293 aodv_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 330 static void 331 #ifdef INET6 332 aodv_v6_draft_01_rrep(const union aodv *ap, const u_char *dat, u_int length) 333 #else 334 aodv_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 368 static void 369 #ifdef INET6 370 aodv_v6_draft_01_rerr(const union aodv *ap, u_int length) 371 #else 372 aodv_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 398 void 399 aodv_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