⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping6.c

📁 IPv6环境中的ping实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			goto fqdnend;		case ICMP6_NI_UNKNOWN:			printf("unknown, type 0x%x", ntohs(ni->ni_type));			goto fqdnend;		default:			printf("unknown code 0x%x, type 0x%x",			    ntohs(ni->ni_code), ntohs(ni->ni_type));			goto fqdnend;		}		switch (ntohs(ni->ni_qtype)) {		case NI_QTYPE_NOOP:			printf("NodeInfo NOOP");			break;		case NI_QTYPE_SUPTYPES:			pr_suptypes(ni, end - (u_char *)ni);			break;		case NI_QTYPE_NODEADDR:			pr_nodeaddr(ni, end - (u_char *)ni);			break;		case NI_QTYPE_FQDN:		default:	/* XXX: for backward compatibility */			cp = (u_char *)ni + ICMP6_NIRLEN;			if (buf[off + ICMP6_NIRLEN] ==			    cc - off - ICMP6_NIRLEN - 1)				oldfqdn = 1;			else				oldfqdn = 0;			if (oldfqdn) {				cp++;	/* skip length */				while (cp < end) {					safeputc(*cp & 0xff);					cp++;				}			} else {				i = 0;				while (cp < end) {					if (dnsdecode((const u_char **)&cp, end,					    (const u_char *)(ni + 1), dnsname,					    sizeof(dnsname)) == NULL) {						printf("???");						break;					}					/*					 * name-lookup special handling for					 * truncated name					 */					if (cp + 1 <= end && !*cp &&					    strlen(dnsname) > 0) {						dnsname[strlen(dnsname) - 1] = '\0';						cp++;					}					printf("%s%s", i > 0 ? "," : "",					    dnsname);				}			}			if (options & F_VERBOSE) {				int32_t ttl;				int comma = 0;				(void)printf(" (");	/*)*/				switch (ni->ni_code) {				case ICMP6_NI_REFUSED:					(void)printf("refused");					comma++;					break;				case ICMP6_NI_UNKNOWN:					(void)printf("unknown qtype");					comma++;					break;				}				if ((end - (u_char *)ni) < ICMP6_NIRLEN) {					/* case of refusion, unknown */					/*(*/					putchar(')');					goto fqdnend;				}				ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]);				if (comma)					printf(",");				if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) {					(void)printf("TTL=%d:meaningless",					    (int)ttl);				} else {					if (ttl < 0) {						(void)printf("TTL=%d:invalid",						   ttl);					} else						(void)printf("TTL=%d", ttl);				}				comma++;				if (oldfqdn) {					if (comma)						printf(",");					printf("03 draft");					comma++;				} else {					cp = (u_char *)ni + ICMP6_NIRLEN;					if (cp == end) {						if (comma)							printf(",");						printf("no name");						comma++;					}				}				if (buf[off + ICMP6_NIRLEN] !=				    cc - off - ICMP6_NIRLEN - 1 && oldfqdn) {					if (comma)						printf(",");					(void)printf("invalid namelen:%d/%lu",					    buf[off + ICMP6_NIRLEN],					    (u_long)cc - off - ICMP6_NIRLEN - 1);					comma++;				}				/*(*/				putchar(')');			}		fqdnend:			;		}	} else {		/* We've got something other than an ECHOREPLY */		if (!(options & F_VERBOSE))			return;		(void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));		pr_icmph(icp, end);	}	if (!(options & F_FLOOD)) {		(void)putchar('\n');		if (options & F_VERBOSE)			pr_exthdrs(mhdr);		(void)fflush(stdout);	}#undef safeputc}voidpr_exthdrs(mhdr)	struct msghdr *mhdr;{	struct cmsghdr *cm;	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;	     cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {		if (cm->cmsg_level != IPPROTO_IPV6)			continue;		switch (cm->cmsg_type) {		case IPV6_HOPOPTS:			printf("  HbH Options: ");			pr_ip6opt(CMSG_DATA(cm));			break;		case IPV6_DSTOPTS:#ifdef IPV6_RTHDRDSTOPTS		case IPV6_RTHDRDSTOPTS:#endif			printf("  Dst Options: ");			pr_ip6opt(CMSG_DATA(cm));			break;		case IPV6_RTHDR:			printf("  Routing: ");			pr_rthdr(CMSG_DATA(cm));			break;		}	}}#ifdef USE_RFC2292BISvoidpr_ip6opt(void *extbuf){	struct ip6_hbh *ext;	int currentlen;	u_int8_t type;	size_t extlen, len;	void *databuf;	size_t offset;	u_int16_t value2;	u_int32_t value4;	ext = (struct ip6_hbh *)extbuf;	extlen = (ext->ip6h_len + 1) * 8;	printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,	    (unsigned int)ext->ip6h_len, (unsigned long)extlen);	currentlen = 0;	while (1) {		currentlen = inet6_opt_next(extbuf, extlen, currentlen,		    &type, &len, &databuf);		if (currentlen == -1)			break;		switch (type) {		/*		 * Note that inet6_opt_next automatically skips any padding		 * optins.		 */		case IP6OPT_JUMBO:			offset = 0;			offset = inet6_opt_get_val(databuf, offset,			    &value4, sizeof(value4));			printf("    Jumbo Payload Opt: Length %u\n",			    (u_int32_t)ntohl(value4));			break;		case IP6OPT_ROUTER_ALERT:			offset = 0;			offset = inet6_opt_get_val(databuf, offset,						   &value2, sizeof(value2));			printf("    Router Alert Opt: Type %u\n",			    ntohs(value2));			break;		default:			printf("    Received Opt %u len %lu\n",			    type, (unsigned long)len);			break;		}	}	return;}#else  /* !USE_RFC2292BIS *//* ARGSUSED */voidpr_ip6opt(void *extbuf){	putchar('\n');	return;}#endif /* USE_RFC2292BIS */#ifdef USE_RFC2292BISvoidpr_rthdr(void *extbuf){	struct in6_addr *in6;	char ntopbuf[INET6_ADDRSTRLEN];	struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;	int i, segments;	/* print fixed part of the header */	printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,	    rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);	if ((segments = inet6_rth_segments(extbuf)) >= 0)		printf("%d segments, ", segments);	else		printf("segments unknown, ");	printf("%d left\n", rh->ip6r_segleft);	for (i = 0; i < segments; i++) {		in6 = inet6_rth_getaddr(extbuf, i);		if (in6 == NULL)			printf("   [%d]<NULL>\n", i);		else {			if (!inet_ntop(AF_INET6, in6, ntopbuf,			    sizeof(ntopbuf)))				strncpy(ntopbuf, "?", sizeof(ntopbuf));			printf("   [%d]%s\n", i, ntopbuf);		}	}	return;}#else  /* !USE_RFC2292BIS *//* ARGSUSED */voidpr_rthdr(void *extbuf){	putchar('\n');	return;}#endif /* USE_RFC2292BIS */intpr_bitrange(v, soff, ii)	u_int32_t v;	int soff;	int ii;{	int off;	int i;	off = 0;	while (off < 32) {		/* shift till we have 0x01 */		if ((v & 0x01) == 0) {			if (ii > 1)				printf("-%u", soff + off - 1);			ii = 0;			switch (v & 0x0f) {			case 0x00:				v >>= 4;				off += 4;				continue;			case 0x08:				v >>= 3;				off += 3;				continue;			case 0x04: case 0x0c:				v >>= 2;				off += 2;				continue;			default:				v >>= 1;				off += 1;				continue;			}		}		/* we have 0x01 with us */		for (i = 0; i < 32 - off; i++) {			if ((v & (0x01 << i)) == 0)				break;		}		if (!ii)			printf(" %u", soff + off);		ii += i;		v >>= i; off += i;	}	return ii;}voidpr_suptypes(ni, nilen)	struct icmp6_nodeinfo *ni; /* ni->qtype must be SUPTYPES */	size_t nilen;{	size_t clen;	u_int32_t v;	const u_char *cp, *end;	u_int16_t cur;	struct cbit {		u_int16_t words;	/*32bit count*/		u_int16_t skip;	} cbit;#define MAXQTYPES	(1 << 16)	size_t off;	int b;	cp = (u_char *)(ni + 1);	end = ((u_char *)ni) + nilen;	cur = 0;	b = 0;	printf("NodeInfo Supported Qtypes");	if (options & F_VERBOSE) {		if (ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS)			printf(", compressed bitmap");		else			printf(", raw bitmap");	}	while (cp < end) {		clen = (size_t)(end - cp);		if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) == 0) {			if (clen == 0 || clen > MAXQTYPES / 8 ||			    clen % sizeof(v)) {				printf("???");				return;			}		} else {			if (clen < sizeof(cbit) || clen % sizeof(v))				return;			memcpy(&cbit, cp, sizeof(cbit));			if (sizeof(cbit) + ntohs(cbit.words) * sizeof(v) >			    clen)				return;			cp += sizeof(cbit);			clen = ntohs(cbit.words) * sizeof(v);			if (cur + clen * 8 + (u_long)ntohs(cbit.skip) * 32 >			    MAXQTYPES)				return;		}		for (off = 0; off < clen; off += sizeof(v)) {			memcpy(&v, cp + off, sizeof(v));			v = (u_int32_t)ntohl(v);			b = pr_bitrange(v, (int)(cur + off * 8), b);		}		/* flush the remaining bits */		b = pr_bitrange(0, (int)(cur + off * 8), b);		cp += clen;		cur += clen * 8;		if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) != 0)			cur += ntohs(cbit.skip) * 32;	}}voidpr_nodeaddr(ni, nilen)	struct icmp6_nodeinfo *ni; /* ni->qtype must be NODEADDR */	int nilen;{	u_char *cp = (u_char *)(ni + 1);	char ntop_buf[INET6_ADDRSTRLEN];	int withttl = 0;	nilen -= sizeof(struct icmp6_nodeinfo);	if (options & F_VERBOSE) {		switch (ni->ni_code) {		case ICMP6_NI_REFUSED:			(void)printf("refused");			break;		case ICMP6_NI_UNKNOWN:			(void)printf("unknown qtype");			break;		}		if (ni->ni_flags & NI_NODEADDR_FLAG_TRUNCATE)			(void)printf(" truncated");	}	putchar('\n');	if (nilen <= 0)		printf("  no address\n");	/*	 * In icmp-name-lookups 05 and later, TTL of each returned address	 * is contained in the resposne. We try to detect the version	 * by the length of the data, but note that the detection algorithm	 * is incomplete. We assume the latest draft by default.	 */	if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0)		withttl = 1;	while (nilen > 0) {		u_int32_t ttl;		if (withttl) {			/* XXX: alignment? */			ttl = (u_int32_t)ntohl(*(u_int32_t *)cp);			cp += sizeof(u_int32_t);			nilen -= sizeof(u_int32_t);		}		if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) ==		    NULL)			strncpy(ntop_buf, "?", sizeof(ntop_buf));		printf("  %s", ntop_buf);		if (withttl) {			if (ttl == 0xffffffff) {				/*				 * XXX: can this convention be applied to all				 * type of TTL (i.e. non-ND TTL)?				 */				printf("(TTL=infty)");			}			else				printf("(TTL=%u)", ttl);		}		putchar('\n');		nilen -= sizeof(struct in6_addr);		cp += sizeof(struct in6_addr);	}}intget_hoplim(mhdr)	struct msghdr *mhdr;{	struct cmsghdr *cm;	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;	     cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {		if (cm->cmsg_len == 0)			return(-1);		if (cm->cmsg_level == IPPROTO_IPV6 &&		    cm->cmsg_type == IPV6_HOPLIMIT &&		    cm->cmsg_len == CMSG_LEN(sizeof(int)))			return(*(int *)CMSG_DATA(cm));	}	return(-1);}struct in6_pktinfo *get_rcvpktinfo(mhdr)	struct msghdr *mhdr;{	struct cmsghdr *cm;	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;	     cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {		if (cm->cmsg_len == 0)			return(NULL);		if (cm->cmsg_level == IPPROTO_IPV6 &&		    cm->cmsg_type == IPV6_PKTINFO &&		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))			return((struct in6_pktinfo *)CMSG_DATA(cm));	}	return(NULL);}intget_pathmtu(mhdr)	struct msghdr *mhdr;{#ifdef IPV6_RECVPATHMTU	struct cmsghdr *cm;	struct ip6_mtuinfo *mtuctl = NULL;	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;	     cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {		if (cm->cmsg_len == 0)			return(0);		if (cm->cmsg_level == IPPROTO_IPV6 &&		    cm->cmsg_type == IPV6_PATHMTU &&		    cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) {			mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm);			/*			 * If the notified destination is different from			 * the one we are pinging, just ignore the info.			 * We check the scope ID only when both notified value			 * and our own value have non-0 values, because we may			 * have used the default scope zone ID for sending,			 * in which case the scope ID value is 0.			 */			if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr,						&dst.sin6_addr) ||

⌨️ 快捷键说明

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