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

📄 tracert.c

📁 Linux 下 C 库及常用 系统调用的使用事例
💻 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 + -