Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Raw Ping (IPv6) 
:(
    Опции темы
suxxor
Дата 6.2.2012, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 14.10.2010

Репутация: нет
Всего: нет



Что нужно сделать чтобы этот код (источник) заработал для версии протокола IPv6?

Код

#define WIN32_LEAN_AND_MEAN        // Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <cstdio>
#include <winsock2.h>
#include <windows.h>

struct ICMPheader
{
    unsigned char    byType;
    unsigned char    byCode;
    unsigned short    nChecksum;
    unsigned short    nId;
    unsigned short    nSequence;
};

struct IPheader
{
    unsigned char    byVerLen;        
    unsigned char    byTos;       
    unsigned short    nTotalLength;   
    unsigned short    nId;            
    unsigned short    nOffset;        
    unsigned char    byTtl;          
    unsigned char    byProtocol;     
    unsigned short    nChecksum;      
    unsigned int    nSrcAddr;       
    unsigned int    nDestAddr;      
};

using namespace std;

unsigned short CalcChecksum (char *pBuffer, int nLen);
bool ValidateChecksum (char *pBuffer, int nLen);
bool Initialize ();
bool UnInitialize ();
bool ResolveIP (char *pszRemoteHost, char **pszIPAddress);
void PrintUsage ();

int main(int argc, char* argv[])
{
    if (argc < 2 || argc > 5)
    {
        PrintUsage ();
        return 0;
    }

    if (Initialize () == false)
    {
        return -1;
    }

    int nSequence = 0;
    int nMessageSize = 32;    //The message size that the ICMP echo request should carry with it
    int nTimeOut = 5000;    //Request time out for echo request (in milliseconds)
    int nCount = 4;    //Number of times the request has to be send

    char *pszRemoteIP = NULL, *pSendBuffer = NULL, *pszRemoteHost = NULL;

    pszRemoteHost = argv [1];
    
    for (int i = 2; i < argc; ++i)
    {
        switch (i)
        {
        case 2:            
            nCount = atoi (argv [2]);
            break;
        case 3:
            nMessageSize = atoi (argv [3]);
            break;
        case 4:
            nTimeOut = atoi (argv [4]);
            break;
        }
    }

    if (ResolveIP (pszRemoteHost, &pszRemoteIP) == false)
    {
        cerr << endl << "Unable to resolve hostname" << endl;
        return -1;
    }

    cout << "Pinging " << pszRemoteHost << " [" << pszRemoteIP << "] with " << nMessageSize << " bytes of data." << endl << endl;
    ICMPheader sendHdr;

    SOCKET sock;
    sock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);    //Create a raw socket which will use ICMP

    SOCKADDR_IN dest;    //Dest address to send the ICMP request
    dest.sin_addr.S_un.S_addr = inet_addr (pszRemoteIP);
    dest.sin_family = AF_INET;
    dest.sin_port = rand ();    //Pick a random port

    int nResult = 0;

    fd_set fdRead;
    SYSTEMTIME timeSend, timeRecv;
    int nTotalRoundTripTime = 0, nMaxRoundTripTime = 0, nMinRoundTripTime = -1, nRoundTripTime = 0;
    int nPacketsSent = 0, nPacketsReceived = 0;

    timeval timeInterval = {0, 0};
    timeInterval.tv_usec = nTimeOut * 1000;
    
    sendHdr.nId = htons (rand ());    //Set the transaction Id

    while (nPacketsSent < nCount)
    {
        //Create the message buffer, which is big enough to store the header and the message data
        pSendBuffer = new char [sizeof (ICMPheader) + nMessageSize];

        sendHdr.byCode = 0;    //Zero for ICMP echo and reply messages
        sendHdr.nSequence = htons (nSequence++);
        sendHdr.byType = 8;    //Eight for ICMP echo message
        sendHdr.nChecksum = 0;    //Checksum is calculated later on

        memcpy_s (pSendBuffer, sizeof (ICMPheader), &sendHdr, sizeof (ICMPheader));    //Copy the message header in the buffer
        memset (pSendBuffer + sizeof (ICMPheader), 'x', nMessageSize);    //Fill the message with some arbitary value

        //Calculate checksum over ICMP header and message data
        sendHdr.nChecksum = htons (CalcChecksum (pSendBuffer, sizeof (ICMPheader) + nMessageSize));    

        //Copy the message header back into the buffer
        memcpy_s (pSendBuffer, sizeof (ICMPheader), &sendHdr, sizeof (ICMPheader));

        nResult = sendto (sock, pSendBuffer, sizeof (ICMPheader) + nMessageSize, 0, (SOCKADDR *)&dest, sizeof (SOCKADDR_IN));
        
        //Save the time at which the ICMP echo message was sent
        ::GetSystemTime (&timeSend);

        ++nPacketsSent;

        if (nResult == SOCKET_ERROR)
        {
            cerr << endl << "An error occured in sendto operation: " << "WSAGetLastError () = " << WSAGetLastError () << endl;
            UnInitialize ();
            delete []pSendBuffer;
            return -1;
        }
        
        FD_ZERO (&fdRead);
        FD_SET (sock, &fdRead);

        if ((nResult = select (0, &fdRead, NULL, NULL, &timeInterval))
            == SOCKET_ERROR)
        {
            cerr << endl << "An error occured in select operation: " << "WSAGetLastError () = " << 
                WSAGetLastError () << endl;
            delete []pSendBuffer;
            return -1;
        }

        if (nResult > 0 && FD_ISSET (sock, &fdRead))
        {
            //Allocate a large buffer to store the response
            char *pRecvBuffer = new char [1500];

            if ((nResult = recvfrom (sock, pRecvBuffer, 1500, 0, 0, 0)) 
                == SOCKET_ERROR)
            {
                cerr << endl << "An error occured in recvfrom operation: " << "WSAGetLastError () = " << 
                    WSAGetLastError () << endl;
                UnInitialize ();
                delete []pSendBuffer;
                delete []pRecvBuffer;
                return -1;
            }
            
            //Get the time at which response is received
            ::GetSystemTime (&timeRecv);

            //We got a response so we construct the ICMP header and message out of it
            ICMPheader recvHdr;
            char *pICMPbuffer = NULL;

            //The response includes the IP header as well, so we move 20 bytes ahead to read the ICMP header
            pICMPbuffer = pRecvBuffer + sizeof(IPheader);

            //ICMP message length is calculated by subtracting the IP header size from the 
            //total bytes received
            int nICMPMsgLen = nResult - sizeof(IPheader);

            //Construct the ICMP header
            memcpy_s (&recvHdr, sizeof (recvHdr), pICMPbuffer, sizeof (recvHdr));

            //Construct the IP header from the response
            IPheader ipHdr;
            memcpy_s (&ipHdr, sizeof (ipHdr), pRecvBuffer, sizeof (ipHdr));

            recvHdr.nId = recvHdr.nId;
            recvHdr.nSequence = recvHdr.nSequence;
            recvHdr.nChecksum = ntohs (recvHdr.nChecksum);

            //Check if the response is an echo reply, transaction ID and sequence number are same
            //as for the request, and that the checksum is correct
            if (recvHdr.byType == 0 &&
                recvHdr.nId == sendHdr.nId &&
                recvHdr.nSequence == sendHdr.nSequence &&
                ValidateChecksum (pICMPbuffer, nICMPMsgLen)  && 
                memcmp (pSendBuffer + sizeof(ICMPheader), pRecvBuffer + sizeof (ICMPheader) + sizeof(IPheader), 
                    nResult - sizeof (ICMPheader) - sizeof(IPheader)) == 0)
            {
                //All's OK
                int nSec = timeRecv.wSecond - timeSend.wSecond;
                if (nSec < 0)
                {
                    nSec = nSec + 60;
                }

                int nMilliSec = abs (timeRecv.wMilliseconds - timeSend.wMilliseconds);

                int nRoundTripTime = 0;
                nRoundTripTime = abs (nSec * 1000 - nMilliSec);

                cout << "Reply from " << pszRemoteIP << ": bytes = " << nResult - sizeof (ICMPheader) - sizeof (IPheader) 
                    << ", time = " << nRoundTripTime << "ms, TTL = " << (int)ipHdr.byTtl << endl;

                nTotalRoundTripTime = nTotalRoundTripTime + nRoundTripTime;

                if (nMinRoundTripTime == -1)
                {
                    nMinRoundTripTime = nRoundTripTime;
                    nMaxRoundTripTime = nRoundTripTime;
                }
                else if (nRoundTripTime < nMinRoundTripTime)
                {
                    nMinRoundTripTime = nRoundTripTime;
                }
                else if (nRoundTripTime > nMaxRoundTripTime)
                {
                    nMaxRoundTripTime = nRoundTripTime;
                }

                ++nPacketsReceived;
            }
            else
            {
                cout << "The echo reply is not correct!" << endl;
            }

            delete []pRecvBuffer;
        }
        else
        {
            cout << "Request timed out." << endl;
        }

        delete []pSendBuffer;
    }

    cout << endl << "Ping statistics for " << pszRemoteIP << ":" << endl << '\t' << "Packets: Sent = " << nPacketsSent << ", Received = " << 
        nPacketsReceived << ", Lost = " << (nPacketsSent - nPacketsReceived) << " (" << 
        ((nPacketsSent - nPacketsReceived)/(float)nPacketsSent) * 100 << "% loss)" << endl << '\t';

    if (nPacketsReceived > 0)
    {
        cout << "\rApproximate round trip times in milli-seconds:" << endl << '\t' << "Minimum = " << nMinRoundTripTime << 
            "ms, Maximum = " << nMaxRoundTripTime << "ms, Average = " << nTotalRoundTripTime / (float)nPacketsReceived << "ms" << endl;
    }

    cout << '\r' << endl;

    if (UnInitialize () == false)
    {
        return -1;
    }

    return 0;
}

unsigned short CalcChecksum (char *pBuffer, int nLen)
{
    //Checksum for ICMP is calculated in the same way as for
    //IP header

    //This code was taken from: http://www.netfor2.com/ipsum.htm

    unsigned short nWord;
    unsigned int nSum = 0;
    int i;
    
    //Make 16 bit words out of every two adjacent 8 bit words in the packet
    //and add them up
    for (i = 0; i < nLen; i = i + 2)
    {
        nWord =((pBuffer [i] << 8)& 0xFF00) + (pBuffer [i + 1] & 0xFF);
        nSum = nSum + (unsigned int)nWord;    
    }
    
    //Take only 16 bits out of the 32 bit sum and add up the carries
    while (nSum >> 16)
    {
        nSum = (nSum & 0xFFFF) + (nSum >> 16);
    }

    //One's complement the result
    nSum = ~nSum;
    
    return ((unsigned short) nSum);
}

bool ValidateChecksum (char *pBuffer, int nLen)
{
    unsigned short nWord;
    unsigned int nSum = 0;
    int i;
    
    //Make 16 bit words out of every two adjacent 8 bit words in the packet
    //and add them up
    for (i = 0; i < nLen; i = i + 2)
    {
        nWord =((pBuffer [i] << 8)& 0xFF00) + (pBuffer [i + 1] & 0xFF);
        nSum = nSum + (unsigned int)nWord;    
    }
    
    //Take only 16 bits out of the 32 bit sum and add up the carries
    while (nSum >> 16)
    {
        nSum = (nSum & 0xFFFF) + (nSum >> 16);
    }

    //To validate the checksum on the received message we don't complement the sum
    //of one's complement
    //One's complement the result
    //nSum = ~nSum;
    
    //The sum of one's complement should be 0xFFFF
    return ((unsigned short)nSum == 0xFFFF);
}

bool Initialize ()
{
    //Initialize WinSock
    WSADATA wsaData;

    if (WSAStartup (MAKEWORD (2, 2), &wsaData) == SOCKET_ERROR)
    {
        cerr << endl << "An error occured in WSAStartup operation: " << "WSAGetLastError () = " << WSAGetLastError () << endl;
        return false;
    }

    SYSTEMTIME time;
    ::GetSystemTime (&time);

    //Seed the random number generator with current millisecond value
    srand (time.wMilliseconds);

    return true;
}

bool UnInitialize ()
{
    //Cleanup
    if (WSACleanup () == SOCKET_ERROR)
    {
        cerr << endl << "An error occured in WSACleanup operation: WSAGetLastError () = " << WSAGetLastError () << endl;
        return false;
    }

    return true;
}

bool ResolveIP (char *pszRemoteHost, char **pszIPAddress)
{
    hostent *pHostent = gethostbyname (pszRemoteHost);
    if (pHostent == NULL)
    {
        cerr << endl << "An error occured in gethostbyname operation: WSAGetLastError () = " << WSAGetLastError () << endl;
        return false;
    }

    in_addr in;
    memcpy_s (&in, sizeof (in_addr), pHostent->h_addr_list [0], sizeof (in_addr));
    *pszIPAddress = inet_ntoa (in);

    return true;
}

void PrintUsage ()
{
    cout << "Usage: ping r n b t" << endl << endl;
    cout << "  r - Remote host" << endl;
    cout << "  n - Number of echo requests to send" << endl;
    cout << "  b - Bytes to send" << endl;
    cout << "  t - Timeout after these many milliseconds" << endl << endl;

    cout << "\rping microsoft.com 4 32 4000" << endl << endl;
}


Вроде для ICMPv6 и структуры другие

Это сообщение отредактировал(а) suxxor - 6.2.2012, 22:06
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0505 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.