Unix下的Ping程序

#define _GNU_SOURCE
#include    <sys/time.h>
#include    <sys/un.h>
#include    <string.h>
#include    <arpa/inet.h>
#include    <signal.h>
#include    <stdarg.h>
#include    <syslog.h>
#include    <errno.h>
#include    <netinet/in_systm.h>
#include    <netinet/ip.h>
#include    <netinet/ip_icmp.h>
#include    <sys/types.h>
#include    <time.h>
#include    <stdlib.h>
#include    <stdio.h>
#include    <unistd.h>
#include    <sys/socket.h>
#include    <netdb.h>
#include    <netinet/ip6.h>
#include    <netinet/icmp6.h>

#define    BUFSIZE    1500
//#define IPV6
/* globals */
char sendbuf[BUFSIZE];

int datalen;    /* # bytes of data following ICMP header */
char *host;
int nsent;    /* add 1 for each sendto() */
pid_t pid;    /* our PID */
int sockfd;
int verbose;

struct proto {
    void (*fproc) (char *, ssize_t, struct msghdr *, struct timeval *);
    void (*fsend) (void);
    void (*finit) (void);
    struct sockaddr *sasend;    /* sockaddr{} for send, from getaddrinfo */
    struct sockaddr *sarecv;    /* sockaddr{} for receiving */
    socklen_t salen;    /* length of sockaddr{}s */
    int icmpproto;    /* IPPROTO_xxx value for ICMP */
} *pr;

#define    MAXLINE    4096    /* max text line length */
int daemon_proc;    /* set nonzero by daemon_init() */
void err_doit(int errnoflag, int level, const char *fmt, va_list ap)
{
    int errno_save, n;
    char buf[MAXLINE + 1];

    errno_save = errno;    /* value caller might want printed */
    #ifdef    HAVE_VSNPRINTF
    vsnprintf(buf, MAXLINE, fmt, ap);    /* safe */
    #else
    vsprintf(buf, fmt, ap);    /* not safe */
    #endif
    n = strlen(buf);
    if (errnoflag)
        snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));
    strcat(buf, "\n");

    if (daemon_proc) {
        syslog(level, "%s", buf);
    } 
    else 
    {
        fflush(stdout);    /* in case stdout and stderr are the same */
        fputs(buf, stderr);
        fflush(stderr);
    }
    return;
}

void err_quit(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(0, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(1);
}

void err_sys(const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, LOG_ERR, fmt, ap);
    va_end(ap);
    exit(1);
}

char *sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
    static char str[128];    /* Unix domain is largest */

    switch (sa->sa_family) {
        case AF_INET:{
            struct sockaddr_in *sin = (struct sockaddr_in *)sa;

            if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str))== NULL)
            return (NULL);
            return (str);
        }

    #ifdef    IPV6
        case AF_INET6:{
            struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;

            if (inet_ntop
            (AF_INET6, &sin6->sin6_addr, str,
            sizeof(str)) == NULL)
            return (NULL);
            return (str);
        }
        #endif

        #ifdef    AF_UNIX
        case AF_UNIX:{
            struct sockaddr_un *unp = (struct sockaddr_un *)sa;

            /* OK to have no pathname bound to the socket: happens on
            every connect() unless client calls bind() first. */
            if (unp->sun_path[0] == 0)
                strcpy(str, "(no pathname bound)");
            else
                snprintf(str, sizeof(str), "%s", unp->sun_path);
            return (str);
        }
        #endif

        #ifdef    HAVE_SOCKADDR_DL_STRUCT
        case AF_LINK:{
            struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;

            if (sdl->sdl_nlen > 0)
                snprintf(str, sizeof(str), "%*s",sdl->sdl_nlen, &sdl->sdl_data[0]);
            else
                snprintf(str, sizeof(str), "AF_LINK, index=%d",    sdl->sdl_index);
            return (str);
        }
        #endif
        default:
            snprintf(str, sizeof(str),"sock_ntop_host: unknown AF_xxx: %d, len %d",sa->sa_family, salen);
            return (str);
    }
    return (NULL);
}

char *Sock_ntop_host(const struct sockaddr *sa, socklen_t salen)
{
    char *ptr;

    if ((ptr = sock_ntop_host(sa, salen)) == NULL)
        err_sys("sock_ntop_host error");    /* inet_ntop() sets errno */
    return (ptr);
}

void tv_sub(struct timeval *out, struct timeval *in)
{
    if ((out->tv_usec -= in->tv_usec) < 0) {    /* out -= in */
        --out->tv_sec;
        out->tv_usec += 1000000;
    }
    out->tv_sec -= in->tv_sec;
}

void proc_v4(char *ptr, ssize_t len, struct msghdr *msg, struct timeval *tvrecv)
{
    int hlen1, icmplen;
    double rtt;
    struct ip *ip;
    struct icmp *icmp;
    struct timeval *tvsend;

    ip = (struct ip *)ptr;    /* start of IP header */
    hlen1 = ip->ip_hl << 2;    /* length of IP header */
    if (ip->ip_p != IPPROTO_ICMP)
        return;    /* not ICMP */

    icmp = (struct icmp *)(ptr + hlen1);    /* start of ICMP header */
    if ((icmplen = len - hlen1) < 8)
        return;    /* malformed packet */

    if (icmp->icmp_type == ICMP_ECHOREPLY) {
        if (icmp->icmp_id != pid)
            return;    /* not a response to our ECHO_REQUEST */
        if (icmplen < 16)
            return;    /* not enough data to use */

        tvsend = (struct timeval *)icmp->icmp_data;
        tv_sub(tvrecv, tvsend);
        rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec / 1000.0;

        printf("%d bytes from %s: seq=%u, ttl=%d, rtt=%.3f ms\n",
        icmplen, Sock_ntop_host(pr->sarecv, pr->salen),
        icmp->icmp_seq, ip->ip_ttl, rtt);

    } 
    else if (verbose) 
    {
        printf(" %d bytes from %s: type = %d, code = %d\n",
        icmplen, Sock_ntop_host(pr->sarecv, pr->salen),
        icmp->icmp_type, icmp->icmp_code);
    }
}

void Gettimeofday(struct timeval *tv, void *foo)
{
    if (gettimeofday(tv, foo) == -1)
        err_sys("gettimeofday error");
    return;
}

uint16_t in_cksum(uint16_t * addr, int len)
{
    int nleft = len;
    uint32_t sum = 0;
    uint16_t *w = addr;
    uint16_t answer = 0;

    /*
    * Our algorithm is simple, using a 32 bit accumulator (sum), we add
    * sequential 16 bit words to it, and at the end, fold back all the
    * carry bits from the top 16 bits into the lower 16 bits.
    */
    while (nleft > 1) {
        sum += *w++;
        nleft -= 2;
    }

    /* 4mop up an odd byte, if necessary */
    if (nleft == 1) {
        *(unsigned char *)(&answer) = *(unsigned char *)w;
        sum += answer;
    }

    /* 4add back carry outs from top 16 bits to low 16 bits */
    sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
    sum += (sum >> 16);    /* add carry */
    answer = ~sum;    /* truncate to 16 bits */
    return (answer);
}

void
Sendto(int fd, const void *ptr, size_t nbytes, int flags,
const struct sockaddr *sa, socklen_t salen)
{
    if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)
    err_sys("sendto error");
}

void send_v4(void)
{
    int len;
    struct icmp *icmp;

    icmp = (struct icmp *)sendbuf;
    icmp->icmp_type = ICMP_ECHO;
    icmp->icmp_code = 0;
    icmp->icmp_id = pid;
    icmp->icmp_seq = nsent++;
    memset(icmp->icmp_data, 0xa5, datalen);    /* fill with pattern */
    Gettimeofday((struct timeval *)icmp->icmp_data, NULL);

    len = 8 + datalen;    /* checksum ICMP header and data */
    icmp->icmp_cksum = 0;
    icmp->icmp_cksum = in_cksum((u_short *) icmp, len);

    Sendto(sockfd, sendbuf, len, 0, pr->sasend, pr->salen);
}

int datalen = 56;    /* data that goes with ICMP echo request */

typedef void Sigfunc(int);    /* for signal handlers */
Sigfunc *signal(int signo, Sigfunc * func)
{
    struct sigaction act, oact;

    act.sa_handler = func;
    sigemptyset(&act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM) {
        #ifdef    SA_INTERRUPT
        act.sa_flags |= SA_INTERRUPT;    /* SunOS 4.x */
        #endif
    } else {
        #ifdef    SA_RESTART
        act.sa_flags |= SA_RESTART;    /* SVR4, 44BSD */
        #endif
    }
    if (sigaction(signo, &act, &oact) < 0)
        return (SIG_ERR);
    return (oact.sa_handler);
}

Sigfunc *Signal(int signo, Sigfunc * func)
{    /* for our signal() function */
    Sigfunc *sigfunc;

    if ((sigfunc = signal(signo, func)) == SIG_ERR)
        err_sys("signal error");
    return (sigfunc);
}

struct addrinfo *Host_serv(const char *host, const char *serv, int family,int socktype)
{
    int n;
    struct addrinfo hints, *res;

    bzero(&hints, sizeof(struct addrinfo));
    hints.ai_flags = AI_CANONNAME;    /* always return canonical name */
    hints.ai_family = family;    /* 0, AF_INET, AF_INET6, etc. */
    hints.ai_socktype = socktype;    /* 0, SOCK_STREAM, SOCK_DGRAM, etc. */

    if ((n = getaddrinfo(host, serv, &hints, &res)) != 0)
        err_quit("host_serv error for %s, %s: %s",
            (host == NULL) ? "(no hostname)" : host,
            (serv == NULL) ? "(no service name)" : serv,
            gai_strerror(n));

    return (res);    /* return pointer to first on linked list */
}

void *Calloc(size_t n, size_t size)
{
    void *ptr;

    if ((ptr = calloc(n, size)) == NULL)
        err_sys("calloc error");
    return (ptr);
}

void sig_alrm(int signo)
{
    (*pr->fsend) ();

    alarm(1);
    return;
}

int Socket(int family, int type, int protocol)
{
    int n;

    if ((n = socket(family, type, protocol)) < 0)
        err_sys("socket error");
    return (n);
}

void readloop(void)
{
    int size;
    char recvbuf[BUFSIZE];
    char controlbuf[BUFSIZE];
    struct msghdr msg;
    struct iovec iov;
    ssize_t n;
    struct timeval tval;

    sockfd = Socket(pr->sasend->sa_family, SOCK_RAW, pr->icmpproto);
    setuid(getuid());    /* don't need special permissions any more */
    if (pr->finit)
        (*pr->finit) ();

    size = 60 * 1024;    /* OK if setsockopt fails */
    setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));

    sig_alrm(SIGALRM);    /* send first packet */

    iov.iov_base = recvbuf;
    iov.iov_len = sizeof(recvbuf);
    msg.msg_name = pr->sarecv;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = controlbuf;
    for (;;) {
        msg.msg_namelen = pr->salen;
        msg.msg_controllen = sizeof(controlbuf);
        n = recvmsg(sockfd, &msg, 0);
        if (n < 0) {
            if (errno == EINTR)
            continue;
            else
            err_sys("recvmsg error");
        }

        Gettimeofday(&tval, NULL);
        (*pr->fproc) (recvbuf, n, &msg, &tval);
    }
}

void proc_v6(char *ptr, ssize_t len, struct msghdr *msg, struct timeval *tvrecv)
{
    #ifdef    IPV6
    double rtt;
    struct icmp6_hdr *icmp6;
    struct timeval *tvsend;
    struct cmsghdr *cmsg;
    int hlim;

    icmp6 = (struct icmp6_hdr *)ptr;
    if (len < 8)
    return;    /* malformed packet */

    if (icmp6->icmp6_type == ICMP6_ECHO_REPLY) {
        if (icmp6->icmp6_id != pid)
        return;    /* not a response to our ECHO_REQUEST */
        if (len < 16)
        return;    /* not enough data to use */

        tvsend = (struct timeval *)(icmp6 + 1);
        tv_sub(tvrecv, tvsend);
        rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec / 1000.0;

        hlim = -1;
        for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
        cmsg = CMSG_NXTHDR(msg, cmsg)) {
            if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_HOPLIMIT) {
                hlim = *(u_int32_t *) CMSG_DATA(cmsg);
                break;
            }
        }
    printf("%d bytes from %s: seq=%u, hlim=",
    len, Sock_ntop_host(pr->sarecv, pr->salen),
    icmp6->icmp6_seq);
    if (hlim == -1)
    printf("???");    /* ancillary data missing */
    else
    printf("%d", hlim);
    printf(", rtt=%.3f ms\n", rtt);
    } else if (verbose) {
        printf(" %d bytes from %s: type = %d, code = %d\n",
        len, Sock_ntop_host(pr->sarecv, pr->salen),
        icmp6->icmp6_type, icmp6->icmp6_code);
    }
#endif    /* IPV6 */
}

void send_v6()
{
#ifdef    IPV6
    int len;
    struct icmp6_hdr *icmp6;

    icmp6 = (struct icmp6_hdr *)sendbuf;
    icmp6->icmp6_type = ICMP6_ECHO_REQUEST;
    icmp6->icmp6_code = 0;
    icmp6->icmp6_id = pid;
    icmp6->icmp6_seq = nsent++;
    memset((icmp6 + 1), 0xa5, datalen);    /* fill with pattern */
    Gettimeofday((struct timeval *)(icmp6 + 1), NULL);

    len = 8 + datalen;    /* 8-byte ICMPv6 header */

    Sendto(sockfd, sendbuf, len, 0, pr->sasend, pr->salen);
    /* 4kernel calculates and stores checksum for us */
#endif    /* IPV6 */
}

void init_v6()
{
#ifdef IPV6
    int on = 1;

    if (verbose == 0) {
        /* install a filter that only passes ICMP6_ECHO_REPLY unless verbose */
        struct icmp6_filter myfilt;
        ICMP6_FILTER_SETBLOCKALL(&myfilt);
        ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &myfilt);
        setsockopt(sockfd, IPPROTO_IPV6, ICMP6_FILTER, &myfilt,
        sizeof(myfilt));
        /* ignore error return; the filter is an optimization */
    }

/* ignore error returned below; we just won't receive the hop limit */
#ifdef IPV6_RECVHOPLIMIT
/* RFC 3542 */
setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on));
#else
/* RFC 2292 */
setsockopt(sockfd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
#endif
#endif
}
struct proto proto_v4 = { proc_v4, send_v4, NULL, NULL, NULL, 0, IPPROTO_ICMP };

#ifdef    IPV6
struct proto proto_v6 =
{ proc_v6, send_v6, init_v6, NULL, NULL, 0, IPPROTO_ICMPV6 };
#endif
int main(int argc, char **argv)
{
    int c;
    struct addrinfo *ai;
    char *h;

    opterr = 0;    /* don't want getopt() writing to stderr */
    while ((c = getopt(argc, argv, "v")) != -1) {
        switch (c) {
            case 'v':
            verbose++;
            break;

            case '?':
            err_quit("unrecognized option: %c", c);
        }
    }

    if (optind != argc - 1)
        err_quit("usage: ping [ -v ] <hostname>");
    host = argv[optind];

    pid = getpid() & 0xffff;    /* ICMP ID field is 16 bits */
    Signal(SIGALRM, sig_alrm);

    ai = Host_serv(host, NULL, 0, 0);

    h = Sock_ntop_host(ai->ai_addr, ai->ai_addrlen);
    printf("PING %s (%s): %d data bytes\n",
    ai->ai_canonname ? ai->ai_canonname : h, h, datalen);

    /* 4initialize according to protocol */
    if (ai->ai_family == AF_INET) {
        pr = &proto_v4;
        #ifdef    IPV6
    } else if (ai->ai_family == AF_INET6) {
        pr = &proto_v6;
        if (IN6_IS_ADDR_V4MAPPED(&(((struct sockaddr_in6 *)
        ai->ai_addr)->sin6_addr)))
        err_quit("cannot ping IPv4-mapped IPv6 address");
        #endif
    } else
        err_quit("unknown address family %d", ai->ai_family);

    pr->sasend = ai->ai_addr;
    pr->sarecv = Calloc(1, ai->ai_addrlen);
    pr->salen = ai->ai_addrlen;

    readloop();

    exit(0);
}
View Code

Windows下的ping程序

/*Ping程序源码(无注释)校园的课程设计*/
//Ping.h

#define WIN32_LEAN_AND_MEAN
#include<windows.h>
#include<winsock2.h>
#include<ws2tcpip.h>
#include<stdio.h>
#include<stdlib.h>

typedef struct tagIP_HEADER{
    unsigned int h_len:4;
    unsigned int ver:4;
    unsigned char tos;
    unsigned short total_len;
    unsigned short ident;
    unsigned short frag_floags;
    unsigned char ttl;
    unsigned char protocol;
    unsigned short checksum;
    unsigned int sourceip;
    unsigned int destip;
}IP_HEADER,*PIP_HEADER;

typedef struct tagIP_OPT_HEADER{
    unsigned char code;
    unsigned char len;
    unsigned char ptr;
    unsigned long addr[9];
}IP_OPT_HEADER,*PIP_OPT_HEADER;

typedef struct tagICMP_HEADER{
    unsigned char type;
    unsigned char code;
    unsigned short checksum;
    unsigned short id; 
    unsigned short seq;
    unsigned long timestamp;
}ICMP_HEADER,*PICMP_HEADER;

#define DEF_PACKET_SIZE 32
#define MAX_PACKET_SIZE 1024
#define ICMP_ECHO 8
#define ICMP_ECHOREPLY 0
#define IP_RECORD_ROUTER 7

void usageinfo(char *progname);
void FillIcmpData(char *icmp_data,int size);
USHORT CheckSum(USHORT *buf,int size);
void DecodeIcmpHeader(char *buf,int ret,LPSOCKADDR_IN lpSin);
void DecodeIpHeader(char *buf,int bytes);



//Ping.cpp

#include<stdio.h>
#include"Ping.h"

#pragma comment(lib,"ws2_32")

int main(int argc,char *argv[])
{
    if(argc==1)
    {
        usageinfo(argv[0]);
        return -1;
    }

    BOOL bRecordRout =FALSE;
    SOCKET hSocket =INVALID_SOCKET;
    SOCKADDR_IN dstSin;
    SOCKADDR_IN fromSin;
    IP_OPT_HEADER ipOptHeader;
    char* pIcmpData = NULL;
    char* pRecvData = NULL;
    char* lpDstIp =NULL;
    int datasize =DEF_PACKET_SIZE;
    int ret;
    int rcvNum;

    for(int i=1;i<argc;i++)
    {
        if(strchr(argv[i],'-')){
            switch(tolower(argv[i][1])){
            case 'r':
                bRecordRout=TRUE;
                break;
            case 'd':
                datasize=atoi(argv[i+1]);
                i=argc+1;
                break;
            }
        }else if(strchr(argv[i],'.')){
            int l=strlen(argv[i]);
            if(l<7||l>15)
                usageinfo(argv[0]);
            else
                lpDstIp=argv[i];
        }
    }

    WSADATA wsaData;
    WORD wVer=MAKEWORD(2,2);
    if(WSAStartup(wVer,&wsaData)!=0){
        printf("WSAStartup Error!\n");
        return -1;
    }

    hSocket =WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);
    if(hSocket==INVALID_SOCKET)
    {
        printf("WSASocket Error,Code:%d",WSAGetLastError());
        WSACleanup();
        return -1;
    }



    
    if(bRecordRout)
    {
        ZeroMemory(&ipOptHeader,sizeof(ipOptHeader));
        ipOptHeader.code=IP_RECORD_ROUTER;
        ipOptHeader.len=39;
        ipOptHeader.ptr=4;
        if((ret=setsockopt(hSocket,IPPROTO_IP,IP_OPTIONS,(char*)&ipOptHeader,sizeof(ipOptHeader)))==SOCKET_ERROR){
            printf("setsockopt(IP_OPTIONS)error,code:%d",WSAGetLastError());
            WSACleanup();
            closesocket(hSocket);
            return -1;
        }
    }


    int timeout=1000;
    if((ret=setsockopt(hSocket,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)))==SOCKET_ERROR)
    {
        printf("setsockopt(SO_RCVTIMEO)error,code:%d",WSAGetLastError());
        WSACleanup();
        closesocket(hSocket);
        return -1;
    }

    if((ret=setsockopt(hSocket,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout)))==SOCKET_ERROR){
        printf("setsockopt(SO_SNDTIMEO)error,code:%d",WSAGetLastError());
        WSACleanup();
        return -1;
    }

    pIcmpData=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET_SIZE);
    pRecvData=(char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MAX_PACKET_SIZE);
    if(pIcmpData==NULL||pRecvData==NULL)
    {
        printf("HeapAlloc Error\n");
        WSACleanup();
        return -1;
    }

    datasize+=sizeof(ICMP_HEADER);
    ZeroMemory(&dstSin,sizeof(dstSin));
    dstSin.sin_family=AF_INET;
    dstSin.sin_addr.s_addr =inet_addr(lpDstIp);
    FillIcmpData(pIcmpData,datasize);
    printf("Ping %s with %d bytes of data\n",inet_ntoa(dstSin.sin_addr),datasize);
    int count=0;
    int seq=0;
    rcvNum=0;

    while(1)
    {
        count++;
        if(count==5)
            break;
        ((PICMP_HEADER)pIcmpData)->checksum=0;
        ((PICMP_HEADER)pIcmpData)->seq=seq++;
        ((PICMP_HEADER)pIcmpData)->timestamp=GetTickCount();
        ((PICMP_HEADER)pIcmpData)->checksum=CheckSum((USHORT*)pIcmpData,datasize);

        if((ret=sendto(hSocket,pIcmpData,datasize,0,(LPSOCKADDR)&dstSin,sizeof(dstSin)))==SOCKET_ERROR){
            if(WSAGetLastError()==WSAETIMEDOUT){
                printf("time out.\n");
                continue;
            }else{
                printf("sendto error,code:%d",WSAGetLastError());
                closesocket(hSocket);
                WSACleanup();
                return -1;
            }
        }
        int fromLen=sizeof(fromSin);
        if((ret=recvfrom(hSocket,pRecvData,MAX_PACKET_SIZE,0,(sockaddr*)&fromSin,&fromLen))==SOCKET_ERROR){
            if(WSAGetLastError()==WSAETIMEDOUT)
            {
                printf("time out.\n");
                continue;
            }
            printf("recvform fail!\n");
            closesocket(hSocket);
            WSACleanup();
            return -1;
        }
        rcvNum++;
        DecodeIcmpHeader(pRecvData,ret,&fromSin);
     }

     printf("\n Ping Statistics for :%s\n",lpDstIp);
     printf("\t    Send=%d    Received=%d,Lost=%d    (%d%%loss)",4,rcvNum,4-rcvNum,(4-rcvNum)/4*100);
     if(hSocket!=INVALID_SOCKET)
        closesocket(hSocket);
     HeapFree(GetProcessHeap(),0,pIcmpData);
     HeapFree(GetProcessHeap(),0,pRecvData);
     WSACleanup();
     return 0;
}

void usageinfo(char *progname)
{
        printf("Ping tool,by blode(blode@peoplemail.com.cn\n)");
        printf("usage:ping[-r]<host ip>[-d][data size]\n");
        printf("\t-r:\trecord router\n");
        printf("\thost ip:\thost ip to ping\n");
        printf("\t-d:\tuse data size option\n");
        printf("\tdata size:\tdata size to ping(<=1024)\n");
}

void FillIcmpData(char *icmp_data,int size)
{
    ICMP_HEADER *icmpHdr;
    icmpHdr=(PICMP_HEADER)icmp_data;
    icmpHdr->checksum=0;
    icmpHdr->code=0;
    icmpHdr->id=(unsigned short)GetCurrentProcessId();
    icmpHdr->seq=0;
    icmpHdr->type=ICMP_ECHO;
    icmpHdr->timestamp=0;
}
USHORT CheckSum(USHORT *buf,int size)
{
    USHORT cksum=0;
    while(size>1)
    {
        cksum+=*buf++;
        size-=sizeof(USHORT);
    }
    if(size)
        cksum+=*buf++;
    cksum=(cksum>>16)+(cksum&0xffff);
    cksum+=(cksum>>16);
    return (USHORT)(~cksum);
}
void DecodeIcmpHeader(char *buf,int ret,LPSOCKADDR_IN lpSin)
{
    ICMP_HEADER *icmpHdr;
    IP_HEADER *ipHdr;
    int ipHdrLen;
    static int first=0;
    DWORD tick=GetTickCount();
    ipHdr=(IP_HEADER*)buf;
    ipHdrLen=ipHdr->h_len*4;
    if(ipHdrLen==60&&!first)
        DecodeIpHeader(buf,ret);
        icmpHdr=(ICMP_HEADER *)(buf+ipHdrLen);
    if(icmpHdr->type!=ICMP_ECHOREPLY){
        printf("no echo reply %d recved\n",icmpHdr->type);
        return ;
    }
    if(icmpHdr->id!=(USHORT)GetCurrentProcessId()){
        printf("someone else's packet!\n");
        return;
    }
    printf("Reply form: %s",inet_ntoa(lpSin->sin_addr));
    printf("\tbytes: %d icmp seq: %d TTL=128",ret,icmpHdr->seq);
    printf("time: %dms\n",tick-icmpHdr->timestamp);
    first++;
        return;
}
void DecodeIpHeader(char *buf,int bytes)
{
    IP_OPT_HEADER *ipOptHdr;
    IN_ADDR in;
        ipOptHdr=(IP_OPT_HEADER *)(buf+20);
    printf("Record Router:");
    for(int i=0;i<(ipOptHdr->ptr/4)-1;i++){
        in.S_un.S_addr=ipOptHdr->addr[i];
        printf("\t%-15s\n",inet_ntoa(in));
    }
}
View Code

posted on 2015-10-23 00:04  步孤天  阅读(701)  评论(0)    收藏  举报