Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Vista Forums > Network & Sharing

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

Reply
 
Old 04-27-2009   #1 (permalink)


Vista 32 bit
 
 

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; 04-28-2009 at 12:40 AM..
My System SpecsSystem Spec
Old 05-01-2009   #2 (permalink)


Win7x64
 
 

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
Old 05-04-2009   #3 (permalink)


Vista 32 bit
 
 

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 System SpecsSystem Spec
Old 05-07-2009   #4 (permalink)


Win7x64
 
 

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
Old 05-07-2009   #5 (permalink)


Vista 32 bit
 
 

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
Old 05-07-2009   #6 (permalink)


Win7x64
 
 

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

Quote  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
Reply

Thread Tools


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


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46