IPv6 ping in windows...problem..lots of ode:(
Hi
I am converting a ping program from ipv4 to ipv6.
My problem is, the program doesn't send the echo request.
I have a feeling that it may be to do with the parameters i am passing to the function, or something to do with the structures and pointers.
The program compiles, runs, resolves the addresses, but will not actually send the echo request.
I am sorry for posting all the code, but i am desprate and need pointing in the right direction.
My head is about to explode!!!
My header file ping.h is included below the main code.
Thank you to anyone who can help
Neill
Code:
//
// PING6.C -- Ping program using ICMP and RAW Sockets
//
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <winnt.h>
#include "ping6.h"
#include <tpipv6.h>
#include <Ws2tcpip.h>
#include "inet_ntop.c"
#include "inet_pton.h"
//Internal Functions
void Ping(const char *com_line_host);
int WaitForEchoReply(SOCKET s);
// ICMP Echo Request/Reply functions
int SendEchoRequest(SOCKET, LPSOCKADDR_IN6);
DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN6);
//const char *com_line_host;
// main()
void main(int argc, char **argv)
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2,0);
int nRet;
argv[1] = "ipv6.research.microsoft.com";
// Init WinSock
nRet = WSAStartup(wVersionRequested, &wsaData);
if (nRet)
{
fprintf(stderr,"\nError initializing WinSock\n");
return;
}
// Check version
if (wsaData.wVersion != wVersionRequested)
{
fprintf(stderr,"\nWinSock version not supported\n");
return;
}
// Go do the ping
Ping(argv[1]);
// Free WinSock
WSACleanup();
}
// Ping()
// Calls SendEchoRequest() and
// RecvEchoReply() and prints results
void Ping(const char *com_line_host)
{
SOCKET rawSocket;
//LPHOSTENT lpHost;
struct sockaddr_in6 saDest, saSrc;
struct addrinfo hints, *res, *res0;
DWORD dwTimeSent;
DWORD dwElapsed;
int nLoop;
int nRet;
int error;
char buf[56];
rawSocket = socket(AF_INET6, SOCK_RAW, 58);
if (rawSocket == SOCKET_ERROR)
{
printf("error creating Socket");
return;
}
memset(&hints, 0, sizeof(hints));
memset(&res0, 0, sizeof(res0));
hints.ai_flags = AI_CANONNAME;
error = getaddrinfo(com_line_host, NULL, &hints, &res0);
if (error) {
printf("%s", gai_strerror(error));
}
// Create raw ipv6 Socket
rawSocket = socket(AF_INET6, SOCK_RAW, 58); //58 = icmpv6
if (rawSocket == SOCKET_ERROR)
{
printf("error creating Socket");
return;
}
// Setup destination address
saDest.sin6_addr = (((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr);
saDest.sin6_family = AF_INET6;
saDest.sin6_port = 0;
// Tell the user what we're doing
printf("\nPinging %s [%s] with %d bytes of data:\n",
com_line_host,
inet_ntop(AF_INET6,&saDest.sin6_addr, buf, sizeof(buf)),
REQ_DATASIZE);
// Ping multiple times
for (nLoop = 0; nLoop < 4; nLoop++)
{
// Send ICMP echo request
SendEchoRequest(rawSocket, &saDest);
// Use select() to wait for data to be received
nRet = WaitForEchoReply(rawSocket);
if (nRet == SOCKET_ERROR)
{
printf ("select()");
}
if (!nRet)
{
printf("\nTimeOut");
}
// Receive reply
dwTimeSent = RecvEchoReply(rawSocket, &saSrc);
// Calculate elapsed time
dwElapsed = GetTickCount() - dwTimeSent;
printf("\nReply from: %s: bytes=%d time=%ldms",
inet_ntop(AF_INET6,&saDest.sin6_addr, buf, sizeof(buf)),
REQ_DATASIZE,
dwElapsed);
}
printf("\n");
nRet = closesocket(rawSocket);
if (nRet == SOCKET_ERROR)
printf("closesocket()");
}
// SendEchoRequest()
// Fill in echo request header
// and send to destination
int SendEchoRequest(SOCKET s,LPSOCKADDR_IN6 lpstToAddr)
{
static ECHOREQUEST echoReq;
static nId = 1;
static nSeq = 1;
int nRet, error;
// Fill in echo request
echoReq.icmp6Hdr.icmp6_type = 128;
echoReq.icmp6Hdr.icmp6_code = 0;
echoReq.icmp6Hdr.icmp6_cksum = 0;
echoReq.icmp6Hdr.icmp6_id = nId++;
echoReq.icmp6Hdr.icmp6_seq = nSeq++;
// Fill in some data to send
for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
echoReq.cData[nRet] = ' '+nRet;
// Save tick count when sent
echoReq.dwTime = GetTickCount();
// Send the echo request
nRet = sendto(s, /* socket */
(LPSTR)&echoReq, /* buffer */
sizeof(ECHOREQUEST), // buffer size
0, /* flags */
(LPSOCKADDR)lpstToAddr, /* destination */
sizeof(SOCKADDR_IN6)); /* address length */
error = WSAGetLastError();
if (nRet == SOCKET_ERROR)
printf ("\nData not Sent");
return (nRet);
}
// RecvEchoReply()
// Receive incoming data
// and parse out fields
DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN6 lpsaFrom)
{
ECHOREPLY echoReply;
int nRet;
int nAddrLen = sizeof(struct sockaddr_in6);
int error;
// Receive the echo reply
nRet = recvfrom(s, // socket
(LPSTR)&echoReply, // buffer
sizeof(ECHOREPLY), // size of buffer
0, // flags
(LPSOCKADDR)lpsaFrom, // From address
&nAddrLen); // pointer to address len
// Check return value
if (nRet == SOCKET_ERROR)
printf("\nNo Data Received");
error = WSAGetLastError();
return(echoReply.echoRequest.dwTime);
}
// WaitForEchoReply()
// Use select() to determine when
// data is waiting to be read
int WaitForEchoReply(SOCKET s)
{
struct timeval Timeout;
fd_set readfds;
readfds.fd_count = 1;
readfds.fd_array[0] = s;
Timeout.tv_sec = 5;
Timeout.tv_usec = 0;
return(select(1, &readfds, NULL, NULL, &Timeout));
}
Ping.h Header File
Code:
//
// Ping.h
//
#pragma pack(1)
#define ICMP_ECHOREPLY 129
#define ICMP_ECHOREQ 128
#include <Ws2tcpip.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <tpipv6.h>
#include <winnt.h>
typedef struct icmp6_hdr {
unsigned char icmp6_type; /* type field */
unsigned char icmp6_code; /* code field */
unsigned short icmp6_cksum; /* checksum field */
unsigned short icmp6_id ; /* echo request/reply */
unsigned short icmp6_seq ; /* echo request/reply */
}ICMP6HDR;
/
#define REQ_DATASIZE 32 // Echo Request Data size
// ICMP Echo Request
typedef struct tagECHOREQUEST
{
ICMP6HDR icmp6Hdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
// ICMP Echo Reply
typedef struct tagECHOREPLY
{
ECHOREQUEST echoRequest;
char cFiller[256];
}ECHOREPLY, *PECHOREPLY;
#pragma pack()