print-icmp6.c

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

C
1,288
字号
/* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 *	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-icmp6.c,v 1.85.2.1 2008-02-05 19:36:58 guy Exp $";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef INET6#include <tcpdump-stdinc.h>#include <stdio.h>#include <string.h>#include "interface.h"#include "addrtoname.h"#include "extract.h"#include "ip6.h"#include "icmp6.h"#include "ipproto.h"#include "udp.h"#include "ah.h"static const char *get_rtpref(u_int);static const char *get_lifetime(u_int32_t);static void print_lladdr(const u_char *, size_t);static void icmp6_opt_print(const u_char *, int);static void mld6_print(const u_char *);static void mldv2_report_print(const u_char *, u_int);static void mldv2_query_print(const u_char *, u_int);static struct udphdr *get_upperlayer(u_char *, u_int *);static void dnsname_print(const u_char *, const u_char *);static void icmp6_nodeinfo_print(u_int, const u_char *, const u_char *);static void icmp6_rrenum_print(const u_char *, const u_char *);#ifndef abs#define abs(a)	((0 < (a)) ? (a) : -(a))#endifstatic struct tok icmp6_type_values[] = {    { ICMP6_DST_UNREACH, "destination unreachable"},    { ICMP6_PACKET_TOO_BIG, "packet too big"},    { ICMP6_TIME_EXCEEDED, "time exceeded in-transit"},    { ICMP6_PARAM_PROB, "parameter problem"},    { ICMP6_ECHO_REQUEST, "echo request"},    { ICMP6_ECHO_REPLY, "echo reply"},    { MLD6_LISTENER_QUERY, "multicast listener query"},    { MLD6_LISTENER_REPORT, "multicast listener report"},    { MLD6_LISTENER_DONE, "multicast listener done"},    { ND_ROUTER_SOLICIT, "router solicitation"},    { ND_ROUTER_ADVERT, "router advertisement"},    { ND_NEIGHBOR_SOLICIT, "neighbor solicitation"},    { ND_NEIGHBOR_ADVERT, "neighbor advertisement"},    { ND_REDIRECT, "redirect"},    { ICMP6_ROUTER_RENUMBERING, "router renumbering"},    { IND_SOLICIT, "inverse neighbor solicitation"},    { IND_ADVERT, "inverse neighbor advertisement"},    { MLDV2_LISTENER_REPORT, "multicast listener report v2"},    { ICMP6_HADISCOV_REQUEST, "ha discovery request"},    { ICMP6_HADISCOV_REPLY, "ha discovery reply"},    { ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"},    { ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"},    { ICMP6_WRUREQUEST, "who-are-you request"},    { ICMP6_WRUREPLY, "who-are-you reply"},    { ICMP6_NI_QUERY, "node information query"},    { ICMP6_NI_REPLY, "node information reply"},    { MLD6_MTRACE, "mtrace message"},    { MLD6_MTRACE_RESP, "mtrace response"},    { 0,	NULL }};static struct tok icmp6_dst_unreach_code_values[] = {    { ICMP6_DST_UNREACH_NOROUTE, "unreachable route" },    { ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"},    { ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"},    { ICMP6_DST_UNREACH_ADDR, "unreachable address"},    { ICMP6_DST_UNREACH_NOPORT, "unreachable port"},    { 0,	NULL }};static struct tok icmp6_opt_pi_flag_values[] = {    { ND_OPT_PI_FLAG_ONLINK, "onlink" },    { ND_OPT_PI_FLAG_AUTO, "auto" },    { ND_OPT_PI_FLAG_ROUTER, "router" },    { 0,	NULL }};static struct tok icmp6_opt_ra_flag_values[] = {    { ND_RA_FLAG_MANAGED, "managed" },    { ND_RA_FLAG_OTHER, "other stateful"},    { ND_RA_FLAG_HOME_AGENT, "home agent"},    { 0,	NULL }};static struct tok icmp6_nd_na_flag_values[] = {    { ND_NA_FLAG_ROUTER, "router" },    { ND_NA_FLAG_SOLICITED, "solicited" },    { ND_NA_FLAG_OVERRIDE, "override" },    { 0,	NULL }};static struct tok icmp6_opt_values[] = {   { ND_OPT_SOURCE_LINKADDR, "source link-address"},   { ND_OPT_TARGET_LINKADDR, "destination link-address"},   { ND_OPT_PREFIX_INFORMATION, "prefix info"},   { ND_OPT_REDIRECTED_HEADER, "redirected header"},   { ND_OPT_MTU, "mtu"},   { ND_OPT_ADVINTERVAL, "advertisement interval"},   { ND_OPT_HOMEAGENT_INFO, "homeagent information"},   { ND_OPT_ROUTE_INFO, "route info"},   { 0,	NULL }};/* mldv2 report types */static struct tok mldv2report2str[] = {	{ 1,	"is_in" },	{ 2,	"is_ex" },	{ 3,	"to_in" },	{ 4,	"to_ex" },	{ 5,	"allow" },	{ 6,	"block" },	{ 0,	NULL }};static const char *get_rtpref(u_int v){	static const char *rtpref_str[] = {		"medium",		/* 00 */		"high",			/* 01 */		"rsv",			/* 10 */		"low"			/* 11 */	};	return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff];}static const char *get_lifetime(u_int32_t v){	static char buf[20];	if (v == (u_int32_t)~0UL)		return "infinity";	else {		snprintf(buf, sizeof(buf), "%u", v);		return buf;	}}static voidprint_lladdr(const u_int8_t *p, size_t l){	const u_int8_t *ep, *q;	q = p;	ep = p + l;	while (l > 0 && q < ep) {		if (q > p)			printf(":");		printf("%02x", *q++);		l--;	}}static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp,	u_int len){	size_t i;	register const u_int16_t *sp;	u_int32_t sum;	union {		struct {			struct in6_addr ph_src;			struct in6_addr ph_dst;			u_int32_t	ph_len;			u_int8_t	ph_zero[3];			u_int8_t	ph_nxt;		} ph;		u_int16_t pa[20];	} phu;	/* pseudo-header */	memset(&phu, 0, sizeof(phu));	phu.ph.ph_src = ip6->ip6_src;	phu.ph.ph_dst = ip6->ip6_dst;	phu.ph.ph_len = htonl(len);	phu.ph.ph_nxt = IPPROTO_ICMPV6;	sum = 0;	for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)		sum += phu.pa[i];	sp = (const u_int16_t *)icp;	for (i = 0; i < (len & ~1); i += 2)		sum += *sp++;	if (len & 1)		sum += htons((*(const u_int8_t *)sp) << 8);	while (sum > 0xffff)		sum = (sum & 0xffff) + (sum >> 16);	sum = ~sum & 0xffff;	return (sum);}voidicmp6_print(const u_char *bp, u_int length, const u_char *bp2, int fragmented){	const struct icmp6_hdr *dp;	const struct ip6_hdr *ip;	const struct ip6_hdr *oip;	const struct udphdr *ouh;	int dport;	const u_char *ep;	u_int prot;	dp = (struct icmp6_hdr *)bp;	ip = (struct ip6_hdr *)bp2;	oip = (struct ip6_hdr *)(dp + 1);	/* 'ep' points to the end of available data. */	ep = snapend;	TCHECK(dp->icmp6_cksum);	if (vflag && !fragmented) {		int sum = dp->icmp6_cksum;		if (TTEST2(bp[0], length)) {			sum = icmp6_cksum(ip, dp, length);			if (sum != 0)				(void)printf("[bad icmp6 cksum %x!] ", sum);			else				(void)printf("[icmp6 sum ok] ");		}	}        printf("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type));        /* display cosmetics: print the packet length for printer that use the vflag now */        if (vflag && (dp->icmp6_type ==                      ND_ROUTER_SOLICIT ||                      ND_ROUTER_ADVERT ||                      ND_NEIGHBOR_ADVERT ||                      ND_NEIGHBOR_SOLICIT ||                      ND_REDIRECT ||                      ICMP6_HADISCOV_REPLY ||                      ICMP6_MOBILEPREFIX_ADVERT ))            printf(", length %u", length);                      	switch (dp->icmp6_type) {	case ICMP6_DST_UNREACH:		TCHECK(oip->ip6_dst);                printf(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",dp->icmp6_code));		switch (dp->icmp6_code) {		case ICMP6_DST_UNREACH_NOROUTE: /* fall through */		case ICMP6_DST_UNREACH_ADMIN:		case ICMP6_DST_UNREACH_ADDR:                        printf(" %s",ip6addr_string(&oip->ip6_dst));                        break;		case ICMP6_DST_UNREACH_BEYONDSCOPE:			printf(" %s, source address %s",			       ip6addr_string(&oip->ip6_dst),			       ip6addr_string(&oip->ip6_src));			break;		case ICMP6_DST_UNREACH_NOPORT:			if ((ouh = get_upperlayer((u_char *)oip, &prot))			    == NULL)				goto trunc;			dport = EXTRACT_16BITS(&ouh->uh_dport);			switch (prot) {			case IPPROTO_TCP:				printf(", %s tcp port %s",					ip6addr_string(&oip->ip6_dst),					tcpport_string(dport));				break;			case IPPROTO_UDP:				printf(", %s udp port %s",					ip6addr_string(&oip->ip6_dst),					udpport_string(dport));				break;			default:				printf(", %s protocol %d port %d unreachable",					ip6addr_string(&oip->ip6_dst),					oip->ip6_nxt, dport);				break;			}			break;		default:                    if (vflag <= 1) {                            print_unknown_data(bp,"\n\t",length);                            return;                    }                    break;		}		break;	case ICMP6_PACKET_TOO_BIG:		TCHECK(dp->icmp6_mtu);		printf(", mtu %u", EXTRACT_32BITS(&dp->icmp6_mtu));		break;	case ICMP6_TIME_EXCEEDED:		TCHECK(oip->ip6_dst);		switch (dp->icmp6_code) {		case ICMP6_TIME_EXCEED_TRANSIT:			printf(" for %s",				ip6addr_string(&oip->ip6_dst));			break;		case ICMP6_TIME_EXCEED_REASSEMBLY:			printf(" (reassembly)");			break;		default:			printf(", unknown code (%u)", dp->icmp6_code);			break;		}		break;	case ICMP6_PARAM_PROB:		TCHECK(oip->ip6_dst);		switch (dp->icmp6_code) {		case ICMP6_PARAMPROB_HEADER:			printf(", errorneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr));			break;		case ICMP6_PARAMPROB_NEXTHEADER:			printf(", next header - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr));			break;		case ICMP6_PARAMPROB_OPTION:			printf(", option - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr));			break;		default:			printf(", code-#%d",			       dp->icmp6_code);			break;		}		break;	case ICMP6_ECHO_REQUEST:	case ICMP6_ECHO_REPLY:		TCHECK(dp->icmp6_seq);		printf(", seq %u", EXTRACT_16BITS(&dp->icmp6_seq));		break;	case ICMP6_MEMBERSHIP_QUERY:		if (length == MLD_MINLEN) {			mld6_print((const u_char *)dp);		} else if (length >= MLDV2_MINLEN) {			printf("v2 ");			mldv2_query_print((const u_char *)dp, length);		} else {			printf(" unknown-version (len %u) ", length);		}		break;	case ICMP6_MEMBERSHIP_REPORT:		mld6_print((const u_char *)dp);		break;	case ICMP6_MEMBERSHIP_REDUCTION:		mld6_print((const u_char *)dp);		break;	case ND_ROUTER_SOLICIT:#define RTSOLLEN 8		if (vflag) {			icmp6_opt_print((const u_char *)dp + RTSOLLEN,					length - RTSOLLEN);		}		break;	case ND_ROUTER_ADVERT:#define RTADVLEN 16		if (vflag) {			struct nd_router_advert *p;			p = (struct nd_router_advert *)dp;			TCHECK(p->nd_ra_retransmit);			printf("\n\thop limit %u, Flags [%s]" \                               ", pref %s, router lifetime %us, reachable time %us, retrans time %us",                               (u_int)p->nd_ra_curhoplimit,                               bittok2str(icmp6_opt_ra_flag_values,"none",(p->nd_ra_flags_reserved)),                               get_rtpref(p->nd_ra_flags_reserved),                               EXTRACT_16BITS(&p->nd_ra_router_lifetime),                               EXTRACT_32BITS(&p->nd_ra_reachable),                               EXTRACT_32BITS(&p->nd_ra_retransmit));			icmp6_opt_print((const u_char *)dp + RTADVLEN,					length - RTADVLEN);		}		break;	case ND_NEIGHBOR_SOLICIT:	    {		struct nd_neighbor_solicit *p;		p = (struct nd_neighbor_solicit *)dp;		TCHECK(p->nd_ns_target);		printf(", who has %s", ip6addr_string(&p->nd_ns_target));		if (vflag) {#define NDSOLLEN 24			icmp6_opt_print((const u_char *)dp + NDSOLLEN,					length - NDSOLLEN);		}	    }		break;	case ND_NEIGHBOR_ADVERT:	    {		struct nd_neighbor_advert *p;		p = (struct nd_neighbor_advert *)dp;		TCHECK(p->nd_na_target);

⌨️ 快捷键说明

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