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

vigneshp

New Member
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:

My Computer

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 Computer

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 DisableTaskOffloadto 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 Computer

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 Computer

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 Computer

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

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 Computer

Back
Top