Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 2003 Bruce M. Simpson <bms (at) 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