Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 1995, 1996
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that: (1) source code distributions
      7  * retain the above copyright notice and this paragraph in its entirety, (2)
      8  * distributions including binary code include the above copyright notice and
      9  * this paragraph in its entirety in the documentation or other materials
     10  * provided with the distribution, and (3) all advertising materials mentioning
     11  * features or use of this software display the following acknowledgement:
     12  * ``This product includes software developed by the University of California,
     13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14  * the University nor the names of its contributors may be used to endorse
     15  * or promote products derived from this software without specific prior
     16  * written permission.
     17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  */
     21 
     22 #ifndef lint
     23 static const char rcsid[] _U_ =
     24     "@(#) $Header: /tcpdump/master/tcpdump/print-dvmrp.c,v 1.27 2003/11/19 09:42:04 guy Exp $ (LBL)";
     25 #endif
     26 
     27 #ifdef HAVE_CONFIG_H
     28 #include "config.h"
     29 #endif
     30 
     31 #include <tcpdump-stdinc.h>
     32 
     33 #include <stdio.h>
     34 #include <string.h>
     35 #include <stdlib.h>
     36 
     37 #include "interface.h"
     38 #include "extract.h"
     39 #include "addrtoname.h"
     40 
     41 /*
     42  * DVMRP message types and flag values shamelessly stolen from
     43  * mrouted/dvmrp.h.
     44  */
     45 #define DVMRP_PROBE		1	/* for finding neighbors */
     46 #define DVMRP_REPORT		2	/* for reporting some or all routes */
     47 #define DVMRP_ASK_NEIGHBORS	3	/* sent by mapper, asking for a list */
     48 					/* of this router's neighbors */
     49 #define DVMRP_NEIGHBORS		4	/* response to such a request */
     50 #define DVMRP_ASK_NEIGHBORS2	5	/* as above, want new format reply */
     51 #define DVMRP_NEIGHBORS2	6
     52 #define DVMRP_PRUNE		7	/* prune message */
     53 #define DVMRP_GRAFT		8	/* graft message */
     54 #define DVMRP_GRAFT_ACK		9	/* graft acknowledgement */
     55 
     56 /*
     57  * 'flags' byte values in DVMRP_NEIGHBORS2 reply.
     58  */
     59 #define DVMRP_NF_TUNNEL		0x01	/* neighbors reached via tunnel */
     60 #define DVMRP_NF_SRCRT		0x02	/* tunnel uses IP source routing */
     61 #define DVMRP_NF_DOWN		0x10	/* kernel state of interface */
     62 #define DVMRP_NF_DISABLED	0x20	/* administratively disabled */
     63 #define DVMRP_NF_QUERIER	0x40	/* I am the subnet's querier */
     64 
     65 static int print_probe(const u_char *, const u_char *, u_int);
     66 static int print_report(const u_char *, const u_char *, u_int);
     67 static int print_neighbors(const u_char *, const u_char *, u_int);
     68 static int print_neighbors2(const u_char *, const u_char *, u_int);
     69 static int print_prune(const u_char *);
     70 static int print_graft(const u_char *);
     71 static int print_graft_ack(const u_char *);
     72 
     73 static u_int32_t target_level;
     74 
     75 void
     76 dvmrp_print(register const u_char *bp, register u_int len)
     77 {
     78 	register const u_char *ep;
     79 	register u_char type;
     80 
     81 	ep = (const u_char *)snapend;
     82 	if (bp >= ep)
     83 		return;
     84 
     85 	TCHECK(bp[1]);
     86 	type = bp[1];
     87 
     88 	/* Skip IGMP header */
     89 	bp += 8;
     90 	len -= 8;
     91 
     92 	switch (type) {
     93 
     94 	case DVMRP_PROBE:
     95 		printf(" Probe");
     96 		if (vflag) {
     97 			if (print_probe(bp, ep, len) < 0)
     98 				goto trunc;
     99 		}
    100 		break;
    101 
    102 	case DVMRP_REPORT:
    103 		printf(" Report");
    104 		if (vflag > 1) {
    105 			if (print_report(bp, ep, len) < 0)
    106 				goto trunc;
    107 		}
    108 		break;
    109 
    110 	case DVMRP_ASK_NEIGHBORS:
    111 		printf(" Ask-neighbors(old)");
    112 		break;
    113 
    114 	case DVMRP_NEIGHBORS:
    115 		printf(" Neighbors(old)");
    116 		if (print_neighbors(bp, ep, len) < 0)
    117 			goto trunc;
    118 		break;
    119 
    120 	case DVMRP_ASK_NEIGHBORS2:
    121 		printf(" Ask-neighbors2");
    122 		break;
    123 
    124 	case DVMRP_NEIGHBORS2:
    125 		printf(" Neighbors2");
    126 		/*
    127 		 * extract version and capabilities from IGMP group
    128 		 * address field
    129 		 */
    130 		bp -= 4;
    131 		TCHECK2(bp[0], 4);
    132 		target_level = (bp[0] << 24) | (bp[1] << 16) |
    133 		    (bp[2] << 8) | bp[3];
    134 		bp += 4;
    135 		if (print_neighbors2(bp, ep, len) < 0)
    136 			goto trunc;
    137 		break;
    138 
    139 	case DVMRP_PRUNE:
    140 		printf(" Prune");
    141 		if (print_prune(bp) < 0)
    142 			goto trunc;
    143 		break;
    144 
    145 	case DVMRP_GRAFT:
    146 		printf(" Graft");
    147 		if (print_graft(bp) < 0)
    148 			goto trunc;
    149 		break;
    150 
    151 	case DVMRP_GRAFT_ACK:
    152 		printf(" Graft-ACK");
    153 		if (print_graft_ack(bp) < 0)
    154 			goto trunc;
    155 		break;
    156 
    157 	default:
    158 		printf(" [type %d]", type);
    159 		break;
    160 	}
    161 	return;
    162 
    163 trunc:
    164 	printf("[|dvmrp]");
    165 	return;
    166 }
    167 
    168 static int
    169 print_report(register const u_char *bp, register const u_char *ep,
    170     register u_int len)
    171 {
    172 	register u_int32_t mask, origin;
    173 	register int metric, done;
    174 	register u_int i, width;
    175 
    176 	while (len > 0) {
    177 		if (len < 3) {
    178 			printf(" [|]");
    179 			return (0);
    180 		}
    181 		TCHECK2(bp[0], 3);
    182 		mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2];
    183 		width = 1;
    184 		if (bp[0])
    185 			width = 2;
    186 		if (bp[1])
    187 			width = 3;
    188 		if (bp[2])
    189 			width = 4;
    190 
    191 		printf("\n\tMask %s", intoa(htonl(mask)));
    192 		bp += 3;
    193 		len -= 3;
    194 		do {
    195 			if (bp + width + 1 > ep) {
    196 				printf(" [|]");
    197 				return (0);
    198 			}
    199 			if (len < width + 1) {
    200 				printf("\n\t  [Truncated Report]");
    201 				return (0);
    202 			}
    203 			origin = 0;
    204 			for (i = 0; i < width; ++i) {
    205 				TCHECK(*bp);
    206 				origin = origin << 8 | *bp++;
    207 			}
    208 			for ( ; i < 4; ++i)
    209 				origin <<= 8;
    210 
    211 			TCHECK(*bp);
    212 			metric = *bp++;
    213 			done = metric & 0x80;
    214 			metric &= 0x7f;
    215 			printf("\n\t  %s metric %d", intoa(htonl(origin)),
    216 				metric);
    217 			len -= width + 1;
    218 		} while (!done);
    219 	}
    220 	return (0);
    221 trunc:
    222 	return (-1);
    223 }
    224 
    225 static int
    226 print_probe(register const u_char *bp, register const u_char *ep,
    227     register u_int len)
    228 {
    229 	register u_int32_t genid;
    230 
    231 	TCHECK2(bp[0], 4);
    232 	if ((len < 4) || ((bp + 4) > ep)) {
    233 		/* { (ctags) */
    234 		printf(" [|}");
    235 		return (0);
    236 	}
    237 	genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3];
    238 	bp += 4;
    239 	len -= 4;
    240 	if (vflag > 1)
    241 		printf("\n\t");
    242 	else
    243 		printf(" ");
    244 	printf("genid %u", genid);
    245 	if (vflag < 2)
    246 		return (0);
    247 
    248 	while ((len > 0) && (bp < ep)) {
    249 		TCHECK2(bp[0], 4);
    250 		printf("\n\tneighbor %s", ipaddr_string(bp));
    251 		bp += 4; len -= 4;
    252 	}
    253 	return (0);
    254 trunc:
    255 	return (-1);
    256 }
    257 
    258 static int
    259 print_neighbors(register const u_char *bp, register const u_char *ep,
    260     register u_int len)
    261 {
    262 	const u_char *laddr;
    263 	register u_char metric;
    264 	register u_char thresh;
    265 	register int ncount;
    266 
    267 	while (len > 0 && bp < ep) {
    268 		TCHECK2(bp[0], 7);
    269 		laddr = bp;
    270 		bp += 4;
    271 		metric = *bp++;
    272 		thresh = *bp++;
    273 		ncount = *bp++;
    274 		len -= 7;
    275 		while (--ncount >= 0) {
    276 			TCHECK2(bp[0], 4);
    277 			printf(" [%s ->", ipaddr_string(laddr));
    278 			printf(" %s, (%d/%d)]",
    279 				   ipaddr_string(bp), metric, thresh);
    280 			bp += 4;
    281 			len -= 4;
    282 		}
    283 	}
    284 	return (0);
    285 trunc:
    286 	return (-1);
    287 }
    288 
    289 static int
    290 print_neighbors2(register const u_char *bp, register const u_char *ep,
    291     register u_int len)
    292 {
    293 	const u_char *laddr;
    294 	register u_char metric, thresh, flags;
    295 	register int ncount;
    296 
    297 	printf(" (v %d.%d):",
    298 	       (int)target_level & 0xff,
    299 	       (int)(target_level >> 8) & 0xff);
    300 
    301 	while (len > 0 && bp < ep) {
    302 		TCHECK2(bp[0], 8);
    303 		laddr = bp;
    304 		bp += 4;
    305 		metric = *bp++;
    306 		thresh = *bp++;
    307 		flags = *bp++;
    308 		ncount = *bp++;
    309 		len -= 8;
    310 		while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) {
    311 			printf(" [%s -> ", ipaddr_string(laddr));
    312 			printf("%s (%d/%d", ipaddr_string(bp),
    313 				     metric, thresh);
    314 			if (flags & DVMRP_NF_TUNNEL)
    315 				printf("/tunnel");
    316 			if (flags & DVMRP_NF_SRCRT)
    317 				printf("/srcrt");
    318 			if (flags & DVMRP_NF_QUERIER)
    319 				printf("/querier");
    320 			if (flags & DVMRP_NF_DISABLED)
    321 				printf("/disabled");
    322 			if (flags & DVMRP_NF_DOWN)
    323 				printf("/down");
    324 			printf(")]");
    325 			bp += 4;
    326 			len -= 4;
    327 		}
    328 		if (ncount != -1) {
    329 			printf(" [|]");
    330 			return (0);
    331 		}
    332 	}
    333 	return (0);
    334 trunc:
    335 	return (-1);
    336 }
    337 
    338 static int
    339 print_prune(register const u_char *bp)
    340 {
    341 	TCHECK2(bp[0], 12);
    342 	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
    343 	bp += 8;
    344 	(void)printf(" timer ");
    345 	relts_print(EXTRACT_32BITS(bp));
    346 	return (0);
    347 trunc:
    348 	return (-1);
    349 }
    350 
    351 static int
    352 print_graft(register const u_char *bp)
    353 {
    354 	TCHECK2(bp[0], 8);
    355 	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
    356 	return (0);
    357 trunc:
    358 	return (-1);
    359 }
    360 
    361 static int
    362 print_graft_ack(register const u_char *bp)
    363 {
    364 	TCHECK2(bp[0], 8);
    365 	printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4));
    366 	return (0);
    367 trunc:
    368 	return (-1);
    369 }
    370