traceroute.c

来自「手机嵌入式Linux下可用的busybox源码」· C语言 代码 · 共 648 行 · 第 1/2 页

C
648
字号
	static const char * const ttab[] = {	"Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",	"Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",	"Echo",         "ICMP 9",       "ICMP 10",      "Time Exceeded",	"Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",	"Info Reply"	};	if(t > 16)		return("OUT-OF-RANGE");	return(ttab[t]);}#endifstatic inline intpacket_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq){	struct icmp *icp;	u_char type, code;	int hlen;	struct ip *ip;	ip = (struct ip *) buf;	hlen = ip->ip_hl << 2;	if (cc < hlen + ICMP_MINLEN) {#ifdef BB_FEATURE_TRACEROUTE_VERBOSE		if (verbose)			printf("packet too short (%d bytes) from %s\n", cc,				inet_ntoa(from->sin_addr));#endif		return (0);	}	cc -= hlen;	icp = (struct icmp *)(buf + hlen);	type = icp->icmp_type; code = icp->icmp_code;	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||	    type == ICMP_UNREACH) {		struct ip *hip;		struct udphdr *up;		hip = &icp->icmp_ip;		hlen = hip->ip_hl << 2;		up = (struct udphdr *)((u_char *)hip + hlen);		if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&		    up->source == htons(ident) &&		    up->dest == htons(port+seq))			return (type == ICMP_TIMXCEED? -1 : code+1);	}#ifdef BB_FEATURE_TRACEROUTE_VERBOSE	if (verbose) {		int i;		u_long *lp = (u_long *)&icp->icmp_ip;		printf("\n%d bytes from %s to %s: icmp type %d (%s) code %d\n",			cc, inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst),			type, pr_type(type), icp->icmp_code);		for (i = 4; i < cc ; i += sizeof(long))			printf("%2d: x%8.8lx\n", i, *lp++);	}#endif	return(0);}static void             /* not inline */send_probe(int seq, int ttl){	struct opacket *op = outpacket;	struct ip *ip = &op->ip;	struct udphdr *up = &op->udp;	int i;	struct timezone tz;	ip->ip_off = 0;	ip->ip_hl = sizeof(*ip) >> 2;	ip->ip_p = IPPROTO_UDP;	ip->ip_len = datalen;	ip->ip_ttl = ttl;	ip->ip_v = IPVERSION;	ip->ip_id = htons(ident+seq);	up->source = htons(ident);	up->dest = htons(port+seq);	up->len = htons((u_short)(datalen - sizeof(struct ip)));	up->check = 0;	op->seq = seq;	op->ttl = ttl;	(void) gettimeofday(&op->tv, &tz);	i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,		   sizeof(struct sockaddr));	if (i < 0 || i != datalen)  {		if (i<0)			perror("sendto");		printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,			datalen, i);		(void) fflush(stdout);	}}int#ifndef BB_TRACEROUTEmain(argc, argv)#elsetraceroute_main(argc, argv)#endif	int argc;	char *argv[];{	extern char *optarg;	extern int optind;	struct hostent *hp;	struct sockaddr_in from, *to;	int ch, i, on, probe, seq, tos, ttl;	int options = 0;                /* socket options */	char *source = 0;	int nprobes = 3;	on = 1;	seq = tos = 0;	to = (struct sockaddr_in *)&whereto;	while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)		switch(ch) {		case 'd':#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG			options |= SO_DEBUG;#endif			break;		case 'm':			max_ttl = atoi(optarg);			if (max_ttl <= 1)				error_msg_and_die("max ttl must be >1.");			break;		case 'n':			nflag++;			break;		case 'p':			port = atoi(optarg);			if (port < 1)				error_msg_and_die("port must be >0.");			break;		case 'q':			nprobes = atoi(optarg);			if (nprobes < 1)				error_msg_and_die("nprobes must be >0.");			break;		case 'r':			options |= SO_DONTROUTE;			break;		case 's':			/*			 * set the ip source address of the outbound			 * probe (e.g., on a multi-homed host).			 */			source = optarg;			break;		case 't':			tos = atoi(optarg);			if (tos < 0 || tos > 255)				error_msg_and_die("tos must be 0 to 255.");			break;		case 'v':#ifdef BB_FEATURE_TRACEROUTE_VERBOSE			verbose++;#endif			break;		case 'w':			waittime = atoi(optarg);			if (waittime <= 1)				error_msg_and_die("wait must be >1 sec.");			break;		default:			show_usage();		}	argc -= optind;	argv += optind;	if (argc < 1)		show_usage();	setlinebuf (stdout);	memset(&whereto, 0, sizeof(struct sockaddr));	hp = xgethostbyname(*argv);			to->sin_family = hp->h_addrtype;	memcpy(&to->sin_addr, hp->h_addr, hp->h_length);			hostname = (char *)hp->h_name;	if (*++argv)		datalen = atoi(*argv);	if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket))		error_msg_and_die("packet size must be 0 <= s < %d.",		    MAXPACKET - sizeof(struct opacket));	datalen += sizeof(struct opacket);	outpacket = (struct opacket *)xmalloc((unsigned)datalen);	memset(outpacket, 0, datalen);	outpacket->ip.ip_dst = to->sin_addr;	outpacket->ip.ip_tos = tos;	outpacket->ip.ip_v = IPVERSION;	outpacket->ip.ip_id = 0;	ident = (getpid() & 0xffff) | 0x8000;	if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)		perror_msg_and_die(can_not_create_raw_socket);	s = create_icmp_socket();#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG	if (options & SO_DEBUG)		(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,				  (char *)&on, sizeof(on));#endif	if (options & SO_DONTROUTE)		(void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,				  (char *)&on, sizeof(on));#ifdef SO_SNDBUF	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,		       sizeof(datalen)) < 0)		perror_msg_and_die("SO_SNDBUF");#endif /* SO_SNDBUF */#ifdef IP_HDRINCL	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,		       sizeof(on)) < 0)		perror_msg_and_die("IP_HDRINCL");#endif /* IP_HDRINCL */#ifdef BB_FEATURE_TRACEROUTE_SO_DEBUG	if (options & SO_DEBUG)		(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,				  (char *)&on, sizeof(on));#endif	if (options & SO_DONTROUTE)		(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,				  (char *)&on, sizeof(on));	if (source) {		memset(&from, 0, sizeof(struct sockaddr));		from.sin_family = AF_INET;		from.sin_addr.s_addr = inet_addr(source);		if (from.sin_addr.s_addr == -1)			error_msg_and_die("unknown host %s", source);		outpacket->ip.ip_src = from.sin_addr;#ifndef IP_HDRINCL		if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0)			perror_msg_and_die("bind");#endif /* IP_HDRINCL */	}	fprintf(stderr, "traceroute to %s (%s)", hostname,		inet_ntoa(to->sin_addr));	if (source)		fprintf(stderr, " from %s", source);	fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);	for (ttl = 1; ttl <= max_ttl; ++ttl) {		u_long lastaddr = 0;		int got_there = 0;		int unreachable = 0;		printf("%2d ", ttl);		for (probe = 0; probe < nprobes; ++probe) {			int cc, reset_timer;			struct timeval t1, t2;			struct timezone tz;			struct ip *ip;			(void) gettimeofday(&t1, &tz);			send_probe(++seq, ttl);			reset_timer = 1;			while ((cc = wait_for_reply(s, &from, reset_timer)) != 0) {				(void) gettimeofday(&t2, &tz);				if ((i = packet_ok(packet, cc, &from, seq))) {					reset_timer = 1;					if (from.sin_addr.s_addr != lastaddr) {						print(packet, cc, &from);						lastaddr = from.sin_addr.s_addr;					}					printf("  %g ms", deltaT(&t1, &t2));					switch(i - 1) {					case ICMP_UNREACH_PORT:						ip = (struct ip *)packet;						if (ip->ip_ttl <= 1)							printf(" !");						++got_there;						break;					case ICMP_UNREACH_NET:						++unreachable;						printf(" !N");						break;					case ICMP_UNREACH_HOST:						++unreachable;						printf(" !H");						break;					case ICMP_UNREACH_PROTOCOL:						++got_there;						printf(" !P");						break;					case ICMP_UNREACH_NEEDFRAG:						++unreachable;						printf(" !F");						break;					case ICMP_UNREACH_SRCFAIL:						++unreachable;						printf(" !S");						break;					}					break;				} else					reset_timer = 0;			}			if (cc == 0)				printf(" *");			(void) fflush(stdout);		}		putchar('\n');		if (got_there || unreachable >= nprobes-1)			exit(0);	}	return 0;}

⌨️ 快捷键说明

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