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

📄 traceroute6.c

📁 IPv6环境下的traceroute实现
💻 C
📖 第 1 页 / 共 3 页
字号:
	int cc = 0;	pfd[0].fd = sock;	pfd[0].events = POLLIN;	pfd[0].revents = 0;	if (poll(pfd, 1, waittime * 1000) > 0)		cc = recvmsg(rcvsock, mhdr, 0);	return(cc);#else	fd_set *fdsp;	struct timeval wait;	int cc = 0, fdsn;	fdsn = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);	if ((fdsp = (fd_set *)malloc(fdsn)) == NULL)		err(1, "malloc");	memset(fdsp, 0, fdsn);	FD_SET(sock, fdsp);	wait.tv_sec = waittime; wait.tv_usec = 0;	if (select(sock+1, fdsp, (fd_set *)0, (fd_set *)0, &wait) > 0)		cc = recvmsg(rcvsock, mhdr, 0);	free(fdsp);	return(cc);#endif}#ifdef IPSEC#ifdef IPSEC_POLICY_IPSECintsetpolicy(so, policy)	int so;	char *policy;{	char *buf;	buf = ipsec_set_policy(policy, strlen(policy));	if (buf == NULL) {		warnx("%s", ipsec_strerror());		return -1;	}	(void)setsockopt(so, IPPROTO_IPV6, IPV6_IPSEC_POLICY,	    buf, ipsec_get_policylen(buf));	free(buf);	return 0;}#endif#endifvoidsend_probe(seq, hops)	int seq, hops;{	int i;	if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,	    (char *)&hops, sizeof(hops)) < 0) {		perror("setsockopt IPV6_UNICAST_HOPS");	}	Dst.sin6_port = htons(port + seq);	if (useicmp) {		struct icmp6_hdr *icp = (struct icmp6_hdr *)outpacket;		struct timeval tv;		struct tv32 *tv32;		icp->icmp6_type = ICMP6_ECHO_REQUEST;		icp->icmp6_code = 0;		icp->icmp6_cksum = 0;		icp->icmp6_id = ident;		icp->icmp6_seq = htons(seq);		(void) gettimeofday(&tv, NULL);		tv32 = (struct tv32 *)((u_int8_t *)outpacket + ICMP6ECHOLEN);		tv32->tv32_sec = htonl(tv.tv_sec);		tv32->tv32_usec = htonl(tv.tv_usec);	} else {		struct opacket *op = outpacket;		op->seq = seq;		op->hops = hops;		(void) gettimeofday(&op->tv, NULL);	}	i = sendto(sndsock, (char *)outpacket, datalen , 0,	    (struct sockaddr *)&Dst, Dst.sin6_len);	if (i < 0 || i != datalen)  {		if (i<0)			perror("sendto");		printf("traceroute6: wrote %s %d chars, ret=%d\n",		    hostname, datalen, i);		(void) fflush(stdout);	}}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_level == IPPROTO_IPV6 &&		    cm->cmsg_type == IPV6_HOPLIMIT &&		    cm->cmsg_len == CMSG_LEN(sizeof(int)))			return(*(int *)CMSG_DATA(cm));	}	return(-1);}doubledeltaT(t1p, t2p)	struct timeval *t1p, *t2p;{	register double dt;	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +	    (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;	return (dt);}/* * Convert an ICMP "type" field to a printable string. */char *pr_type(t0)	int t0;{	u_char t = t0 & 0xff;	char *cp;	switch (t) {	case ICMP6_DST_UNREACH:		cp = "Destination Unreachable";		break;	case ICMP6_PACKET_TOO_BIG:		cp = "Packet Too Big";		break;	case ICMP6_TIME_EXCEEDED:		cp = "Time Exceeded";		break;	case ICMP6_PARAM_PROB:		cp = "Parameter Problem";		break;	case ICMP6_ECHO_REQUEST:		cp = "Echo Request";		break;	case ICMP6_ECHO_REPLY:		cp = "Echo Reply";		break;	case ICMP6_MEMBERSHIP_QUERY:		cp = "Group Membership Query";		break;	case ICMP6_MEMBERSHIP_REPORT:		cp = "Group Membership Report";		break;	case ICMP6_MEMBERSHIP_REDUCTION:		cp = "Group Membership Reduction";		break;	case ND_ROUTER_SOLICIT:		cp = "Router Solicitation";		break;	case ND_ROUTER_ADVERT:		cp = "Router Advertisement";		break;	case ND_NEIGHBOR_SOLICIT:		cp = "Neighbor Solicitation";		break;	case ND_NEIGHBOR_ADVERT:		cp = "Neighbor Advertisement";		break;	case ND_REDIRECT:		cp = "Redirect";		break;	default:		cp = "Unknown";		break;	}	return cp;}intpacket_ok(mhdr, cc, seq)	struct msghdr *mhdr;	int cc;	int seq;{	register struct icmp6_hdr *icp;	struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;	u_char type, code;	char *buf = (char *)mhdr->msg_iov[0].iov_base;	struct cmsghdr *cm;	int *hlimp;	char hbuf[NI_MAXHOST];#ifdef OLDRAWSOCKET	int hlen;	struct ip6_hdr *ip;#endif#ifdef OLDRAWSOCKET	ip = (struct ip6_hdr *) buf;	hlen = sizeof(struct ip6_hdr);	if (cc < hlen + sizeof(struct icmp6_hdr)) {		if (verbose) {			if (getnameinfo((struct sockaddr *)from, from->sin6_len,			    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)				strlcpy(hbuf, "invalid", sizeof(hbuf));			printf("packet too short (%d bytes) from %s\n", cc,			    hbuf);		}		return (0);	}	cc -= hlen;	icp = (struct icmp6_hdr *)(buf + hlen);#else	if (cc < sizeof(struct icmp6_hdr)) {		if (verbose) {			if (getnameinfo((struct sockaddr *)from, from->sin6_len,			    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)				strlcpy(hbuf, "invalid", sizeof(hbuf));			printf("data too short (%d bytes) from %s\n", cc, hbuf);		}		return(0);	}	icp = (struct icmp6_hdr *)buf;#endif	/* get optional information via advanced API */	rcvpktinfo = NULL;	hlimp = NULL;	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;	    cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {		if (cm->cmsg_level == IPPROTO_IPV6 &&		    cm->cmsg_type == IPV6_PKTINFO &&		    cm->cmsg_len ==		    CMSG_LEN(sizeof(struct in6_pktinfo)))			rcvpktinfo = (struct in6_pktinfo *)(CMSG_DATA(cm));		if (cm->cmsg_level == IPPROTO_IPV6 &&		    cm->cmsg_type == IPV6_HOPLIMIT &&		    cm->cmsg_len == CMSG_LEN(sizeof(int)))			hlimp = (int *)CMSG_DATA(cm);	}	if (rcvpktinfo == NULL || hlimp == NULL) {		warnx("failed to get received hop limit or packet info");#if 0		return(0);#else		rcvhlim = 0;	/*XXX*/#endif	}	else		rcvhlim = *hlimp;	type = icp->icmp6_type;	code = icp->icmp6_code;	if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)	 || type == ICMP6_DST_UNREACH) {		struct ip6_hdr *hip;		struct udphdr *up;		hip = (struct ip6_hdr *)(icp + 1);		if ((up = get_udphdr(hip, (u_char *)(buf + cc))) == NULL) {			if (verbose)				warnx("failed to get upper layer header");			return(0);		}		if (useicmp &&		    ((struct icmp6_hdr *)up)->icmp6_id == ident &&		    ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq))			return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1);		else if (!useicmp &&		    up->uh_sport == htons(srcport) &&		    up->uh_dport == htons(port + seq))			return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1);	} else if (useicmp && type == ICMP6_ECHO_REPLY) {		if (icp->icmp6_id == ident &&		    icp->icmp6_seq == htons(seq))			return (ICMP6_DST_UNREACH_NOPORT + 1);	}	if (verbose) {		int i;		u_int8_t *p;		char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];		if (getnameinfo((struct sockaddr *)from, from->sin6_len,		    sbuf, sizeof(sbuf), NULL, 0, NI_NUMERICHOST) != 0)			strlcpy(sbuf, "invalid", sizeof(sbuf));		printf("\n%d bytes from %s to %s", cc, sbuf,		    rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,		    dbuf, sizeof(dbuf)) : "?");		printf(": icmp type %d (%s) code %d\n", type, pr_type(type),		    icp->icmp6_code);		p = (u_int8_t *)(icp + 1);#define WIDTH	16		for (i = 0; i < cc; i++) {			if (i % WIDTH == 0)				printf("%04x:", i);			if (i % 4 == 0)				printf(" ");			printf("%02x", p[i]);			if (i % WIDTH == WIDTH - 1)				printf("\n");		}		if (cc % WIDTH != 0)			printf("\n");	}	return(0);}/* * Increment pointer until find the UDP or ICMP header. */struct udphdr *get_udphdr(ip6, lim)	struct ip6_hdr *ip6;	u_char *lim;{	u_char *cp = (u_char *)ip6, nh;	int hlen;	if (cp + sizeof(*ip6) >= lim)		return(NULL);	nh = ip6->ip6_nxt;	cp += sizeof(struct ip6_hdr);	while (lim - cp >= 8) {		switch (nh) {		case IPPROTO_ESP:		case IPPROTO_TCP:			return(NULL);		case IPPROTO_ICMPV6:			return(useicmp ? (struct udphdr *)cp : NULL);		case IPPROTO_UDP:			return(useicmp ? NULL : (struct udphdr *)cp);		case IPPROTO_FRAGMENT:			hlen = sizeof(struct ip6_frag);			nh = ((struct ip6_frag *)cp)->ip6f_nxt;			break;		case IPPROTO_AH:			hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;			nh = ((struct ip6_ext *)cp)->ip6e_nxt;			break;		default:			hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;			nh = ((struct ip6_ext *)cp)->ip6e_nxt;			break;		}		cp += hlen;	}	return(NULL);}voidprint(mhdr, cc)	struct msghdr *mhdr;	int cc;{	struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;	char hbuf[NI_MAXHOST];	if (getnameinfo((struct sockaddr *)from, from->sin6_len,	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)		strlcpy(hbuf, "invalid", sizeof(hbuf));	if (nflag)		printf(" %s", hbuf);	else if (lflag)		printf(" %s (%s)", inetname((struct sockaddr *)from), hbuf);	else		printf(" %s", inetname((struct sockaddr *)from));	if (verbose) {#ifdef OLDRAWSOCKET		printf(" %d bytes to %s", cc,		    rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,		    hbuf, sizeof(hbuf)) : "?");#else		printf(" %d bytes of data to %s", cc,		    rcvpktinfo ?  inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,		    hbuf, sizeof(hbuf)) : "?");#endif	}}/* * Subtract 2 timeval structs:  out = out - in. * Out is assumed to be >= in. */voidtvsub(out, in)	register struct timeval *out, *in;{	if ((out->tv_usec -= in->tv_usec) < 0)   {		out->tv_sec--;		out->tv_usec += 1000000;	}	out->tv_sec -= in->tv_sec;}/* * Construct an Internet address representation. * If the nflag has been supplied, give * numeric value, otherwise try for symbolic name. */const char *inetname(sa)	struct sockaddr *sa;{	register char *cp;	static char line[NI_MAXHOST];	static char domain[MAXHOSTNAMELEN + 1];	static int first = 1;	if (first && !nflag) {		first = 0;		if (gethostname(domain, sizeof(domain)) == 0 &&		    (cp = strchr(domain, '.')))			(void) strlcpy(domain, cp + 1, sizeof(domain));		else			domain[0] = 0;	}	cp = NULL;	if (!nflag) {		if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,		    NI_NAMEREQD) == 0) {			if ((cp = strchr(line, '.')) &&			    !strcmp(cp + 1, domain))				*cp = 0;			cp = line;		}	}	if (cp)		return cp;	if (getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0,	    NI_NUMERICHOST) != 0)		strlcpy(line, "invalid", sizeof(line));	return line;}voidusage(){	fprintf(stderr,"usage: traceroute6 [-dIlnrv] [-f firsthop] [-g gateway] [-m hoplimit]\n""       [-p port] [-q probes] [-s src] [-w waittime] target [datalen]\n");	exit(1);}

⌨️ 快捷键说明

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