📄 traceroute.c
字号:
#include <stdio.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#include <netinet/udp.h>#include <netinet/ip_icmp.h>#include <netinet/in.h>#include <netinet/ip.h>#include <errno.h>#include <signal.h>#include <setjmp.h>#define BUFFER_SIZE 1500int ttl = 0;static sigjmp_buf jmpbuf;static void recvfrom_alarm(int signo) { printf("*"); alarm(3); siglongjmp(jmpbuf, 1);}int main(int argc, char *argv[]){ int max_ttl=30;//最大TTL u_short sport=30000;//本机端口 u_short dport=32768+666;//宿端口 int myflag= 1; const char *message = "Hello Linux World!";//发送的字符串 int len=strlen(message);//字符串长度 int i,j, packetsize, sockfd, number, clilen; struct in_addr src_addr,des_addr; struct hostent *host; struct sockaddr_in cliaddr,servaddr; struct udphdr *udp; struct iphdr *ip,*ip_header; struct icmphdr *icmp; struct timeval t1,t2; double rtt; char recvbuf[BUFFER_SIZE] , packet[BUFFER_SIZE], ipstr[INET_ADDRSTRLEN],iptr[INET_ADDRSTRLEN]; if(argc != 2) { printf("usage :traceroute hostname \n"); exit(1); } src_addr.s_addr = htonl(INADDR_ANY); if((host=gethostbyname(argv[1])) == NULL)//get host by name { perror("gethostbyname"); exit(1); } memcpy((void*)&des_addr,host->h_addr,sizeof(struct in_addr)); if(inet_ntop(AF_INET,&(des_addr),iptr,INET_ADDRSTRLEN) == NULL) { perror("inet_ntop"); exit(1); } printf("traceroute to %s (%s) %d hop max %d bytes packets\n",argv[1],iptr,max_ttl,len); if((sockfd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0) { perror("socket"); exit(1); } if(setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,(char*)&myflag,sizeof(myflag))<0) { perror("setsockopt"); exit(1); } packetsize = sizeof(struct iphdr) + sizeof(struct udphdr) + strlen(message);//计算发送包的大小 signal(SIGALRM,recvfrom_alarm); alarm(3); for (ttl=1;ttl <=max_ttl;ttl++) { //创建ip头 ip_header = (struct iphdr *)packet; bzero((char*)(ip_header),sizeof(struct iphdr)); ip_header->ihl = 5; ip_header->version = 4; ip_header->id = htons(getpid()); ip_header->ttl = ttl; ip_header->protocol = IPPROTO_UDP; ip_header->daddr = des_addr.s_addr; //为剩余空间清零 bzero((packet + sizeof(struct udphdr) + sizeof(struct iphdr)),BUFFER_SIZE-packetsize); printf("%2d",ttl); fflush(stdout); //udp指针 udp =(struct udphdr*)(packet + sizeof(struct iphdr)); //创建udp头 udp->source = htons(sport); udp->dest = htons(dport); udp->len = htons((sizeof(struct udphdr)+strlen(message))); udp->check = 0; //将Hello Linux World 拷贝到包中 memcpy((char*)udp+sizeof(struct udphdr),message,strlen(message)); //连接准备工作 bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(dport); servaddr.sin_addr = des_addr; //时间戳 for(j=0;j<3;j++) { gettimeofday(&t1,NULL); if(sendto(sockfd,packet,packetsize,0,(struct sockaddr *)&servaddr,sizeof(servaddr)) != packetsize) { perror("sendto"); exit(1); } if (sigsetjmp(jmpbuf, 1) != 0) continue; number = recvfrom(sockfd,recvbuf, BUFFER_SIZE-1, 0, (struct sockaddr *)&cliaddr , &clilen); gettimeofday(&t2,NULL); t2.tv_sec = t2.tv_sec - t1.tv_sec; t2.tv_usec = t2.tv_usec - t1.tv_usec; rtt = t2.tv_sec*1000.0+ t2.tv_usec/1000.0; printf(" %.3f ms",rtt); } recvbuf[number] = '\0'; ip = (struct iphdr*)recvbuf; icmp = (struct icmphdr *)(recvbuf+sizeof(struct iphdr)); udp = (struct udphdr *)(recvbuf + 2*sizeof(struct iphdr) + sizeof(struct icmphdr)); printf(" %s ",inet_ntop(AF_INET,(struct in_addr *)&(ip->saddr),ipstr,INET_ADDRSTRLEN)); printf("\n"); if(icmp->type==ICMP_TIME_EXCEEDED && icmp->code==ICMP_EXC_TTL) { continue; } if(icmp->type==ICMP_DEST_UNREACH && icmp->code==ICMP_PORT_UNREACH) { ip = (struct iphdr*)recvbuf; break; } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -