📄 tracert.c
字号:
/*tracert.c*/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/un.h>#include <sys/time.h>#include <sys/times.h>#include <sys/ioctl.h>#include <unistd.h>#include <netinet/in.h>#include <netdb.h>//// Defines for ICMP message types//#define ICMP_ECHOREPLY 0#define ICMP_DESTUNREACH 3#define ICMP_SRCQUENCH 4#define ICMP_REDIRECT 5#define ICMP_ECHO 8#define ICMP_TIMEOUT 11#define ICMP_PARMERR 12#define MAX_HOPS 30#define ICMP_MIN 8 // Minimum 8 byte icmp packet (just header)//// IP Header//typedef struct iphdr { unsigned int h_len:4; // Length of the header unsigned int version:4; // Version of IP unsigned char tos; // Type of service unsigned short total_len; // Total length of the packet unsigned short ident; // Unique identifier unsigned short frag_and_flags; // Flags unsigned char ttl; // Time to live unsigned char proto; // Protocol (TCP, UDP etc) unsigned short checksum; // IP checksum unsigned int sourceIP; // Source IP unsigned int destIP; // Destination IP} IpHeader;//// ICMP header//typedef struct _ihdr { char i_type; // ICMP message type char i_code; // Sub code unsigned short i_cksum; unsigned short i_id; // Unique id unsigned short i_seq; // Sequence number // This is not the std header, but we reserve space for time unsigned long timestamp;} IcmpHeader;#define DEF_PACKET_SIZE 32#define MAX_PACKET 1024//// Function: usage//void usage(char *progname){ printf("usage: %s host-name [max-hops]\n", progname); exit(-1);}//// Function: set_ttl//int set_ttl(int s, int nTimeToLive){ int nRet; nRet = setsockopt(s, IPPROTO_IP, IP_TTL, (int *)&nTimeToLive, sizeof(int)); if (nRet < 0) { perror("setsockopt in set_ttl:"); return 0; } return 1;}//// Function: decode_resp//int decode_resp(char *buf, int bytes, struct sockaddr_in *from, int ttl){ IpHeader *iphdr = NULL; IcmpHeader *icmphdr = NULL; unsigned short iphdrlen; struct hostent *lpHostent = NULL; struct in_addr inaddr = from->sin_addr; iphdr = (IpHeader *)buf; // Number of 32-bit words * 4 = bytes iphdrlen = iphdr->h_len * 4; if (bytes < iphdrlen + ICMP_MIN) printf("Too few bytes from %s\n",
inet_ntoa(from->sin_addr)); icmphdr = (IcmpHeader*)(buf + iphdrlen); switch (icmphdr->i_type) { case ICMP_ECHOREPLY: // Response from destination lpHostent = gethostbyaddr((const char *)&from->sin_addr, 4, AF_INET); if (lpHostent != NULL) printf("gethostbyaddr success\n"); return 1; break; case ICMP_TIMEOUT: // Response from router along the way printf("%2d %s\n", ttl, inet_ntoa(inaddr)); return 0; break; case ICMP_DESTUNREACH: // Can't reach the destination at all printf("%2d %s reports: Host is unreachable\n", ttl, inet_ntoa(inaddr)); return 1; break; default: printf("non-echo type %d recvd\n", icmphdr->i_type); return 1; break; } return 0;}//// Function: checksum//unsigned short checksum(unsigned short *buffer, int size) { unsigned long cksum=0; while(size > 1) { cksum += *buffer++; size -= sizeof(unsigned short); } if(size ) cksum += *(unsigned char*)buffer; cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >> 16); return (unsigned short)(~cksum);}//// Function: fill_icmp_data//void fill_icmp_data(char * icmp_data, int datasize){ IcmpHeader *icmp_hdr; char *datapart; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr->i_type = ICMP_ECHO; icmp_hdr->i_code = 0; icmp_hdr->i_id = (unsigned short)getpid(); icmp_hdr->i_cksum = 0; icmp_hdr->i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); memset(datapart,'E', datasize - sizeof(IcmpHeader));}long GetTickCount(){ struct tms tm; return times(&tm);}//// Function: main// int main(int argc, char **argv){ int sockRaw; struct hostent *hp = NULL; struct sockaddr_in dest, from; int ret, datasize, fromlen = sizeof(from), done = 0, maxhops, ttl = 1; char *icmp_data, *recvbuf; int bOpt; unsigned short seq_no = 0; struct timeval timeout; if (argc < 2) usage(argv[0]); if (argc == 3) maxhops = atoi(argv[2]); else maxhops = MAX_HOPS; sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sockRaw < 0) { perror("socket"); exit(-1); } // // Set the receive and send timeout values to a second // timeout.tv_sec = 1; timeout.tv_usec = 0; ret = setsockopt(sockRaw, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(struct timeval)); if (ret == -1) { perror("setsockopt in main receive:"); return -1; } timeout.tv_sec = 1; timeout.tv_usec = 0; ret = setsockopt(sockRaw, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(struct timeval)); if (ret == -1) { perror("setsockopt in send:"); return -1; } memset(&dest, 0, sizeof(struct sockaddr_in)); dest.sin_family = AF_INET; if ((dest.sin_addr.s_addr = inet_addr(argv[1])) == INADDR_NONE) { hp = gethostbyname(argv[1]); if (hp) memcpy(&dest.sin_addr, hp->h_addr, hp->h_length); else { printf("Unable to resolve %s\n",argv[1]); exit(-1); } } // // Set the data size to the default packet size. // We don't care about the data since this is just traceroute/ping // datasize = DEF_PACKET_SIZE; datasize += sizeof(IcmpHeader); // // Allocate the sending and receiving buffers for ICMP packets // icmp_data = malloc(MAX_PACKET*sizeof(char)); recvbuf = malloc(MAX_PACKET*sizeof(char)); if ((!icmp_data) || (!recvbuf)) { perror("malloc:"); return -1; } // // Here we are creating and filling in an ICMP header that is the // core of trace route. // memset(icmp_data, 0, MAX_PACKET); fill_icmp_data(icmp_data, datasize); printf("\nTracing route to %s over a maximum of %d hops:\n\n", argv[1], maxhops); for(ttl = 1; ((ttl < maxhops) && (!done)); ttl++) { int bwrote; // Set the time to live option on the socket // set_ttl(sockRaw, ttl); // // Fill in some more data in the ICMP header // ((IcmpHeader*)icmp_data)->i_cksum = 0; ((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); ((IcmpHeader*)icmp_data)->i_seq = seq_no++; ((IcmpHeader*)icmp_data)->i_cksum = checksum((unsigned short*)icmp_data, datasize); // // Send the ICMP packet to the destination // bwrote = sendto(sockRaw, icmp_data, datasize, 0, (struct sockaddr *)&dest, sizeof(dest)); if (bwrote < 0) { perror("sendto:"); return -1; } // Read a packet back from the destination or a router along // the way. // ret = recvfrom(sockRaw, recvbuf, MAX_PACKET, 0, (struct sockaddr*)&from, &fromlen); if (ret < 0) { perror("recvfrom:"); return -1; } // // Decode the response to see if the ICMP response is from a // router along the way or whether it has reached the destination. // done = decode_resp(recvbuf, ret, &from, ttl); sleep(1); } free(recvbuf); free(icmp_data); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -