IPv6 pings with Icmp6SendEcho2

G

Guest

I am attempting to write a functon that can perform IPv6 compliant pings.
But, Icmp6SendEcho2 causes an access violation whenever it is called:

First-chance exception at 0x76d641e8 in mping2.exe: 0xC0000005: Access
violation reading location 0x00000000.
Unhandled exception at 0x76d641e8 in mping2.exe: 0xC0000005: Access
violation reading location 0x00000000.

I have been unable to pinpoint the cause of the access violation so far, so
I was hoping somebody here would notice the error of my ways and point it out
to me.
Below is the function in question.

Thank you!


int CIcmpEcho::pingNew(CString strHost, CString &retData)
//uses newer IP-Helper to do pings
//IPv6 compliant
{
HANDLE hIcmpFile;
char EchoRequest[MAX_BUF_SIZE] = {0}, EchoReply[MAX_BUF_SIZE +
sizeof(ICMPECHO)];
DWORD dwPingReplies;
IN_ADDR iaDest;
struct addrinfo *saDest = NULL;
struct addrinfo *saSource = NULL;

if ( getaddrinfo("", 0, NULL, &saSource) != 0 )
//get address information for the ping source
{
TRACE("Invalid Socket (Localhost)\n");
return -5;
}

if ( getaddrinfo("::1", 0, NULL, &saDest) != 0 )
//get address information for the ping destination
{
TRACE("Invalid Socket (Destination)\n");
freeaddrinfo(saSource);
return -4;
}

if (m_uPacketSize > MAX_BUF_SIZE)
//check for ping packets that are too large
{
retData.Format("ERROR - Data size too big %d", m_uPacketSize);
freeaddrinfo(saDest);
freeaddrinfo(saSource);
return -3;
}

if ((hIcmpFile = Icmp6CreateFile()) == INVALID_HANDLE_VALUE)
//Create handle to IPv6 ICMP
{
TRACE("\tUnable to open file.\n");
retData = _T("ERROR - IcmpCreateFile() failed");
freeaddrinfo(saDest);
freeaddrinfo(saSource);
return -1;
}

dwPingReplies = Icmp6SendEcho2(hIcmpFile, //IPv6 Ping Handle
NULL, //Event
NULL, //APC Routine
NULL, //APC Context
(struct sockaddr_in6 *)saSource->ai_addr, //Source address
(struct sockaddr_in6 *)saDest->ai_addr, //Dest address
EchoRequest, //Request data
m_uPacketSize, //Request size
NULL, //Request Options
EchoReply, //Reply buffer
8*sizeof(EchoReply) + sizeof(ICMP_ECHO_REPLY),
m_msTimeout ); //Timeout (ms)

if ( !dwPingReplies )
{
if (((ICMPECHO *)EchoReply)->Status == IP_REQ_TIMED_OUT)
{
retData = _T("timed out");
freeaddrinfo(saDest);
freeaddrinfo(saSource);
IcmpCloseHandle(hIcmpFile);
return 0;
}
else
{
retData.Format("ERROR - Status: %ld", GetLastError());
freeaddrinfo(saDest);
freeaddrinfo(saSource);
IcmpCloseHandle(hIcmpFile);
return -5;
}
}

iaDest.s_addr = ((ICMPECHO *)EchoReply)->Source;
retData.Format("Reply from %s: bytes=%d time=%ldms TTL=%d",
inet_ntoa(iaDest),
((ICMPECHO *)EchoReply)->DataSize,
((ICMPECHO *)EchoReply)->RTTime > 0 ? ((ICMPECHO *)EchoReply)->RTTime :
0,
((ICMPECHO *)EchoReply)->ipInfo.Ttl);

freeaddrinfo(saDest);
freeaddrinfo(saSource);
IcmpCloseHandle(hIcmpFile);
return 1;
}
 
G

Guest

I've answered my own question. Since I've seen little literature on the
topic, I'll go ahead and post my answer here. My problem was silly, I'd
forgotton to specify a required parameter (IP option information). Here is
the working code:

int CIcmpEcho::ping6(CString strHost, CString &retData)
{
HANDLE hIcmpFile;
HINSTANCE hndlIcmp6;
IP_OPTION_INFORMATION ipInfo = {255, 0, 0, 0, NULL};
char EchoRequest[MAX_BUF_SIZE] = {0}, EchoReply[MAX_BUF_SIZE +
sizeof(ICMP_ECHO_REPLY) + 8];
DWORD dwPingReplies;
struct addrinfo *saDest = NULL;
struct sockaddr_in6 sa6Source;

if (m_uPacketSize > MAX_BUF_SIZE)
{
retData.Format("ERROR - Data size(%d) too big", m_uPacketSize);
return -2;
}

//Load the IP-Helper API
hndlIcmp6 = LoadLibrary("IPHLPAPI.DLL");
if (!hndlIcmp6)
{
retData = _T("ERROR - Could not load IPHLPAPI.DLL");
return -3;
}

// Retrieve IP-Helper ICMPv6 function pointers
pIcmp6CreateFile = (HANDLE (WINAPI
*)(void))GetProcAddress(hndlIcmp6,"Icmp6CreateFile");
pIcmpCloseHandle = (BOOL (WINAPI
*)(HANDLE))GetProcAddress(hndlIcmp6,"IcmpCloseHandle");
pIcmp6SendEcho2 = (DWORD (WINAPI *)(HANDLE, HANDLE, FARPROC, PVOID, struct
sockaddr_in6*, struct sockaddr_in6*, LPVOID, WORD, PIP_OPTION_INFORMATION,
LPVOID, DWORD, DWORD)) GetProcAddress(hndlIcmp6,"Icmp6SendEcho2");
pIcmp6ParseReplies = (DWORD (WINAPI *)(LPVOID, DWORD
))GetProcAddress(hndlIcmp6,"Icmp6ParseReplies");

//define local source information
sa6Source.sin6_addr = in6addr_any;
sa6Source.sin6_family = AF_INET6;
sa6Source.sin6_flowinfo = 0;
sa6Source.sin6_port = 0;

// Get address information for the ping destination
if (getaddrinfo(strHost, 0, NULL, &saDest))
{
retData.Format("Destination socket invalid");
FreeLibrary(hndlIcmp6);
return -4;
}

// Create handle to IPv6 ICMP
if ((hIcmpFile = pIcmp6CreateFile()) == INVALID_HANDLE_VALUE)
{
retData = _T("ERROR - IcmpCreateFile() failed");
freeaddrinfo(saDest);
FreeLibrary(hndlIcmp6);
return -5;
}

dwPingReplies = pIcmp6SendEcho2(hIcmpFile, //IPv6 Ping Handle
NULL, //Event
NULL, //APC Routine
NULL, //APC Context
&sa6Source, //local source address
(struct sockaddr_in6 *)saDest->ai_addr, //Dest address
EchoRequest, //Request data
m_uPacketSize, //Request size
&ipInfo, //Request Options
EchoReply, //Reply buffer
sizeof(EchoReply), //Reply size
m_msTimeout); //Timeout (ms)
// Cleanup
pIcmpCloseHandle(hIcmpFile);
freeaddrinfo(saDest);
FreeLibrary(hndlIcmp6);

// Translate the replies
pIcmp6ParseReplies(EchoReply, sizeof(EchoReply));
if (!dwPingReplies)
{
if (((ICMP_ECHO_REPLY *)EchoReply)->Status == IP_REQ_TIMED_OUT)
{
retData = _T("timed out");
return 0;
}
else
{
retData.Format("ERROR - Status: %ld", GetLastError());
return -6;
}
}

retData.Format("Reply from %s: bytes=%d time=%ldms TTL=%d",
"unknown",
((ICMP_ECHO_REPLY *)EchoReply)->DataSize,
((ICMP_ECHO_REPLY *)EchoReply)->RoundTripTime > 0 ? ((ICMP_ECHO_REPLY
*)EchoReply)->RoundTripTime : 0,
((ICMP_ECHO_REPLY *)EchoReply)->Options.Ttl);
return dwPingReplies;
}


PaulH said:
I am attempting to write a functon that can perform IPv6 compliant pings.
But, Icmp6SendEcho2 causes an access violation whenever it is called:

First-chance exception at 0x76d641e8 in mping2.exe: 0xC0000005: Access
violation reading location 0x00000000.
Unhandled exception at 0x76d641e8 in mping2.exe: 0xC0000005: Access
violation reading location 0x00000000.

I have been unable to pinpoint the cause of the access violation so far, so
I was hoping somebody here would notice the error of my ways and point it out
to me.
Below is the function in question.

Thank you!


int CIcmpEcho::pingNew(CString strHost, CString &retData)
//uses newer IP-Helper to do pings
//IPv6 compliant
{
HANDLE hIcmpFile;
char EchoRequest[MAX_BUF_SIZE] = {0}, EchoReply[MAX_BUF_SIZE +
sizeof(ICMPECHO)];
DWORD dwPingReplies;
IN_ADDR iaDest;
struct addrinfo *saDest = NULL;
struct addrinfo *saSource = NULL;

if ( getaddrinfo("", 0, NULL, &saSource) != 0 )
//get address information for the ping source
{
TRACE("Invalid Socket (Localhost)\n");
return -5;
}

if ( getaddrinfo("::1", 0, NULL, &saDest) != 0 )
//get address information for the ping destination
{
TRACE("Invalid Socket (Destination)\n");
freeaddrinfo(saSource);
return -4;
}

if (m_uPacketSize > MAX_BUF_SIZE)
//check for ping packets that are too large
{
retData.Format("ERROR - Data size too big %d", m_uPacketSize);
freeaddrinfo(saDest);
freeaddrinfo(saSource);
return -3;
}

if ((hIcmpFile = Icmp6CreateFile()) == INVALID_HANDLE_VALUE)
//Create handle to IPv6 ICMP
{
TRACE("\tUnable to open file.\n");
retData = _T("ERROR - IcmpCreateFile() failed");
freeaddrinfo(saDest);
freeaddrinfo(saSource);
return -1;
}

dwPingReplies = Icmp6SendEcho2(hIcmpFile, //IPv6 Ping Handle
NULL, //Event
NULL, //APC Routine
NULL, //APC Context
(struct sockaddr_in6 *)saSource->ai_addr, //Source address
(struct sockaddr_in6 *)saDest->ai_addr, //Dest address
EchoRequest, //Request data
m_uPacketSize, //Request size
NULL, //Request Options
EchoReply, //Reply buffer
8*sizeof(EchoReply) + sizeof(ICMP_ECHO_REPLY),
m_msTimeout ); //Timeout (ms)

if ( !dwPingReplies )
{
if (((ICMPECHO *)EchoReply)->Status == IP_REQ_TIMED_OUT)
{
retData = _T("timed out");
freeaddrinfo(saDest);
freeaddrinfo(saSource);
IcmpCloseHandle(hIcmpFile);
return 0;
}
else
{
retData.Format("ERROR - Status: %ld", GetLastError());
freeaddrinfo(saDest);
freeaddrinfo(saSource);
IcmpCloseHandle(hIcmpFile);
return -5;
}
}

iaDest.s_addr = ((ICMPECHO *)EchoReply)->Source;
retData.Format("Reply from %s: bytes=%d time=%ldms TTL=%d",
inet_ntoa(iaDest),
((ICMPECHO *)EchoReply)->DataSize,
((ICMPECHO *)EchoReply)->RTTime > 0 ? ((ICMPECHO *)EchoReply)->RTTime :
0,
((ICMPECHO *)EchoReply)->ipInfo.Ttl);

freeaddrinfo(saDest);
freeaddrinfo(saSource);
IcmpCloseHandle(hIcmpFile);
return 1;
}
 
K

krisan

i would be so grateful if someone comes out with a program that supports
both IPv4 and IPv6

ie if we give a host name to ping , how to know whether the given
ipaddress is a IPv4 one or Ipv6 one ... is there any function that
differentiate these both...
 
Top