📄 scanroute.c
字号:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/time.h>#include <sys/socket.h>#include <sys/types.h>#include <netinet/in_systm.h>#include <netinet/in.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#define __FAVOR_BSD#include <netinet/udp.h>#include <arpa/inet.h>enum {CMD_NAME, DST_IP};enum {ON, OFF};#define MAXHOSTNAMELEN 256#define BUFSIZE 512struct packet_udp{ struct ip ip; struct udphdr udp;};void make_ip_header(struct ip *ip, int src_ip, int dst_ip, int ip_len);void make_udp_header(struct udphdr *udp);void tvsub(struct timeval *out, struct timeval *in);u_short checksum(u_short *data, int len);int main(int argc, char * argv[]){ struct packet_udp sendpacket; /* UDP packet to be sent */ struct sockaddr_in send_sa; int send_sd; int recv_sd; int len; int ttl; int i; u_char buff[BUFSIZE]; struct timeval tvm0; /* the time packet sent */ struct timeval tvm1; /* the time packet received */ struct timeval tv; /* (select)'s time out */ fd_set readfd; /* descriptor for (select) check */ int on = 1; int dns_flg = ON; /* whether to resolve host's domain name */ /* check arg "-n" */ if(argc == 3 && (strcmp(argv[1], "-n") == 0)) { dns_flg = OFF; argv[1] = argv[2]; argv[2] = NULL; argc = 2; } if(argc != 2) { fprintf(stderr, "usage: %s [-n] dst_ip \n", argv[CMD_NAME]); exit(EXIT_FAILURE); } memset((char *)&send_sa, 0, sizeof(struct sockaddr_in)); send_sa.sin_family = AF_INET; /* convert domain name to IP */ if((send_sa.sin_addr.s_addr = inet_addr(argv[DST_IP])) == INADDR_NONE) { struct hostent *he; if((he = gethostbyname(argv[DST_IP])) == NULL) { fprintf(stderr, "unknow host %s \n", argv[DST_IP]); exit(EXIT_FAILURE); } send_sa.sin_family = he->h_addrtype; memcpy((char*)&(send_sa.sin_addr), he->h_addr, sizeof(he->h_length)); } /* open a RAW socket for UDP to send */ if((send_sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { perror("socket(RAW)"); exit(EXIT_FAILURE); } if(setsockopt(send_sd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) { perror("setsockopt(IPPROTO_IP, IP_HDRINCL)"); exit(EXIT_FAILURE); } /* open a RAW socket for ICMP to receive */ if((recv_sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { perror("socket(SOCK_RAW)"); exit(EXIT_FAILURE); } /* generate a UDP packet */ len = sizeof(struct packet_udp); memset((char*)&sendpacket, 0, sizeof(struct packet_udp)); make_udp_header(&(sendpacket.udp)); make_ip_header(&(sendpacket.ip), 0, send_sa.sin_addr.s_addr, len); /* main routine */ printf("Scanroute %s \n", inet_ntoa(send_sa.sin_addr)); for(ttl = 1; ttl <= 64; ttl++) { printf("%2d: ", ttl); fflush(stdout); sendpacket.ip.ip_ttl = ttl; for(i = 0; i < 3; i++) { /* send a UDP packet */ if(sendto(send_sd, (char*)&sendpacket, len, 0, (struct sockaddr *)&send_sa, sizeof(send_sa)) < 0) { perror("sendto"); exit(EXIT_FAILURE); } /* store the time sent */ gettimeofday(&tvm0, (struct timezone *)0); /* set time out */ tv.tv_sec = 3; tv.tv_usec = 0;reread: /* check descriptors using "select" */ FD_ZERO(&readfd); FD_SET(recv_sd, &readfd); if((select(recv_sd+1, &readfd, NULL, NULL, &tv)) > 0) { int hlen; /* len of header */ struct icmp *icmp; struct ip *ip; struct hostent *host; char hostip[256]; struct in_addr ipaddr; /* receive a ICMP packet */ if(recvfrom(recv_sd, buff, BUFSIZE, 0, NULL, NULL) < 0) { perror("recvfrom"); exit(EXIT_FAILURE); } ip = (struct ip *)buff; hlen = ip->ip_hl << 2; if(ip->ip_p != IPPROTO_ICMP) goto reread; icmp = (struct icmp *)(buff + hlen); /* don't receive unrelated packets */ if((icmp->icmp_type != ICMP_TIMXCEED || icmp->icmp_code != ICMP_TIMXCEED_INTRANS) && (icmp->icmp_type != ICMP_UNREACH_PORT)) goto reread; /* store the time received packet */ gettimeofday(&tvm1, (struct timezone *)0); tvsub(&tvm1, &tvm0); memcpy(&ipaddr, &(ip->ip_src.s_addr), sizeof(ipaddr)); strcpy(hostip, inet_ntoa(*(struct in_addr *)&(ip->ip_src.s_addr))); /* display IP and domain name */ if(dns_flg == OFF) printf("% -15s", hostip); else if((host= gethostbyaddr((char*)&ipaddr, 4, AF_INET)) == NULL) printf("%-15s(%S)", hostip, hostip); else printf("%-15s(%S)", hostip, host->h_name); printf(":RTT= %8.4fms", tvm1.tv_sec*1000.0 + tvm1.tv_usec/1000.0); /* check whether reached dst host */ if(icmp->icmp_type == ICMP_UNREACH_PORT) { printf("\n Reach!\n"); goto exit; } else break; } else { printf("?"); fflush(stdout); } } printf(" \n"); }exit: close(send_sd); close(recv_sd); return EXIT_SUCCESS;}void make_udp_header(struct udphdr *udp){ udp->uh_sport = htons(0); udp->uh_ulen = htons((u_short)sizeof(struct udphdr)); udp->uh_dport = htons(33434); /* port of traceroute */ udp->uh_sum = htons(0);}void make_ip_header(struct ip *ip, int src_ip, int dst_ip, int ip_len){ memset((char *)ip, 0, sizeof(struct ip)); /* generate an IP header */ ip->ip_v = IPVERSION; ip->ip_hl = sizeof(struct ip) >> 2; ip->ip_id = htons(0); ip->ip_off = 0;#ifdef _linux /* linux's RAW IP */ ip->ip_len = htons(ip_len); ip->ip_off = htons(0);#else /* BSD's RAW IP */ ip->ip_len = ip_len; ip->ip_off = 0;#endif ip->ip_ttl = 64; ip->ip_p = IPPROTO_UDP; ip->ip_src.s_addr = src_ip; ip->ip_dst.s_addr = dst_ip; /* calc the checksum */ ip->ip_sum = 0; ip->ip_sum = checksum((u_short *)ip, sizeof(struct ip));}void tvsub(struct timeval *out, struct timeval * in){ if( (out->tv_usec -= in->tv_usec) < 0) { out->tv_sec --; out->tv_usec += 1000000; } out->tv_sec -= in->tv_sec;}u_short checksum(u_short *data, int len){ u_long sum = 0; /* increase 2 bytes at one time */ for(; len > 1; len -= 2) { sum += *data++; if(sum & 0x80000000) sum = (sum & 0xffff) + (sum >> 16); } /* process if len is odd */ if(len == 1) { u_short i = 0; *(u_char *)(&i) = * (u_char *)data; sum += i; } /* process the overflow bit */ while(sum >> 16) sum = (sum & 0xffff) + (sum >> 16); return (sum == 0xffff) ? sum : ~sum;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -