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

📄 ping6.c

📁 IPv6环境中的ping实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			options |= F_FQDN;			break;		case 'W':			options &= ~F_NOUSERDATA;			options |= F_FQDNOLD;			break;#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC		case 'P':			options |= F_POLICY;			if (!strncmp("in", optarg, 2)) {				if ((policy_in = strdup(optarg)) == NULL)					errx(1, "strdup");			} else if (!strncmp("out", optarg, 3)) {				if ((policy_out = strdup(optarg)) == NULL)					errx(1, "strdup");			} else				errx(1, "invalid security policy");			break;#else		case 'A':			options |= F_AUTHHDR;			break;		case 'E':			options |= F_ENCRYPT;			break;#endif /*IPSEC_POLICY_IPSEC*/#endif /*IPSEC*/		default:			usage();			/*NOTREACHED*/		}	}	argc -= optind;	argv += optind;	if (argc < 1) {		usage();		/*NOTREACHED*/	}	if (argc > 1) {#ifdef IPV6_RECVRTHDR	/* 2292bis */		rthlen = CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0,		    argc - 1));#else  /* RFC2292 */		rthlen = inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1);#endif		if (rthlen == 0) {			errx(1, "too many intermediate hops");			/*NOTREACHED*/		}		ip6optlen += rthlen;	}	if (options & F_NIGROUP) {		target = nigroup(argv[argc - 1]);		if (target == NULL) {			usage();			/*NOTREACHED*/		}	} else		target = argv[argc - 1];	/* getaddrinfo */	memset(&hints, 0, sizeof(struct addrinfo));	hints.ai_flags = AI_CANONNAME;	hints.ai_family = AF_INET6;	hints.ai_socktype = SOCK_RAW;	hints.ai_protocol = IPPROTO_ICMPV6;	ret_ga = getaddrinfo(target, NULL, &hints, &res);	if (ret_ga)		errx(1, "%s", gai_strerror(ret_ga));	if (res->ai_canonname)		hostname = res->ai_canonname;	else		hostname = target;	if (!res->ai_addr)		errx(1, "getaddrinfo failed");	(void)memcpy(&dst, res->ai_addr, res->ai_addrlen);	if ((s = socket(res->ai_family, res->ai_socktype,	    res->ai_protocol)) < 0)		err(1, "socket");	/* set the source address if specified. */	if ((options & F_SRCADDR) &&	    bind(s, (struct sockaddr *)&src, srclen) != 0) {		err(1, "bind");	}	/* set the gateway (next hop) if specified */	if (gateway) {		struct addrinfo ghints, *gres;		int error;		memset(&ghints, 0, sizeof(ghints));		ghints.ai_family = AF_INET6;		ghints.ai_socktype = SOCK_RAW;		ghints.ai_protocol = IPPROTO_ICMPV6;		error = getaddrinfo(gateway, NULL, &hints, &gres);		if (error) {			errx(1, "getaddrinfo for the gateway %s: %s",			     gateway, gai_strerror(error));		}		if (gres->ai_next && (options & F_VERBOSE))			warnx("gateway resolves to multiple addresses");		if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP,			       gres->ai_addr, gres->ai_addrlen)) {			err(1, "setsockopt(IPV6_NEXTHOP)");		}		freeaddrinfo(gres);	}	/*	 * let the kerel pass extension headers of incoming packets,	 * for privileged socket options	 */	if ((options & F_VERBOSE) != 0) {		int opton = 1;#ifdef IPV6_RECVHOPOPTS		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_RECVHOPOPTS)");#else  /* old adv. API */		if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_HOPOPTS)");#endif#ifdef IPV6_RECVDSTOPTS		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_RECVDSTOPTS)");#else  /* old adv. API */		if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_DSTOPTS)");#endif#ifdef IPV6_RECVRTHDRDSTOPTS		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");#endif	}	/* revoke root privilege */	seteuid(getuid());	setuid(getuid());	if ((options & F_FLOOD) && (options & F_INTERVAL))		errx(1, "-f and -i incompatible options");	if ((options & F_NOUSERDATA) == 0) {		if (datalen >= sizeof(struct tv32)) {			/* we can time transfer */			timing = 1;		} else			timing = 0;		/* in F_VERBOSE case, we may get non-echoreply packets*/		if (options & F_VERBOSE)			packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;		else			packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;	} else {		/* suppress timing for node information query */		timing = 0;		datalen = 2048;		packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;	}	if (!(packet = (u_char *)malloc((u_int)packlen)))		err(1, "Unable to allocate packet");	if (!(options & F_PINGFILLED))		for (i = ICMP6ECHOLEN; i < packlen; ++i)			*datap++ = i;	ident = getpid() & 0xFFFF;#ifndef __OpenBSD__	gettimeofday(&timeout, NULL);	srand((unsigned int)(timeout.tv_sec ^ timeout.tv_usec ^ (long)ident));	memset(nonce, 0, sizeof(nonce));	for (i = 0; i < sizeof(nonce); i += sizeof(int))		*((int *)&nonce[i]) = rand();#else	memset(nonce, 0, sizeof(nonce));	for (i = 0; i < sizeof(nonce); i += sizeof(u_int32_t))		*((u_int32_t *)&nonce[i]) = arc4random();#endif	hold = 1;	if (options & F_SO_DEBUG)		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,		    sizeof(hold));	optval = IPV6_DEFHLIM;	if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))		if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,		    &optval, sizeof(optval)) == -1)			err(1, "IPV6_MULTICAST_HOPS");#ifdef IPV6_USE_MIN_MTU	if (mflag != 1) {		optval = mflag > 1 ? 0 : 1;		if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,		    &optval, sizeof(optval)) == -1)			err(1, "setsockopt(IPV6_USE_MIN_MTU)");	}#ifdef IPV6_RECVPATHMTU	else {		optval = 1;		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU,		    &optval, sizeof(optval)) == -1)			err(1, "setsockopt(IPV6_RECVPATHMTU)");	}#endif /* IPV6_RECVPATHMTU */#endif /* IPV6_USE_MIN_MTU */#ifdef IPSEC#ifdef IPSEC_POLICY_IPSEC	if (options & F_POLICY) {		if (setpolicy(s, policy_in) < 0)			errx(1, "%s", ipsec_strerror());		if (setpolicy(s, policy_out) < 0)			errx(1, "%s", ipsec_strerror());	}#else	if (options & F_AUTHHDR) {		optval = IPSEC_LEVEL_REQUIRE;#ifdef IPV6_AUTH_TRANS_LEVEL		if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,		    &optval, sizeof(optval)) == -1)			err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)");#else /* old def */		if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_LEVEL,		    &optval, sizeof(optval)) == -1)			err(1, "setsockopt(IPV6_AUTH_LEVEL)");#endif	}	if (options & F_ENCRYPT) {		optval = IPSEC_LEVEL_REQUIRE;		if (setsockopt(s, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,		    &optval, sizeof(optval)) == -1)			err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)");	}#endif /*IPSEC_POLICY_IPSEC*/#endif#ifdef ICMP6_FILTER    {	struct icmp6_filter filt;	if (!(options & F_VERBOSE)) {		ICMP6_FILTER_SETBLOCKALL(&filt);		if ((options & F_FQDN) || (options & F_FQDNOLD) ||		    (options & F_NODEADDR) || (options & F_SUPTYPES))			ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);		else			ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);	} else {		ICMP6_FILTER_SETPASSALL(&filt);	}	if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,	    sizeof(filt)) < 0)		err(1, "setsockopt(ICMP6_FILTER)");    }#endif /*ICMP6_FILTER*/	/* let the kerel pass extension headers of incoming packets */	if ((options & F_VERBOSE) != 0) {		int opton = 1;#ifdef IPV6_RECVRTHDR		if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_RECVRTHDR)");#else  /* old adv. API */		if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,		    sizeof(opton)))			err(1, "setsockopt(IPV6_RTHDR)");#endif	}/*	optval = 1;	if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))		if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,		    &optval, sizeof(optval)) == -1)			err(1, "IPV6_MULTICAST_LOOP");*/	/* Specify the outgoing interface and/or the source address */	if (usepktinfo)		ip6optlen += CMSG_SPACE(sizeof(struct in6_pktinfo));	if (hoplimit != -1)		ip6optlen += CMSG_SPACE(sizeof(int));#ifdef IPV6_REACHCONF	if (options & F_REACHCONF)		ip6optlen += CMSG_SPACE(0);#endif	/* set IP6 packet options */	if (ip6optlen) {		if ((scmsg = (char *)malloc(ip6optlen)) == 0)			errx(1, "can't allocate enough memory");		smsghdr.msg_control = (caddr_t)scmsg;		smsghdr.msg_controllen = ip6optlen;		scmsgp = (struct cmsghdr *)scmsg;	}	if (usepktinfo) {		pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));		memset(pktinfo, 0, sizeof(*pktinfo));		scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));		scmsgp->cmsg_level = IPPROTO_IPV6;		scmsgp->cmsg_type = IPV6_PKTINFO;		scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);	}	/* set the outgoing interface */	if (ifname) {#ifndef USE_SIN6_SCOPE_ID		/* pktinfo must have already been allocated */		if ((pktinfo->ipi6_ifindex = if_nametoindex(ifname)) == 0)			errx(1, "%s: invalid interface name", ifname);#else		if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0)			errx(1, "%s: invalid interface name", ifname);#endif	}	if (hoplimit != -1) {		scmsgp->cmsg_len = CMSG_LEN(sizeof(int));		scmsgp->cmsg_level = IPPROTO_IPV6;		scmsgp->cmsg_type = IPV6_HOPLIMIT;		*(int *)(CMSG_DATA(scmsgp)) = hoplimit;		scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);	}#ifdef IPV6_REACHCONF	if (options & F_REACHCONF) {		scmsgp->cmsg_len = CMSG_LEN(0);		scmsgp->cmsg_level = IPPROTO_IPV6;		scmsgp->cmsg_type = IPV6_REACHCONF;		scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);	}#endif	if (argc > 1) {	/* some intermediate addrs are specified */		int hops, error;#ifdef USE_RFC2292BIS		int rthdrlen;#endif#ifdef USE_RFC2292BIS		rthdrlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1);		scmsgp->cmsg_len = CMSG_LEN(rthdrlen);		scmsgp->cmsg_level = IPPROTO_IPV6;		scmsgp->cmsg_type = IPV6_RTHDR;		rthdr = (struct ip6_rthdr *)CMSG_DATA(scmsgp);		rthdr = inet6_rth_init((void *)rthdr, rthdrlen,		    IPV6_RTHDR_TYPE_0, argc - 1);		if (rthdr == NULL)			errx(1, "can't initialize rthdr");#else  /* old advanced API */		if ((scmsgp = (struct cmsghdr *)inet6_rthdr_init(scmsgp,		    IPV6_RTHDR_TYPE_0)) == 0)			errx(1, "can't initialize rthdr");#endif /* USE_RFC2292BIS */		for (hops = 0; hops < argc - 1; hops++) {			struct addrinfo *iaip;			if ((error = getaddrinfo(argv[hops], NULL, &hints,			    &iaip)))				errx(1, "%s", gai_strerror(error));			if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6)				errx(1,				    "bad addr family of an intermediate addr");#ifdef USE_RFC2292BIS			if (inet6_rth_add(rthdr,			    &(SIN6(iaip->ai_addr))->sin6_addr))				errx(1, "can't add an intermediate node");#else  /* old advanced API */			if (inet6_rthdr_add(scmsgp,			    &(SIN6(iaip->ai_addr))->sin6_addr,			    IPV6_RTHDR_LOOSE))				errx(1, "can't add an intermediate node");#endif /* USE_RFC2292BIS */			freeaddrinfo(iaip);		}#ifndef USE_RFC2292BIS		if (inet6_rthdr_lasthop(scmsgp, IPV6_RTHDR_LOOSE))			errx(1, "can't set the last flag");#endif		scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);	}	if (!(options & F_SRCADDR)) {		/*		 * get the source address. XXX since we revoked the root		 * privilege, we cannot use a raw socket for this.		 */		int dummy, len = sizeof(src);		if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)			err(1, "UDP socket");		src.sin6_family = AF_INET6;		src.sin6_addr = dst.sin6_addr;		src.sin6_port = ntohs(DUMMY_PORT);		src.sin6_scope_id = dst.sin6_scope_id;#ifdef USE_RFC2292BIS		if (pktinfo &&		    setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO,		    (void *)pktinfo, sizeof(*pktinfo)))			err(1, "UDP setsockopt(IPV6_PKTINFO)");		if (hoplimit != -1 &&		    setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS,		    (void *)&hoplimit, sizeof(hoplimit)))			err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)");		if (hoplimit != -1 &&		    setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,		    (void *)&hoplimit, sizeof(hoplimit)))			err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)");		if (rthdr &&		    setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR,		    (void *)rthdr, (rthdr->ip6r_len + 1) << 3))			err(1, "UDP setsockopt(IPV6_RTHDR)");#else  /* old advanced API */		if (smsghdr.msg_control &&		    setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTOPTIONS,		    (void *)smsghdr.msg_control, smsghdr.msg_controllen))			err(1, "UDP setsockopt(IPV6_PKTOPTIONS)");#endif		if (connect(dummy, (struct sockaddr *)&src, len) < 0)			err(1, "UDP connect");		if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0)			err(1, "getsockname");		close(dummy);	}#if defined(SO_SNDBUF) && defined(SO_RCVBUF)	if (sockbufsize) {		if (datalen > sockbufsize)			warnx("you need -b to increase socket buffer size");		if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sockbufsize,		    sizeof(sockbufsize)) < 0)			err(1, "setsockopt(SO_SNDBUF)");		if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sockbufsize,		    sizeof(sockbufsize)) < 0)			err(1, "setsockopt(SO_RCVBUF)");	}	else {		if (datalen > 8 * 1024)	/*XXX*/			warnx("you need -b to increase socket buffer size");		/*		 * When pinging the broadcast address, you can get a lot of		 * answers. Doing something so evil is useful if you are trying		 * to stress the ethernet, or just want to fill the arp cache		 * to get some stuff for /etc/ethers.		 */		hold = 48 * 1024;		setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,		    sizeof(hold));	}#endif	optval = 1;#ifndef USE_SIN6_SCOPE_ID#ifdef IPV6_RECVPKTINFO	if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,	    sizeof(optval)) < 0)		warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */#else  /* old adv. API */	if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval,	    sizeof(optval)) < 0)		warn("setsockopt(IPV6_PKTINFO)"); /* XXX err? */#endif#endif /* USE_SIN6_SCOPE_ID */#ifdef IPV6_RECVHOPLIMIT	if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval,	    sizeof(optval)) < 0)		warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */#else  /* old adv. API */	if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval,	    sizeof(optval)) < 0)		warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */#endif	printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),	    (unsigned long)(pingerlen() - 8));	printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));	printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));	while (preload--)		/* Fire off them quickies. */		(void)pinger();	(void)signal(SIGINT, onsignal);#ifdef SIGINFO	(void)signal(SIGINFO, onsignal);#endif	if ((options & F_FLOOD) == 0) {		(void)signal(SIGALRM, onsignal);		itimer.it_interval = interval;		itimer.it_value = interval;		(void)setitimer(ITIMER_REAL, &itimer, NULL);		if (ntransmitted)			retransmit();	}

⌨️ 快捷键说明

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