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

📄 ping6.c

📁 IPv6环境中的ping实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);	if ((fdmaskp = malloc(fdmasks)) == NULL)		err(1, "malloc");	seenalrm = seenint = 0;#ifdef SIGINFO	seeninfo = 0;#endif	for (;;) {		struct msghdr m;		struct cmsghdr *cm;		u_char buf[1024];		struct iovec iov[2];		/* signal handling */		if (seenalrm) {			retransmit();			seenalrm = 0;			continue;		}		if (seenint) {			onint(SIGINT);			seenint = 0;			continue;		}#ifdef SIGINFO		if (seeninfo) {			summary();			seeninfo = 0;			continue;		}#endif		if (options & F_FLOOD) {			(void)pinger();			timeout.tv_sec = 0;			timeout.tv_usec = 10000;			tv = &timeout;		} else			tv = NULL;		memset(fdmaskp, 0, fdmasks);		FD_SET(s, fdmaskp);		cc = select(s + 1, fdmaskp, NULL, NULL, tv);		if (cc < 0) {			if (errno != EINTR) {				warn("select");				sleep(1);			}			continue;		} else if (cc == 0)			continue;		m.msg_name = (caddr_t)&from;		m.msg_namelen = sizeof(from);		memset(&iov, 0, sizeof(iov));		iov[0].iov_base = (caddr_t)packet;		iov[0].iov_len = packlen;		m.msg_iov = iov;		m.msg_iovlen = 1;		cm = (struct cmsghdr *)buf;		m.msg_control = (caddr_t)buf;		m.msg_controllen = sizeof(buf);		cc = recvmsg(s, &m, 0);		if (cc < 0) {			if (errno != EINTR) {				warn("recvmsg");				sleep(1);			}			continue;		} else if (cc == 0) {			int mtu;			/*			 * receive control messages only. Process the			 * exceptions (currently the only possiblity is			 * a path MTU notification.)			 */			if ((mtu = get_pathmtu(&m)) > 0) {				if ((options & F_VERBOSE) != 0) {					printf("new path MTU (%d) is "					    "notified\n", mtu);				}			}			continue;		} else {			/*			 * an ICMPv6 message (probably an echoreply) arrived.			 */			pr_pack(packet, cc, &m);		}		if (npackets && nreceived >= npackets)			break;	}	summary();	exit(nreceived == 0);}voidonsignal(sig)	int sig;{	switch (sig) {	case SIGALRM:		seenalrm++;		break;	case SIGINT:		seenint++;		break;#ifdef SIGINFO	case SIGINFO:		seeninfo++;		break;#endif	}}/* * retransmit -- *	This routine transmits another ping6. */voidretransmit(){	struct itimerval itimer;	if (pinger() == 0)		return;	/*	 * If we're not transmitting any more packets, change the timer	 * to wait two round-trip times if we've received any packets or	 * ten seconds if we haven't.	 */#define	MAXWAIT		10	if (nreceived) {		itimer.it_value.tv_sec =  2 * tmax / 1000;		if (itimer.it_value.tv_sec == 0)			itimer.it_value.tv_sec = 1;	} else		itimer.it_value.tv_sec = MAXWAIT;	itimer.it_interval.tv_sec = 0;	itimer.it_interval.tv_usec = 0;	itimer.it_value.tv_usec = 0;	(void)signal(SIGALRM, onint);	(void)setitimer(ITIMER_REAL, &itimer, NULL);}/* * pinger -- *	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet * will be added on by the kernel.  The ID field is our UNIX process ID, * and the sequence number is an ascending integer.  The first 8 bytes * of the data portion are used to hold a UNIX "timeval" struct in VAX * byte-order, to compute the round-trip time. */size_tpingerlen(){	size_t l;	if (options & F_FQDN)		l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);	else if (options & F_FQDNOLD)		l = ICMP6_NIQLEN;	else if (options & F_NODEADDR)		l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);	else if (options & F_SUPTYPES)		l = ICMP6_NIQLEN;	else		l = ICMP6ECHOLEN + datalen;	return l;}intpinger(){	struct icmp6_hdr *icp;	struct iovec iov[2];	int i, cc;	struct icmp6_nodeinfo *nip;	int seq;	if (npackets && ntransmitted >= npackets)		return(-1);	/* no more transmission */	icp = (struct icmp6_hdr *)outpack;	nip = (struct icmp6_nodeinfo *)outpack;	memset(icp, 0, sizeof(*icp));	icp->icmp6_cksum = 0;	seq = ntransmitted++;	CLR(seq % mx_dup_ck);	if (options & F_FQDN) {		icp->icmp6_type = ICMP6_NI_QUERY;		icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;		nip->ni_qtype = htons(NI_QTYPE_FQDN);		nip->ni_flags = htons(0);		memcpy(nip->icmp6_ni_nonce, nonce,		    sizeof(nip->icmp6_ni_nonce));		*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);		memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,		    sizeof(dst.sin6_addr));		cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);		datalen = 0;	} else if (options & F_FQDNOLD) {		/* packet format in 03 draft - no Subject data on queries */		icp->icmp6_type = ICMP6_NI_QUERY;		icp->icmp6_code = 0;	/* code field is always 0 */		nip->ni_qtype = htons(NI_QTYPE_FQDN);		nip->ni_flags = htons(0);		memcpy(nip->icmp6_ni_nonce, nonce,		    sizeof(nip->icmp6_ni_nonce));		*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);		cc = ICMP6_NIQLEN;		datalen = 0;	} else if (options & F_NODEADDR) {		icp->icmp6_type = ICMP6_NI_QUERY;		icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;		nip->ni_qtype = htons(NI_QTYPE_NODEADDR);		nip->ni_flags = naflags;		memcpy(nip->icmp6_ni_nonce, nonce,		    sizeof(nip->icmp6_ni_nonce));		*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);		memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,		    sizeof(dst.sin6_addr));		cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);		datalen = 0;	} else if (options & F_SUPTYPES) {		icp->icmp6_type = ICMP6_NI_QUERY;		icp->icmp6_code = ICMP6_NI_SUBJ_FQDN;	/*empty*/		nip->ni_qtype = htons(NI_QTYPE_SUPTYPES);		/* we support compressed bitmap */		nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS;		memcpy(nip->icmp6_ni_nonce, nonce,		    sizeof(nip->icmp6_ni_nonce));		*(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);		cc = ICMP6_NIQLEN;		datalen = 0;	} else {		icp->icmp6_type = ICMP6_ECHO_REQUEST;		icp->icmp6_code = 0;		icp->icmp6_id = htons(ident);		icp->icmp6_seq = ntohs(seq);		if (timing) {			struct timeval tv;			struct tv32 *tv32;			(void)gettimeofday(&tv, NULL);			tv32 = (struct tv32 *)&outpack[ICMP6ECHOLEN];			tv32->tv32_sec = htonl(tv.tv_sec);			tv32->tv32_usec = htonl(tv.tv_usec);		}		cc = ICMP6ECHOLEN + datalen;	}#ifdef DIAGNOSTIC	if (pingerlen() != cc)		errx(1, "internal error; length mismatch");#endif	smsghdr.msg_name = (caddr_t)&dst;	smsghdr.msg_namelen = sizeof(dst);	memset(&iov, 0, sizeof(iov));	iov[0].iov_base = (caddr_t)outpack;	iov[0].iov_len = cc;	smsghdr.msg_iov = iov;	smsghdr.msg_iovlen = 1;	i = sendmsg(s, &smsghdr, 0);	if (i < 0 || i != cc)  {		if (i < 0)			warn("sendmsg");		(void)printf("ping6: wrote %s %d chars, ret=%d\n",		    hostname, cc, i);	}	if (!(options & F_QUIET) && options & F_FLOOD)		(void)write(STDOUT_FILENO, &DOT, 1);	return(0);}intmyechoreply(icp)	const struct icmp6_hdr *icp;{	if (ntohs(icp->icmp6_id) == ident)		return 1;	else		return 0;}intmynireply(nip)	const struct icmp6_nodeinfo *nip;{	if (memcmp(nip->icmp6_ni_nonce + sizeof(u_int16_t),	    nonce + sizeof(u_int16_t),	    sizeof(nonce) - sizeof(u_int16_t)) == 0)		return 1;	else		return 0;}char *dnsdecode(sp, ep, base, buf, bufsiz)	const u_char **sp;	const u_char *ep;	const u_char *base;	/*base for compressed name*/	u_char *buf;	size_t bufsiz;{	int i;	const u_char *cp;	char cresult[MAXDNAME + 1];	const u_char *comp;	int l;	cp = *sp;	*buf = '\0';	if (cp >= ep)		return NULL;	while (cp < ep) {		i = *cp;		if (i == 0 || cp != *sp) {			if (strlcat(buf, ".", bufsiz) >= bufsiz)				return NULL;	/*result overrun*/		}		if (i == 0)			break;		cp++;		if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {			/* DNS compression */			if (!base)				return NULL;			comp = base + (i & 0x3f);			if (dnsdecode(&comp, cp, base, cresult,			    sizeof(cresult)) == NULL)				return NULL;			if (strlcat(buf, cresult, bufsiz) >= bufsiz)				return NULL;	/*result overrun*/			break;		} else if ((i & 0x3f) == i) {			if (i > ep - cp)				return NULL;	/*source overrun*/			while (i-- > 0 && cp < ep) {				l = snprintf(cresult, sizeof(cresult),				    isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);				if (l >= sizeof(cresult) || l < 0)					return NULL;				if (strlcat(buf, cresult, bufsiz) >= bufsiz)					return NULL;	/*result overrun*/				cp++;			}		} else			return NULL;	/*invalid label*/	}	if (i != 0)		return NULL;	/*not terminated*/	cp++;	*sp = cp;	return buf;}/* * pr_pack -- *	Print out the packet, if it came from us.  This logic is necessary * because ALL readers of the ICMP socket get a copy of ALL ICMP packets * which arrive ('tis only fair).  This permits multiple copies of this * program to be run without having intermingled output (or statistics!). */voidpr_pack(buf, cc, mhdr)	u_char *buf;	int cc;	struct msghdr *mhdr;{#define safeputc(c)	printf((isprint((c)) ? "%c" : "\\%03o"), c)	struct icmp6_hdr *icp;	struct icmp6_nodeinfo *ni;	int i;	int hoplim;	struct sockaddr *from;	int fromlen;	u_char *cp = NULL, *dp, *end = buf + cc;	struct in6_pktinfo *pktinfo = NULL;	struct timeval tv, tp;	struct tv32 *tpp;	double triptime = 0;	int dupflag;	size_t off;	int oldfqdn;	u_int16_t seq;	char dnsname[MAXDNAME + 1];	(void)gettimeofday(&tv, NULL);	if (!mhdr || !mhdr->msg_name ||	    mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||	    ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) {		if (options & F_VERBOSE)			warnx("invalid peername");		return;	}	from = (struct sockaddr *)mhdr->msg_name;	fromlen = mhdr->msg_namelen;	if (cc < sizeof(struct icmp6_hdr)) {		if (options & F_VERBOSE)			warnx("packet too short (%d bytes) from %s", cc,			    pr_addr(from, fromlen));		return;	}	icp = (struct icmp6_hdr *)buf;	ni = (struct icmp6_nodeinfo *)buf;	off = 0;	if ((hoplim = get_hoplim(mhdr)) == -1) {		warnx("failed to get receiving hop limit");		return;	}	if ((pktinfo = get_rcvpktinfo(mhdr)) == NULL) {		warnx("failed to get receiving pakcet information");		return;	}	if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {		seq = ntohs(icp->icmp6_seq);		++nreceived;		if (timing) {			tpp = (struct tv32 *)(icp + 1);			tp.tv_sec = ntohl(tpp->tv32_sec);			tp.tv_usec = ntohl(tpp->tv32_usec);			tvsub(&tv, &tp);			triptime = ((double)tv.tv_sec) * 1000.0 +			    ((double)tv.tv_usec) / 1000.0;			tsum += triptime;#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)			tsumsq += triptime * triptime;#endif			if (triptime < tmin)				tmin = triptime;			if (triptime > tmax)				tmax = triptime;		}		if (TST(seq % mx_dup_ck)) {			++nrepeats;			--nreceived;			dupflag = 1;		} else {			SET(seq % mx_dup_ck);			dupflag = 0;		}		if (options & F_QUIET)			return;		if (options & F_FLOOD)			(void)write(STDOUT_FILENO, &BSPACE, 1);		else {			(void)printf("%d bytes from %s, icmp_seq=%u", cc,			    pr_addr(from, fromlen), seq);			(void)printf(" hlim=%d", hoplim);			if ((options & F_VERBOSE) != 0) {				struct sockaddr_in6 dstsa;				memset(&dstsa, 0, sizeof(dstsa));				dstsa.sin6_family = AF_INET6;#ifdef SIN6_LEN				dstsa.sin6_len = sizeof(dstsa);#endif				dstsa.sin6_scope_id = pktinfo->ipi6_ifindex;				dstsa.sin6_addr = pktinfo->ipi6_addr;				(void)printf(" dst=%s",				    pr_addr((struct sockaddr *)&dstsa,				    sizeof(dstsa)));			}			if (timing)				(void)printf(" time=%g ms", triptime);			if (dupflag)				(void)printf("(DUP!)");			/* check the data */			cp = buf + off + ICMP6ECHOLEN + ICMP6ECHOTMLEN;			dp = outpack + ICMP6ECHOLEN + ICMP6ECHOTMLEN;			for (i = 8; cp < end; ++i, ++cp, ++dp) {				if (*cp != *dp) {					(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp);					break;				}			}		}	} else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) {		seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce);		++nreceived;		if (TST(seq % mx_dup_ck)) {			++nrepeats;			--nreceived;			dupflag = 1;		} else {			SET(seq % mx_dup_ck);			dupflag = 0;		}		if (options & F_QUIET)			return;		(void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));		switch (ntohs(ni->ni_code)) {		case ICMP6_NI_SUCCESS:			break;		case ICMP6_NI_REFUSED:			printf("refused, type 0x%x", ntohs(ni->ni_type));

⌨️ 快捷键说明

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