Windows Vista Forums

Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Server 20

  1. #1



    Newbie
    Join Date : Apr 2009
    Posts : 3
    Vista 32 bit
    Local Time: 02:48 PM

    Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Server 20

    Hi Guys,
    For a reqt, we are doing ping and traceroute on our application using Raw Sockets. This code supports both IPv4 and IPv6. On IPv4 environment, both ping and traceroute works fine in Vista / Non Vista (Win XP, Win 2003). But on IPv6 environment, both ping and tracroute are working fine only on Vista and not working on Windows XP or Windows 2003. We tried with ethereal and captured all the packets that are being send during ping. It says that "checksum incorrect" in the ping request. When gone through ICMPv6 RFC, they mentioned that checksum has to be calculated along with Pseudo-header. We included pseudo-header based on the information provided on sites, that didn't worked. We tried various options on pseudo header by including and not including source address, destination address. But nothing worked.
    Kindly note that ping and traceroute are working fine from command line using ping and tracert on Win XP / Win 2003 in IPv6 environment. While going through some sites and forums I came to know that IPv6 is not completely implemented on Win XP or Win Server 2003. Is it causing this problem?

    The issues I guess here are,

    * Checksum calculation have some issues
    * Pseudo-header format and its size that we mentioned may be incorrect
    * IPv6 may not work on Win XP / Win 2003. If this is the case, how to get this one work on Win XP and Win 2003 (both 32 and 64 bits)

    The following is the part of source code that fills ICMP data and calculate checksum.

    Code:

    // ICMP packet types
    #define ICMP_ECHO_REPLY 0
    #define ICMP_ECHO_REPLY_V6 129

    #define ICMP_DEST_UNREACH 3
    #define ICMP_DEST_UNREACH_V6 1

    #define ICMP_TTL_EXPIRE 11
    #define ICMP_TTL_EXPIRE_V6 3

    #define ICMP_ECHO_REQUEST 8
    #define ICMP_ECHO_REQUEST_V6 128

    // ICMP header structure
    typedef struct _icmpHdr
    {
    unsigned char i_type; // ICMP packet type
    unsigned char i_code; // Sub code type
    unsigned short i_checksum; // ICMP Checksum
    unsigned short i_id; // Process Id
    unsigned short i_seq; // ICMP Sequence number
    //
    // This is not the std header, but we reserve space for time
    //
    unsigned long i_ulTimeStamp;
    } ICMPHeader;

    // Fill in ICMP Packet field
    void ping::InitICMPData(char* cHdrPing, int nPacketSize, int nSeqNo, struct addrinfo* dest)
    {
    ICMPHeader *icHdrPing;
    char *datapart;
    int family = dest->ai_family ;

    if(AF_INET6 == family)
    {
    //memcpy( cHdrPing + 16 , (void *)&(((struct sockaddr_in6 *)dest->ai_addr)->sin6_addr.u) , 16);
    *(cHdrPing + 32) = 40 ;
    *(cHdrPing + 39) = 58;
    icHdrPing = (ICMPHeader*)(cHdrPing + 40);
    nPacketSize += 40;
    }
    else
    {
    icHdrPing = (ICMPHeader*)cHdrPing;
    }

    icHdrPing->i_type = AF_INET6 == family ? ICMP_ECHO_REQUEST_V6:ICMP_ECHO_REQUEST;
    icHdrPing->i_code = 0;
    icHdrPing->i_checksum = 0;

    icHdrPing->i_id = htons(whatIsProcessId());
    icHdrPing->i_seq = htons(nSeqNo);
    icHdrPing->i_ulTimeStamp = GetTickCount ();

    datapart = (char *)icHdrPing + sizeof(ICMPHeader);

    memset(datapart,'E', 32);
    // Calculate a checksum on the result
    icHdrPing->i_checksum = CalcCheckSum((unsigned short*)cHdrPing, nPacketSize);
    printf("TYPE = %d\n" , icHdrPing->i_type);
    printf("CHECk = %x\n" , icHdrPing->i_checksum);

    printf("End of InitICMPdata\n");
    }

    // Calculate check sum of the packet
    unsigned short ping::CalcCheckSum(unsigned short* usBuffer, int nSize)
    {
    unsigned long ulChkSum = 0;

    while(nSize > 1)
    {
    ulChkSum += *usBuffer++;
    nSize -= sizeof(unsigned short);
    }

    if (nSize)
    {
    ulChkSum += *(unsigned char*)usBuffer;
    }

    ulChkSum = (ulChkSum >> 16) + (ulChkSum & 0xffff);
    ulChkSum += (ulChkSum >> 16);

    return (unsigned short)(~ulChkSum);
    }

    As it is a very critical reqt. we have to fix this problem immediately. Please help me find a solution on this issue to get this work on Win XP / Win 2003.

    Thanks in advance.


    Thanks and regards,
    Vignesh

    Last edited by vigneshp; 27 Apr 2009 at 11:40 PM.
      My System SpecsSystem Spec

  2.   


  3. #2
    H2SO4's Avatar

    A bit of a numpty
    Join Date : Mar 2009
    Australia
    Posts : 1,241
    Win7x64
    Local Time: 03:18 AM
    australia

     

    Re: Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Serve

    Under XP and Win2k3, IPv6 was implemented as a separate network stack - not part of the monolithic tcpip.sys transport. Therefore, if the same compiled binary does what you want it to do under Vista, odds are that you are indeed encountering a problem with the older XP/2k3 IPv6 implementation.

    One thing I'd suggest is that you completely disable the NIC's checksum offload capabilities while you're conducting your tests. There's always a possibility that the NDIS5 NIC driver under XP/2k3 is interfering and skewing your results.

      My System SpecsSystem Spec

  4. #3



    Newbie
    Join Date : Apr 2009
    Posts : 3
    Vista 32 bit
    Local Time: 02:48 PM


      Thread Starter

    Re: Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Serve

    Thanks for the reply.

    I tried your suggestion on my Win 2k3 machine to disable NIC's checksum offload capabilities. I did this in registry at,

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

    by setting DisableTaskOffload to 1


    But checksum is still failing when I try to ping IPv6 machine.


    Can you please answer my following questions:


    1. In ICMPv6 RFC they mentioned that pseudo-header is required to be included to calculate checksum. In vista and unix, checksum calculation is automatically done by kernel, but not in Win2k3 or Win Xp. If I include pseudo-header and calculate checksum, will it work on these platforms?


    2. To perform ping or traceroute programatically on Win XP and Win 2k3, whatelse I have to do? Please go through by code above and let me know what is the mistake I am doing while calculating checksum along with pseudo-header.


    If you look into the InitICMPData(char* cHdrPing, int nPacketSize, int nSeqNo, struct addrinfo* dest) method you will find that it is matching RFC 4443. What I am trying to do there is fill the pseudo header, put ICMP header data and then I am trying to pass those data for calculating checksum. Based on the pseudo header information provided in RFC, i copy values in the case of IPv6 as follows. I have provided comments inline in the code.


    ICMPHeader *icHdrPing;
    char *datapart;
    int family = dest->ai_family ;

    if(AF_INET6 == family)
    {
    // Pseudo header starts here
    // Here I copy destination address
    memcpy( cHdrPing + 16 , (void *)&(((struct sockaddr_in6 *)dest->ai_addr)->sin6_addr.u) , 16);
    // Upper layer packet length is provided here
    *(cHdrPing + 32) = 40 ;
    // This is next header
    *(cHdrPing + 39) = 58;
    // Copying cHdrPing from 40th location into icHdrPing
    icHdrPing = (ICMPHeader*)(cHdrPing + 40);
    nPacketSize += 40;
    }
    else
    {
    icHdrPing = (ICMPHeader*)cHdrPing;
    }

    // Now filling ICMPv6 header data
    icHdrPing->i_type = AF_INET6 == family ? ICMP_ECHO_REQUEST_V6:ICMP_ECHO_REQUEST;
    icHdrPing->i_code = 0;
    // Initially setting checksum to 0
    icHdrPing->i_checksum = 0;
    icHdrPing->i_id = htons(whatIsProcessId());
    icHdrPing->i_seq = htons(nSeqNo);
    icHdrPing->i_ulTimeStamp = GetTickCount ();

    datapart = (char *)icHdrPing + sizeof(ICMPHeader);

    memset(datapart,'E', 32);
    // Now calculating checksum for the pseudo header + ICMP header. cHdrPing variable have those data in it. Checksum is now calculated for that data here
    icHdrPing->i_checksum = CalcCheckSum((unsigned short*)cHdrPing, nPacketSize);
    printf("TYPE = %d\n" , icHdrPing->i_type);
    printf("CHECk = %x\n" , icHdrPing->i_checksum);

    printf("End of InitICMPdata\n");
    }


    Please help me solve this problem as it is very important.


    Thanks,
    Vignesh

      My System SpecsSystem Spec

  5. #4
    H2SO4's Avatar

    A bit of a numpty
    Join Date : Mar 2009
    Australia
    Posts : 1,241
    Win7x64
    Local Time: 03:18 AM
    australia

     

    Re: Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Serve

    Here's your answer ===> Windows Server 2003 does not set the value of the icmp6_cksum field in the icmp6_hdr structure for ICMPv6 packets

    "In this scenario, the value of the icmp6_cksum field in the icmp6_hdr structure is still 0 in the transmitted packet. This behavior does not comply with the RFC 3542 requirements. This behavior causes the functions of some applications to fail if the following conditions are true:
    • The application uses the ICMPv6 protocol.
    • The application expects Windows Server 2003 to set the value of the icmp6_cksum field."

    Looks like the hotfix was not ported to 32-bit XP though, for what that's worth. If the clients which are going to be running your app are unmanaged, then getting them to install hotfixes is like herding cats anyway. If they are managed, it may be easier to install Vista and thus save everyone a few IPv6 headaches.

      My System SpecsSystem Spec

  6. #5



    Newbie
    Join Date : Apr 2009
    Posts : 3
    Vista 32 bit
    Local Time: 02:48 PM


      Thread Starter

    Re: Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Serve

    Thanks H2SO4. I have identified the problem and fixed it and is working fine. The problem is in payload size that I am putting in pseudo-header. The payload size variable size is 4 bytes (i.e) 32nd byte of pseudo-header. I was placing payload size at 32nd position, but it should be at 35th position (that is at 4th byte). That means the value should be stored in big endian format. Also another issue I was facing with source address. Initially i was not filling it. After filling the source address, it is able to ping and traceroute IPv6 on both Xp and Win2k3.

    Thanks a lot again..

    - Vignesh P

      My System SpecsSystem Spec

  7. #6
    H2SO4's Avatar

    A bit of a numpty
    Join Date : Mar 2009
    Australia
    Posts : 1,241
    Win7x64
    Local Time: 03:18 AM
    australia

     

    Re: Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Serve

    Quote Originally Posted by vigneshp View Post
    Thanks H2SO4. I have identified the problem and fixed it and is working fine. The problem is in payload size that I am putting in pseudo-header. The payload size variable size is 4 bytes (i.e) 32nd byte of pseudo-header. I was placing payload size at 32nd position, but it should be at 35th position (that is at 4th byte). That means the value should be stored in big endian format. Also another issue I was facing with source address. Initially i was not filling it. After filling the source address, it is able to ping and traceroute IPv6 on both Xp and Win2k3.

    Thanks a lot again..

    - Vignesh P
    Glad to hear those changes allowed the app to start working, though I'm not sure I understand how it would've previously worked in Vista if the payload field contents were off by a dword or even reversed.

      My System SpecsSystem Spec


Ping and Traceroute not working in IPv6 environment on Windows XP / Windows Server 20
Similar Threads
Thread Forum
I can ping with IPv6. I can not ping with IPv4. Vista General
Switch the Pinging from IPv6 to Ping IPv4 Network & Sharing
CAL for Windows Server 2008 in a Terminal Server environment .NET General
Cannot ping with IPv6 Vista networking & sharing
Re: IE7 on Vista stops working in network environment with ISA server Vista performance & maintenance