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