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