print-pim.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,094 行 · 第 1/2 页

C
1,094
字号
/* * Copyright (c) 1995, 1996 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic const char rcsid[] _U_ =    "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.49 2006-02-13 01:31:35 hannes Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <tcpdump-stdinc.h>#include "interface.h"#define PIMV2_TYPE_HELLO         0#define PIMV2_TYPE_REGISTER      1#define PIMV2_TYPE_REGISTER_STOP 2#define PIMV2_TYPE_JOIN_PRUNE    3#define PIMV2_TYPE_BOOTSTRAP     4#define PIMV2_TYPE_ASSERT        5#define PIMV2_TYPE_GRAFT         6#define PIMV2_TYPE_GRAFT_ACK     7#define PIMV2_TYPE_CANDIDATE_RP  8#define PIMV2_TYPE_PRUNE_REFRESH 9static struct tok pimv2_type_values[] = {    { PIMV2_TYPE_HELLO,         "Hello" },    { PIMV2_TYPE_REGISTER,      "Register" },    { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },    { PIMV2_TYPE_JOIN_PRUNE,    "Join / Prune" },    { PIMV2_TYPE_BOOTSTRAP,     "Bootstrap" },    { PIMV2_TYPE_ASSERT,        "Assert" },    { PIMV2_TYPE_GRAFT,         "Graft" },    { PIMV2_TYPE_GRAFT_ACK,     "Graft Acknowledgement" },    { PIMV2_TYPE_CANDIDATE_RP,  "Candidate RP Advertisement" },    { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },    { 0, NULL}};#define PIMV2_HELLO_OPTION_HOLDTIME             1#define PIMV2_HELLO_OPTION_LANPRUNEDELAY        2#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD     18#define PIMV2_HELLO_OPTION_DR_PRIORITY         19#define PIMV2_HELLO_OPTION_GENID               20#define PIMV2_HELLO_OPTION_REFRESH_CAP         21#define PIMV2_HELLO_OPTION_BIDIR_CAP           22#define PIMV2_HELLO_OPTION_ADDRESS_LIST        24#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001static struct tok pimv2_hello_option_values[] = {    { PIMV2_HELLO_OPTION_HOLDTIME,         "Hold Time" },    { PIMV2_HELLO_OPTION_LANPRUNEDELAY,    "LAN Prune Delay" },    { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD,  "DR Priority (Old)" },    { PIMV2_HELLO_OPTION_DR_PRIORITY,      "DR Priority" },    { PIMV2_HELLO_OPTION_GENID,            "Generation ID" },    { PIMV2_HELLO_OPTION_REFRESH_CAP,      "State Refresh Capability" },    { PIMV2_HELLO_OPTION_BIDIR_CAP,        "Bi-Directional Capability" },    { PIMV2_HELLO_OPTION_ADDRESS_LIST,     "Address List" },    { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },    { 0, NULL}};#define PIMV2_REGISTER_FLAG_LEN      4#define PIMV2_REGISTER_FLAG_BORDER 0x80000000#define PIMV2_REGISTER_FLAG_NULL   0x40000000static struct tok pimv2_register_flag_values[] = {    { PIMV2_REGISTER_FLAG_BORDER, "Border" },    { PIMV2_REGISTER_FLAG_NULL, "Null" },    { 0, NULL}};    /* * XXX: We consider a case where IPv6 is not ready yet for portability, * but PIM dependent defintions should be independent of IPv6... */struct pim {	u_int8_t pim_typever;			/* upper 4bit: PIM version number; 2 for PIMv2 */			/* lower 4bit: the PIM message type, currently they are:			 * Hello, Register, Register-Stop, Join/Prune,			 * Bootstrap, Assert, Graft (PIM-DM only),			 * Graft-Ack (PIM-DM only), C-RP-Adv			 */#define PIM_VER(x)	(((x) & 0xf0) >> 4)#define PIM_TYPE(x)	((x) & 0x0f)	u_char  pim_rsv;	/* Reserved */	u_short	pim_cksum;	/* IP style check sum */};#include <stdio.h>#include <stdlib.h>#include "interface.h"#include "addrtoname.h"#include "extract.h"#include "ip.h"static void pimv2_print(register const u_char *bp, register u_int len);static voidpimv1_join_prune_print(register const u_char *bp, register u_int len){	int maddrlen, addrlen, ngroups, njoin, nprune;	int njp;	/* If it's a single group and a single source, use 1-line output. */	if (TTEST2(bp[0], 30) && bp[11] == 1 &&	    ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) {		int hold;		(void)printf(" RPF %s ", ipaddr_string(bp));		hold = EXTRACT_16BITS(&bp[6]);		if (hold != 180) {			(void)printf("Hold ");			relts_print(hold);		}		(void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune",		ipaddr_string(&bp[26]), bp[25] & 0x3f,		ipaddr_string(&bp[12]));		if (EXTRACT_32BITS(&bp[16]) != 0xffffffff)			(void)printf("/%s", ipaddr_string(&bp[16]));		(void)printf(") %s%s %s",		    (bp[24] & 0x01) ? "Sparse" : "Dense",		    (bp[25] & 0x80) ? " WC" : "",		    (bp[25] & 0x40) ? "RP" : "SPT");		return;	}	TCHECK2(bp[0], sizeof(struct in_addr));	if (vflag > 1)		(void)printf("\n");	(void)printf(" Upstream Nbr: %s", ipaddr_string(bp));	TCHECK2(bp[6], 2);	if (vflag > 1)		(void)printf("\n");	(void)printf(" Hold time: ");	relts_print(EXTRACT_16BITS(&bp[6]));	if (vflag < 2)		return;	bp += 8;	len -= 8;	TCHECK2(bp[0], 4);	maddrlen = bp[1];	addrlen = bp[2];	ngroups = bp[3];	bp += 4;	len -= 4;	while (ngroups--) {		/*		 * XXX - does the address have length "addrlen" and the		 * mask length "maddrlen"?		 */		TCHECK2(bp[0], sizeof(struct in_addr));		(void)printf("\n\tGroup: %s", ipaddr_string(bp));		TCHECK2(bp[4], sizeof(struct in_addr));		if (EXTRACT_32BITS(&bp[4]) != 0xffffffff)			(void)printf("/%s", ipaddr_string(&bp[4]));		TCHECK2(bp[8], 4);		njoin = EXTRACT_16BITS(&bp[8]);		nprune = EXTRACT_16BITS(&bp[10]);		(void)printf(" joined: %d pruned: %d", njoin, nprune);		bp += 12;		len -= 12;		for (njp = 0; njp < (njoin + nprune); njp++) {			const char *type;			if (njp < njoin)				type = "Join ";			else				type = "Prune";			TCHECK2(bp[0], 6);			(void)printf("\n\t%s %s%s%s%s/%d", type,			    (bp[0] & 0x01) ? "Sparse " : "Dense ",			    (bp[1] & 0x80) ? "WC " : "",			    (bp[1] & 0x40) ? "RP " : "SPT ",			ipaddr_string(&bp[2]), bp[1] & 0x3f);			bp += 6;			len -= 6;		}	}	return;trunc:	(void)printf("[|pim]");	return;}voidpimv1_print(register const u_char *bp, register u_int len){	register const u_char *ep;	register u_char type;	ep = (const u_char *)snapend;	if (bp >= ep)		return;	TCHECK(bp[1]);	type = bp[1];	switch (type) {	case 0:		(void)printf(" Query");		if (TTEST(bp[8])) {			switch (bp[8] >> 4) {			case 0:				(void)printf(" Dense-mode");				break;			case 1:				(void)printf(" Sparse-mode");				break;			case 2:				(void)printf(" Sparse-Dense-mode");				break;			default:				(void)printf(" mode-%d", bp[8] >> 4);				break;			}		}		if (vflag) {			TCHECK2(bp[10],2);			(void)printf(" (Hold-time ");			relts_print(EXTRACT_16BITS(&bp[10]));			(void)printf(")");		}		break;	case 1:		(void)printf(" Register");		TCHECK2(bp[8], 20);			/* ip header */		(void)printf(" for %s > %s", ipaddr_string(&bp[20]),		    ipaddr_string(&bp[24]));		break;	case 2:		(void)printf(" Register-Stop");		TCHECK2(bp[12], sizeof(struct in_addr));		(void)printf(" for %s > %s", ipaddr_string(&bp[8]),		    ipaddr_string(&bp[12]));		break;	case 3:		(void)printf(" Join/Prune");		if (vflag)			pimv1_join_prune_print(&bp[8], len - 8);		break;	case 4:		(void)printf(" RP-reachable");		if (vflag) {			TCHECK2(bp[22], 2);			(void)printf(" group %s",			ipaddr_string(&bp[8]));			if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)				(void)printf("/%s", ipaddr_string(&bp[12]));			(void)printf(" RP %s hold ", ipaddr_string(&bp[16]));			relts_print(EXTRACT_16BITS(&bp[22]));		}		break;	case 5:		(void)printf(" Assert");		TCHECK2(bp[16], sizeof(struct in_addr));		(void)printf(" for %s > %s", ipaddr_string(&bp[16]),		    ipaddr_string(&bp[8]));		if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)			(void)printf("/%s", ipaddr_string(&bp[12]));		TCHECK2(bp[24], 4);		(void)printf(" %s pref %d metric %d",		    (bp[20] & 0x80) ? "RP-tree" : "SPT",		EXTRACT_32BITS(&bp[20]) & 0x7fffffff,		EXTRACT_32BITS(&bp[24]));		break;	case 6:		(void)printf(" Graft");		if (vflag)			pimv1_join_prune_print(&bp[8], len - 8);		break;	case 7:		(void)printf(" Graft-ACK");		if (vflag)			pimv1_join_prune_print(&bp[8], len - 8);		break;	case 8:		(void)printf(" Mode");		break;	default:		(void)printf(" [type %d]", type);		break;	}	if ((bp[4] >> 4) != 1)		(void)printf(" [v%d]", bp[4] >> 4);	return;trunc:	(void)printf("[|pim]");	return;}/* * auto-RP is a cisco protocol, documented at * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt * * This implements version 1+, dated Sept 9, 1998. */voidcisco_autorp_print(register const u_char *bp, register u_int len){	int type;	int numrps;	int hold;	TCHECK(bp[0]);	(void)printf(" auto-rp ");	type = bp[0];	switch (type) {	case 0x11:		(void)printf("candidate-advert");		break;	case 0x12:		(void)printf("mapping");		break;	default:		(void)printf("type-0x%02x", type);		break;	}	TCHECK(bp[1]);	numrps = bp[1];	TCHECK2(bp[2], 2);	(void)printf(" Hold ");	hold = EXTRACT_16BITS(&bp[2]);	if (hold)		relts_print(EXTRACT_16BITS(&bp[2]));	else		printf("FOREVER");	/* Next 4 bytes are reserved. */	bp += 8; len -= 8;	/*XXX skip unless -v? */	/*	 * Rest of packet:	 * numrps entries of the form:	 * 32 bits: RP	 * 6 bits: reserved	 * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".	 * 8 bits: # of entries for this RP	 * each entry: 7 bits: reserved, 1 bit: negative,	 *	       8 bits: mask 32 bits: source	 * lather, rinse, repeat.	 */	while (numrps--) {		int nentries;		char s;		TCHECK2(bp[0], 4);		(void)printf(" RP %s", ipaddr_string(bp));		TCHECK(bp[4]);		switch (bp[4] & 0x3) {		case 0: printf(" PIMv?");			break;		case 1:	printf(" PIMv1");			break;		case 2:	printf(" PIMv2");			break;		case 3:	printf(" PIMv1+2");			break;		}		if (bp[4] & 0xfc)			(void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc);		TCHECK(bp[5]);		nentries = bp[5];		bp += 6; len -= 6;		s = ' ';		for (; nentries; nentries--) {			TCHECK2(bp[0], 6);			(void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "",			    ipaddr_string(&bp[2]), bp[1]);			if (bp[0] & 0xfe)				(void)printf("[rsvd=0x%02x]", bp[0] & 0xfe);			s = ',';			bp += 6; len -= 6;		}	}	return;trunc:	(void)printf("[|autorp]");	return;}voidpim_print(register const u_char *bp, register u_int len){	register const u_char *ep;	register struct pim *pim = (struct pim *)bp;	ep = (const u_char *)snapend;	if (bp >= ep)		return;#ifdef notyet			/* currently we see only version and type */	TCHECK(pim->pim_rsv);#endif	switch (PIM_VER(pim->pim_typever)) {	case 2:            if (!vflag) {                printf("PIMv%u, %s, length %u",                       PIM_VER(pim->pim_typever),                       tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)),                       len);                return;            } else {                printf("PIMv%u, length %u\n\t%s",                       PIM_VER(pim->pim_typever),                       len,                       tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)));                pimv2_print(bp, len);            }            break;	default:		printf("PIMv%u, length %u",                       PIM_VER(pim->pim_typever),                       len);		break;	}	return;}/* * PIMv2 uses encoded address representations. * * The last PIM-SM I-D before RFC2117 was published specified the * following representation for unicast addresses.  However, RFC2117 * specified no encoding for unicast addresses with the unicast * address length specified in the header.  Therefore, we have to * guess which encoding is being used (Cisco's PIMv2 implementation * uses the non-RFC encoding).  RFC2117 turns a previously "Reserved" * field into a 'unicast-address-length-in-bytes' field.  We guess * that it's the draft encoding if this reserved field is zero. * * RFC2362 goes back to the encoded format, and calls the addr length * field "reserved" again. * * The first byte is the address family, from: * *    0    Reserved *    1    IP (IP version 4) *    2    IP6 (IP version 6) *    3    NSAP *    4    HDLC (8-bit multidrop) *    5    BBN 1822 *    6    802 (includes all 802 media plus Ethernet "canonical format") *    7    E.163 *    8    E.164 (SMDS, Frame Relay, ATM) *    9    F.69 (Telex) *   10    X.121 (X.25, Frame Relay) *   11    IPX *   12    Appletalk *   13    Decnet IV *   14    Banyan Vines *   15    E.164 with NSAP format subaddress * * In addition, the second byte is an "Encoding".  0 is the default * encoding for the address family, and no other encodings are currently * specified. * */static int pimv2_addr_len;enum pimv2_addrtype {	pimv2_unicast, pimv2_group, pimv2_source};/*  0                   1                   2                   3 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Addr Family   | Encoding Type |     Unicast Address           | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++ *  0                   1                   2                   3 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Addr Family   | Encoding Type |   Reserved    |  Mask Len     | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |                Group multicast Address                        | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ *  0                   1                   2                   3 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Addr Family   | Encoding Type | Rsrvd   |S|W|R|  Mask Len     | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |                        Source Address                         | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */static intpimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent){	int af;	int len, hdrlen;	TCHECK(bp[0]);	if (pimv2_addr_len == 0) {		TCHECK(bp[1]);		switch (bp[0]) {		case 1:			af = AF_INET;			len = sizeof(struct in_addr);			break;#ifdef INET6		case 2:			af = AF_INET6;			len = sizeof(struct in6_addr);			break;#endif		default:			return -1;		}		if (bp[1] != 0)			return -1;		hdrlen = 2;	} else {		switch (pimv2_addr_len) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?