print-icmp6.c

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

C
1,288
字号
		printf(", tgt is %s",			ip6addr_string(&p->nd_na_target));		if (vflag) {                        printf(", Flags [%s]",                               bittok2str(icmp6_nd_na_flag_values,                                          "none",                                          EXTRACT_32BITS(&p->nd_na_flags_reserved)));#define NDADVLEN 24			icmp6_opt_print((const u_char *)dp + NDADVLEN,					length - NDADVLEN);#undef NDADVLEN		}	    }		break;	case ND_REDIRECT:#define RDR(i) ((struct nd_redirect *)(i))		TCHECK(RDR(dp)->nd_rd_dst);		printf(", %s", getname6((const u_char *)&RDR(dp)->nd_rd_dst));		TCHECK(RDR(dp)->nd_rd_target);		printf(" to %s",		    getname6((const u_char*)&RDR(dp)->nd_rd_target));#define REDIRECTLEN 40		if (vflag) {			icmp6_opt_print((const u_char *)dp + REDIRECTLEN,					length - REDIRECTLEN);		}		break;#undef REDIRECTLEN#undef RDR	case ICMP6_ROUTER_RENUMBERING:		icmp6_rrenum_print(bp, ep);		break;	case ICMP6_NI_QUERY:	case ICMP6_NI_REPLY:		icmp6_nodeinfo_print(length, bp, ep);		break;	case IND_SOLICIT:	case IND_ADVERT:		break;	case ICMP6_V2_MEMBERSHIP_REPORT:		mldv2_report_print((const u_char *) dp, length);		break;	case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */	case ICMP6_HADISCOV_REQUEST:                TCHECK(dp->icmp6_data16[0]);                printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]));                break;	case ICMP6_HADISCOV_REPLY:		if (vflag) {			struct in6_addr *in6;			u_char *cp;			TCHECK(dp->icmp6_data16[0]);			printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]));			cp = (u_char *)dp + length;			in6 = (struct in6_addr *)(dp + 1);			for (; (u_char *)in6 < cp; in6++) {				TCHECK(*in6);				printf(", %s", ip6addr_string(in6));			}		}		break;	case ICMP6_MOBILEPREFIX_ADVERT:		if (vflag) {			TCHECK(dp->icmp6_data16[0]);			printf(", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]));			if (dp->icmp6_data16[1] & 0xc0)				printf(" ");			if (dp->icmp6_data16[1] & 0x80)				printf("M");			if (dp->icmp6_data16[1] & 0x40)				printf("O");#define MPADVLEN 8			icmp6_opt_print((const u_char *)dp + MPADVLEN,					length - MPADVLEN);		}		break;	default:                printf(", length %u", length);                if (vflag <= 1)                    print_unknown_data(bp,"\n\t", length);                return;        }        if (!vflag)            printf(", length %u", length); 	return;trunc:	fputs("[|icmp6]", stdout);}static struct udphdr *get_upperlayer(u_char *bp, u_int *prot){	const u_char *ep;	struct ip6_hdr *ip6 = (struct ip6_hdr *)bp;	struct udphdr *uh;	struct ip6_hbh *hbh;	struct ip6_frag *fragh;	struct ah *ah;	u_int nh;	int hlen;	/* 'ep' points to the end of available data. */	ep = snapend;	if (!TTEST(ip6->ip6_nxt))		return NULL;	nh = ip6->ip6_nxt;	hlen = sizeof(struct ip6_hdr);	while (bp < ep) {		bp += hlen;		switch(nh) {		case IPPROTO_UDP:		case IPPROTO_TCP:			uh = (struct udphdr *)bp;			if (TTEST(uh->uh_dport)) {				*prot = nh;				return(uh);			}			else				return(NULL);			/* NOTREACHED */		case IPPROTO_HOPOPTS:		case IPPROTO_DSTOPTS:		case IPPROTO_ROUTING:			hbh = (struct ip6_hbh *)bp;			if (!TTEST(hbh->ip6h_len))				return(NULL);			nh = hbh->ip6h_nxt;			hlen = (hbh->ip6h_len + 1) << 3;			break;		case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */			fragh = (struct ip6_frag *)bp;			if (!TTEST(fragh->ip6f_offlg))				return(NULL);			/* fragments with non-zero offset are meaningless */			if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0)				return(NULL);			nh = fragh->ip6f_nxt;			hlen = sizeof(struct ip6_frag);			break;		case IPPROTO_AH:			ah = (struct ah *)bp;			if (!TTEST(ah->ah_len))				return(NULL);			nh = ah->ah_nxt;			hlen = (ah->ah_len + 2) << 2;			break;		default:	/* unknown or undecodable header */			*prot = nh; /* meaningless, but set here anyway */			return(NULL);		}	}	return(NULL);		/* should be notreached, though */}static voidicmp6_opt_print(const u_char *bp, int resid){	const struct nd_opt_hdr *op;	const struct nd_opt_hdr *opl;	/* why there's no struct? */	const struct nd_opt_prefix_info *opp;	const struct icmp6_opts_redirect *opr;	const struct nd_opt_mtu *opm;	const struct nd_opt_advinterval *opa;	const struct nd_opt_homeagent_info *oph;	const struct nd_opt_route_info *opri;	const u_char *cp, *ep;	struct in6_addr in6, *in6p;	size_t l;#define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return	cp = bp;	/* 'ep' points to the end of available data. */	ep = snapend;	while (cp < ep) {		op = (struct nd_opt_hdr *)cp;		ECHECK(op->nd_opt_len);		if (resid <= 0)			return;		if (op->nd_opt_len == 0)			goto trunc;		if (cp + (op->nd_opt_len << 3) > ep)			goto trunc;                printf("\n\t  %s option (%u), length %u (%u): ",                       tok2str(icmp6_opt_values, "unknown", op->nd_opt_type),                       op->nd_opt_type,                       op->nd_opt_len << 3,                       op->nd_opt_len);		switch (op->nd_opt_type) {		case ND_OPT_SOURCE_LINKADDR:			opl = (struct nd_opt_hdr *)op;			l = (op->nd_opt_len << 3) - 2;			print_lladdr(cp + 2, l);			break;		case ND_OPT_TARGET_LINKADDR:			opl = (struct nd_opt_hdr *)op;			l = (op->nd_opt_len << 3) - 2;			print_lladdr(cp + 2, l);			break;		case ND_OPT_PREFIX_INFORMATION:			opp = (struct nd_opt_prefix_info *)op;			TCHECK(opp->nd_opt_pi_prefix);                        printf("%s/%u%s, Flags [%s], valid time %ss",                               ip6addr_string(&opp->nd_opt_pi_prefix),                               opp->nd_opt_pi_prefix_len,                               (op->nd_opt_len != 4) ? "badlen" : "",                               bittok2str(icmp6_opt_pi_flag_values, "none", opp->nd_opt_pi_flags_reserved),                               get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time)));                        printf(", pref. time %ss", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time)));			break;		case ND_OPT_REDIRECTED_HEADER:			opr = (struct icmp6_opts_redirect *)op;                        print_unknown_data(bp,"\n\t    ",op->nd_opt_len<<3);			/* xxx */			break;		case ND_OPT_MTU:			opm = (struct nd_opt_mtu *)op;			TCHECK(opm->nd_opt_mtu_mtu);			printf(" %u%s",                               EXTRACT_32BITS(&opm->nd_opt_mtu_mtu),                               (op->nd_opt_len != 1) ? "bad option length" : "" );                        break;		case ND_OPT_ADVINTERVAL:			opa = (struct nd_opt_advinterval *)op;			TCHECK(opa->nd_opt_adv_interval);			printf(" %us", EXTRACT_32BITS(&opa->nd_opt_adv_interval));			break;		case ND_OPT_HOMEAGENT_INFO:			oph = (struct nd_opt_homeagent_info *)op;			TCHECK(oph->nd_opt_hai_lifetime);			printf(" preference %u, lifetime %u",                               EXTRACT_16BITS(&oph->nd_opt_hai_preference),                               EXTRACT_16BITS(&oph->nd_opt_hai_lifetime));			break;		case ND_OPT_ROUTE_INFO:			opri = (struct nd_opt_route_info *)op;			TCHECK(opri->nd_opt_rti_lifetime);			memset(&in6, 0, sizeof(in6));			in6p = (struct in6_addr *)(opri + 1);			switch (op->nd_opt_len) {			case 1:				break;			case 2:				TCHECK2(*in6p, 8);				memcpy(&in6, opri + 1, 8);				break;			case 3:				TCHECK(*in6p);				memcpy(&in6, opri + 1, sizeof(in6));				break;			default:				goto trunc;			}			printf(" %s/%u", ip6addr_string(&in6),			    opri->nd_opt_rti_prefixlen);			printf(", pref=%s", get_rtpref(opri->nd_opt_rti_flags));			printf(", lifetime=%s",			    get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime)));			break;		default:                        if (vflag <= 1) {                            print_unknown_data(cp+2,"\n\t  ", (op->nd_opt_len << 3) - 2); /* skip option header */                            return;                        }                        break;		}                /* do we want to see an additional hexdump ? */                if (vflag> 1)                    print_unknown_data(cp+2,"\n\t    ", (op->nd_opt_len << 3) - 2); /* skip option header */		cp += op->nd_opt_len << 3;		resid -= op->nd_opt_len << 3;	}	return; trunc:	fputs("[ndp opt]", stdout);	return;#undef ECHECK}static voidmld6_print(const u_char *bp){	struct mld6_hdr *mp = (struct mld6_hdr *)bp;	const u_char *ep;	/* 'ep' points to the end of available data. */	ep = snapend;	if ((u_char *)mp + sizeof(*mp) > ep)		return;	printf("max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay));	printf("addr: %s", ip6addr_string(&mp->mld6_addr));}static voidmldv2_report_print(const u_char *bp, u_int len){    struct icmp6_hdr *icp = (struct icmp6_hdr *) bp;    u_int group, nsrcs, ngroups;    u_int i, j;    /* Minimum len is 8 */    if (len < 8) {	printf(" [invalid len %d]", len);	return;    }    TCHECK(icp->icmp6_data16[1]);    ngroups = ntohs(icp->icmp6_data16[1]);    printf(", %d group record(s)", ngroups);    if (vflag > 0) {	/* Print the group records */	group = 8;        for (i = 0; i < ngroups; i++) {	    /* type(1) + auxlen(1) + numsrc(2) + grp(16) */	    if (len < group + 20) {		printf(" [invalid number of groups]");		return;	    }            TCHECK2(bp[group + 4], sizeof(struct in6_addr));            printf(" [gaddr %s", ip6addr_string(&bp[group + 4]));	    printf(" %s", tok2str(mldv2report2str, " [v2-report-#%d]",								bp[group]));            nsrcs = (bp[group + 2] << 8) + bp[group + 3];	    /* Check the number of sources and print them */	    if (len < group + 20 + (nsrcs * sizeof(struct in6_addr))) {		printf(" [invalid number of sources %d]", nsrcs);		return;	    }            if (vflag == 1)                printf(", %d source(s)", nsrcs);            else {		/* Print the sources */                (void)printf(" {");                for (j = 0; j < nsrcs; j++) {                    TCHECK2(bp[group + 20 + j * sizeof(struct in6_addr)],                            sizeof(struct in6_addr));		    printf(" %s", ip6addr_string(&bp[group + 20 + j * sizeof(struct in6_addr)]));		}                (void)printf(" }");            }	    /* Next group record */            group += 20 + nsrcs * sizeof(struct in6_addr);	    printf("]");        }    }    return;trunc:    (void)printf("[|icmp6]");    return;}static voidmldv2_query_print(const u_char *bp, u_int len){    struct icmp6_hdr *icp = (struct icmp6_hdr *) bp;    u_int mrc;    int mrt, qqi;    u_int nsrcs;    register u_int i;    /* Minimum len is 28 */    if (len < 28) {	printf(" [invalid len %d]", len);	return;    }    TCHECK(icp->icmp6_data16[0]);    mrc = ntohs(icp->icmp6_data16[0]);    if (mrc < 32768) {	mrt = mrc;    } else {        mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3);    }    if (vflag) {	(void)printf(" [max resp delay=%d]", mrt);    }    TCHECK2(bp[8], sizeof(struct in6_addr));    printf(" [gaddr %s", ip6addr_string(&bp[8]));    if (vflag) {        TCHECK(bp[25]);	if (bp[24] & 0x08) {		printf(" sflag");	}	if (bp[24] & 0x07) {		printf(" robustness=%d", bp[24] & 0x07);	}	if (bp[25] < 128) {		qqi = bp[25];	} else {		qqi = ((bp[25] & 0x0f) | 0x10) << (((bp[25] & 0x70) >> 4) + 3);	}	printf(" qqi=%d", qqi);    }    TCHECK2(bp[26], 2);    nsrcs = ntohs(*(u_short *)&bp[26]);    if (nsrcs > 0) {	if (len < 28 + nsrcs * sizeof(struct in6_addr))	    printf(" [invalid number of sources]");	else if (vflag > 1) {	    printf(" {");	    for (i = 0; i < nsrcs; i++) {		TCHECK2(bp[28 + i * sizeof(struct in6_addr)],                        sizeof(struct in6_addr));		printf(" %s", ip6addr_string(&bp[28 + i * sizeof(struct in6_addr)]));	    }	    printf(" }");	} else	    printf(", %d source(s)", nsrcs);    }    printf("]");    return;

⌨️ 快捷键说明

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