Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Recuperer le sequence number en cours

10 réponses
Avatar
B.Cerede
Bonjour,

Je développe un petit programme en C pour pinger des machine.

Et je voudrais savoir comment faire la fonction ping de windows pour
récuperer son sequence number.

Est ce faisable via une api? Y a t'il une fonction en C?

Merci.

10 réponses

Avatar
mika
"B.Cerede" wrote in message
news:gqr0kh$luf$
Bonjour,

Je développe un petit programme en C pour pinger des machine.

Et je voudrais savoir comment faire la fonction ping de windows pour
récuperer son sequence number.

Est ce faisable via une api? Y a t'il une fonction en C?



Tu peux regarder l'exemple ping.cpp du SDK Windows qui fait un ping ICMP
Avatar
B.Cerede
mika a écrit :
"B.Cerede" wrote in message
news:gqr0kh$luf$
Bonjour,

Je développe un petit programme en C pour pinger des machine.

Et je voudrais savoir comment faire la fonction ping de windows pour
récuperer son sequence number.

Est ce faisable via une api? Y a t'il une fonction en C?



Tu peux regarder l'exemple ping.cpp du SDK Windows qui fait un ping ICMP




Aurais tu un lien pour cet exemple s'il te plait?

Merci
Avatar
Jean-Claude BELLAMY
"B.Cerede" a écrit dans le message de
news:gqr0kh$luf$
Bonjour,

Je développe un petit programme en C pour pinger des machine.
Et je voudrais savoir comment faire la fonction ping de windows pour
récuperer son sequence number.
Est ce faisable via une api? Y a t'il une fonction en C?




A partir de W2k, c'est possible avec l'API "IPHLPAPI.DLL" (située dans
%systemroot%system32)
Fichier lib : iphlpapi.lib.
Headers : icmpapi.h

Dans ton cas, la fonction à utiliser est "IcmpSendEcho"

The IcmpSendEcho function sends an IPv4 ICMP echo request and returns any
echo response replies. The call returns when the time-out has expired or the
reply buffer is filled.

http://msdn.microsoft.com/en-us/library/aa366050(VS.85).aspx


--
May the Force be with You!
La Connaissance s'accroît quand on la partage
----------------------------------------------------------
Jean-Claude BELLAMY [MVP] - http://www.bellamyjc.org
Avatar
mika
"B.Cerede" wrote in message
news:gqr96j$vn4$

Aurais tu un lien pour cet exemple s'il te plait?

Merci



Il faut télécharger le Windows SDK (ou Platform SDK) chez Microsoft et il
est dans :
..Microsoft Platform SDKSamplesNetDSWinSockPing

Sinon, quelqu'un a posté les sources concaténés :
http://www.experts-exchange.com/Programming/Languages/CPP/Q_20678838.html
(commence à " From Network Programming for Microsoft Windows, ")
Avatar
B.Cerede
mika a écrit :
"B.Cerede" wrote in message
news:gqr96j$vn4$

Aurais tu un lien pour cet exemple s'il te plait?

Merci



Il faut télécharger le Windows SDK (ou Platform SDK) chez Microsoft et il
est dans :
..Microsoft Platform SDKSamplesNetDSWinSockPing

Sinon, quelqu'un a posté les sources concaténés :
http://www.experts-exchange.com/Programming/Languages/CPP/Q_20678838.html
(commence à " From Network Programming for Microsoft Windows, ")




Je n'ai pas de compte pour experts exchange :(
Avatar
Jean-Claude BELLAMY
"B.Cerede" a écrit dans le message de
news:gqtjbi$vn6$
mika a écrit :
"B.Cerede" wrote in message
Aurais tu un lien pour cet exemple s'il te plait?

Merci



Il faut télécharger le Windows SDK (ou Platform SDK) chez Microsoft et il
est dans :
..Microsoft Platform SDKSamplesNetDSWinSockPing

Sinon, quelqu'un a posté les sources concaténés :
http://www.experts-exchange.com/Programming/Languages/CPP/Q_20678838.html
(commence à " From Network Programming for Microsoft Windows, ")


Je n'ai pas de compte pour experts exchange :(





Mais pourquoi n'es-tu pas allé sur le site MSDN, dont je t'ai donné un lien
à propos de IcmpSendEcho ????
Il y a tout ce qu'il faut, y compris un exemple !
http://msdn.microsoft.com/en-us/library/aa366050(VS.85).aspx

Pas besoin de perdre son temps sur "experts-exchange" !!!
(son côté MERCANTILE m'a toujours rebuté!)


--
May the Force be with You!
La Connaissance s'accroît quand on la partage
----------------------------------------------------------
Jean-Claude BELLAMY [MVP] - http://www.bellamyjc.org
Avatar
B.Cerede
Le problème c'est que je veut gérer moi même la gestion et l'envoi du
paquet ICMP, pour la portabilité de mon code :(
Avatar
Stephane
B.Cerede wrote:
Le problème c'est que je veut gérer moi même la gestion et l'envoi du
paquet ICMP, pour la portabilité de mon code :(



et dans le cache de google ? http://minilien.com/?up3SqjPWLI
et tu peux télécharger sinon le SDK de Windows.
Avatar
B.Cerede
Le cache ne change rien ;) Il faut quand même un compte pour voir :(

Ou puis je télécharger le SDK de Windows?
Avatar
Stephane
B.Cerede wrote:
Le cache ne change rien ;) Il faut quand même un compte pour voir :(

Ou puis je télécharger le SDK de Windows?




Chez Microsoft !

Un copier-coller des fichiers :

/ From Network Programming for Microsoft Windows, Second Edition by
// Anthony Jones and James Ohlund.
// Copyright 2002. Reproduced by permission of Microsoft Press.
// All rights reserved.
//
//
// Sample: IPv4 and IPv6 Ping Sample
//
// Files:
// iphdr.h - IPv4 and IPv6 packet header definitions
// ping.cpp - this file
// resolve.cpp - Common name resolution routine
// resolve.h - Header file for common name resolution routines
//
// Description:
// This sample illustrates how to use raw sockets to send ICMP
// echo requests and receive their response. This sample performs
// both IPv4 and IPv6 ICMP echo requests. When using raw sockets,
// the protocol value supplied to the socket API is used as the
// protocol field (or next header field) of the IP packet. Then
// as a part of the data submitted to sendto, we include both
// the ICMP request and data.
//
// For IPv4 the IP record route option is supported via the
// IP_OPTIONS socket option.
//
// Compile:
// cl -o ping.exe ping.cpp resolve.cpp ws2_32.lib
//
// Command Line Options/Parameters:
// ping.exe [-a 4|6] [-i ttl] [-l datasize] [-r] [host]
//
// -a Address family (IPv4 or IPv6)
// -i ttl TTL value to set on socket
// -l size Amount of data to send as part of the ICMP request
// -r Use IPv4 record route
// host Hostname or literal address
//
#ifdef _IA64_
#pragma warning (disable: 4267)
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>

#include "resolve.h"

#include "iphdr.h"

#define DEFAULT_DATA_SIZE 32 // default data size

#define DEFAULT_SEND_COUNT 4 // number of ICMP requests to send

#define DEFAULT_RECV_TIMEOUT 6000 // six second

#define DEFAULT_TTL 128

#define MAX_RECV_BUF_LEN 0xFFFF // Max incoming packet size.

int gAddressFamily¯_UNSPEC, // Address family to use
gProtocol=IPPROTO_ICMP, // Protocol value
gTtlÞFAULT_TTL; // Default TTL value
int gDataSizeÞFAULT_DATA_SIZE; // Amount of data to send
BOOL bRecordRouteúLSE; // Use IPv4 record route?
char *gDestination=NULL, // Destination
recvbuf[MAX_RECV_BUF_LEN]; // For received packets
int recvbuflen = MAX_RECV_BUF_LEN; // Length of received packets.


//
// Function: usage
//
// Description:
// Print usage information.
//
void usage(char *progname)
{
printf("usage: %s [options] <host> n", progname);
printf(" host Remote machine to pingn");
printf(" options: n");
printf(" -a 4|6 Address family (default:
AF_UNSPEC)n");
printf(" -i ttl Time to live (default: 128) n");
printf(" -l bytes Amount of data to send (default:
32) n");
printf(" -r Record route (IPv4 only)n");

return;
}

//
// Function: InitIcmpHeader
//
// Description:
// Helper function to fill in various stuff in our ICMP request.
//
void InitIcmpHeader(char *buf, int datasize)
{
ICMP_HDR *icmp_hdr=NULL;
char *datapart=NULL;

icmp_hdr = (ICMP_HDR *)buf;
icmp_hdr->icmp_type = ICMPV4_ECHO_REQUEST_TYPE; //
request an ICMP echo
icmp_hdr->icmp_code = ICMPV4_ECHO_REQUEST_CODE;
icmp_hdr->icmp_id = (USHORT)GetCurrentProcessId();
icmp_hdr->icmp_checksum = 0;
icmp_hdr->icmp_sequence = 0;

datapart = buf + sizeof(ICMP_HDR);
//
// Place some data in the buffer.
//
memset(datapart, 'E', datasize);
}

//
// Function: InitIcmp6Header
//
// Description:
// Initialize the ICMP6 header as well as the echo request header.
//
int InitIcmp6Header(char *buf, int datasize)
{
ICMPV6_HDR *icmp6_hdr=NULL;
ICMPV6_ECHO_REQUEST *icmp6_req=NULL;
char *datapart=NULL;

// Initialize the ICMP6 headerf ields
icmp6_hdr = (ICMPV6_HDR *)buf;
icmp6_hdr->icmp6_type = ICMPV6_ECHO_REQUEST_TYPE;
icmp6_hdr->icmp6_code = ICMPV6_ECHO_REQUEST_CODE;
icmp6_hdr->icmp6_checksum = 0;

// Initialize the echo request fields
icmp6_req = (ICMPV6_ECHO_REQUEST *)(buf + sizeof(ICMPV6_HDR));
icmp6_req->icmp6_echo_id = (USHORT)GetCurrentProcessId();
icmp6_req->icmp6_echo_sequence = 0;

datapart = (char *)buf + sizeof(ICMPV6_HDR) +
sizeof(ICMPV6_ECHO_REQUEST);

memset(datapart, '#', datasize);

return (sizeof(ICMPV6_HDR) + sizeof(ICMPV6_ECHO_REQUEST));
}

//
// Function: checksum
//
// Description:
// This function calculates the 16-bit one's complement sum
// of the supplied buffer (ICMP) header.
//
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;

while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum);
}

//
// Function: ValidateArgs
//
// Description:
// Parse the command line arguments.
//
BOOL ValidateArgs(int argc, char **argv)
{
int i;
BOOL isValid = FALSE;

for(i=1; i < argc ;i++)
{
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 'a': // address family
if (i+1 >= argc)
{
usage(argv[0]);
goto CLEANUP;
}
if (argv[i+1][0] == '4')
gAddressFamily = AF_INET;
else if (argv[i+1][0] == '6')
gAddressFamily = AF_INET6;
else
{
usage(argv[0]);
goto CLEANUP;
}

i++;
break;
case 'i': // Set TTL value
if (i+1 >= argc)
{
usage(argv[0]);
goto CLEANUP;
}

gTtl = atoi(argv[++i]);
break;
case 'l': // buffer size tos end
if (i+1 >= argc)
{
usage(argv[0]);
goto CLEANUP;
}

gDataSize = atoi(argv[++i]);
break;
case 'r': // record route option
bRecordRoute = TRUE;
break;
default:
usage(argv[0]);
goto CLEANUP;
}
}
else
{
gDestination = argv[i];
}
}

isValid = TRUE;

CLEANUP:
return isValid;
}

//
// Function: SetIcmpSequence
//
// Description:
// This routine sets the sequence number of the ICMP request packet.
//
void SetIcmpSequence(char *buf)
{
ULONG sequence=0;

sequence = GetTickCount();
if (gAddressFamily == AF_INET)
{
ICMP_HDR *icmpv4=NULL;

icmpv4 = (ICMP_HDR *)buf;

icmpv4->icmp_sequence = (USHORT)sequence;
}
else if (gAddressFamily == AF_INET6)
{
ICMPV6_HDR *icmpv6=NULL;
ICMPV6_ECHO_REQUEST *req6=NULL;

icmpv6 = (ICMPV6_HDR *)buf;
req6 = (ICMPV6_ECHO_REQUEST *)(buf + sizeof(ICMPV6_HDR));

req6->icmp6_echo_sequence = (USHORT)sequence;
}
}

//
// Function: ComputeIcmp6PseudoHeaderChecksum
//
// Description:
// This routine computes the ICMP6 checksum which includes the pseudo
// header of the IPv6 header (see RFC2460 and RFC2463). The one
difficulty
// here is we have to know the source and destination IPv6 addresses
which
// will be contained in the IPv6 header in order to compute the checksum.
// To do this we call the SIO_ROUTING_INTERFACE_QUERY ioctl to find which
// local interface for the outgoing packet.
//
USHORT ComputeIcmp6PseudoHeaderChecksum(SOCKET s, char *icmppacket, int
icmplen, struct addrinfo *dest)
{
SOCKADDR_STORAGE localif;
DWORD bytes;
char tmp[MAX_RECV_BUF_LEN] = {''},
*ptr=NULL,
proto=0;
int rc, total, length, i;

// Find out which local interface for the destination
rc = WSAIoctl(
s,
SIO_ROUTING_INTERFACE_QUERY,
dest->ai_addr,
(DWORD) dest->ai_addrlen,
(SOCKADDR *) &localif,
(DWORD) sizeof(localif),
&bytes,
NULL,
NULL
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAIoctl failed: %dn", WSAGetLastError());
return 0xFFFF;
}

// We use a temporary buffer to calculate the pseudo header.
ptr = tmp;
total = 0;

// Copy source address
memcpy(ptr, &((SOCKADDR_IN6 *)&localif)->sin6_addr, sizeof(struct
in6_addr));
ptr += sizeof(struct in6_addr);
total += sizeof(struct in6_addr);

// Copy destination address
memcpy(ptr, &((SOCKADDR_IN6 *)dest->ai_addr)->sin6_addr,
sizeof(struct in6_addr));
ptr += sizeof(struct in6_addr);
total += sizeof(struct in6_addr);

// Copy ICMP packet length
length = htonl(icmplen);

memcpy(ptr, &length, sizeof(length));
ptr += sizeof(length);
total += sizeof(length);

// Zero the 3 bytes
memset(ptr, 0, 3);
ptr += 3;
total += 3;

// Copy next hop header
proto = IPPROTO_ICMP6;

memcpy(ptr, &proto, sizeof(proto));
ptr += sizeof(proto);
total += sizeof(proto);

// Copy the ICMP header and payload
memcpy(ptr, icmppacket, icmplen);
ptr += icmplen;
total += icmplen;

for(i=0; i < icmplen%2 ;i++)
{
*ptr = 0;
ptr++;
total++;
}


return checksum((USHORT *)tmp, total);
}

//
// Function: ComputeIcmpChecksum
//
// Description:
// This routine computes the checksum for the ICMP request. For IPv4 its
// easy, just compute the checksum for the ICMP packet and data. For
IPv6,
// its more complicated. The pseudo checksum has to be computed for IPv6
// which includes the ICMP6 packet and data plus portions of the IPv6
// header which is difficult since we aren't building our own IPv6
// header.
//
void ComputeIcmpChecksum(SOCKET s, char *buf, int packetlen, struct
addrinfo *dest)
{
if (gAddressFamily == AF_INET)
{
ICMP_HDR *icmpv4=NULL;

icmpv4 = (ICMP_HDR *)buf;
icmpv4->icmp_checksum = 0;
icmpv4->icmp_checksum = checksum((USHORT *)buf, packetlen);
}
else if (gAddressFamily == AF_INET6)
{
ICMPV6_HDR *icmpv6=NULL;

icmpv6 = (ICMPV6_HDR *)buf;
icmpv6->icmp6_checksum = 0;
icmpv6->icmp6_checksum = ComputeIcmp6PseudoHeaderChecksum(
s,
buf,
packetlen,
dest
);
}
}

//
// Function: PostRecvfrom
//
// Description:
// This routine posts an overlapped WSARecvFrom on the raw socket.
//
int PostRecvfrom(SOCKET s, char *buf, int buflen, SOCKADDR *from, int
*fromlen, WSAOVERLAPPED *ol)
{
WSABUF wbuf;
DWORD flags,
bytes;
int rc;

wbuf.buf = buf;
wbuf.len = buflen;

flags = 0;

rc = WSARecvFrom(
s,
&wbuf,
1,
&bytes,
&flags,
from,
fromlen,
ol,
NULL
);
if (rc == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
fprintf(stderr, "WSARecvFrom failed: %dn", WSAGetLastError());
return SOCKET_ERROR;
}
}
return NO_ERROR;
}

//
// Function: PrintPayload
//
// Description:
// This routine is for IPv4 only. It determines if there are any IP
options
// present (by seeing if the IP header length is greater than 20
bytes) and
// if so it prints the IP record route options.
//
void PrintPayload(char *buf, int bytes)
{
int hdrlen=0,
routes=0,
i;

UNREFERENCED_PARAMETER(bytes);

if (gAddressFamily == AF_INET)
{
SOCKADDR_IN hop;
IPV4_OPTION_HDR *v4opt=NULL;
IPV4_HDR *v4hdr=NULL;

hop.sin_family = (USHORT)gAddressFamily;
hop.sin_port = 0;

v4hdr = (IPV4_HDR *)buf;
hdrlen = (v4hdr->ip_verlen & 0x0F) * 4;

// If the header length is greater than the size of the basic IPv4
// header then there are options present. Find them and
print them.
if (hdrlen > sizeof(IPV4_HDR))
{
v4opt = (IPV4_OPTION_HDR *)(buf + sizeof(IPV4_HDR));
routes = (v4opt->opt_ptr / sizeof(ULONG)) - 1;
for(i=0; i < routes ;i++)
{
hop.sin_addr.s_addr = v4opt->opt_addr[i];

// Print the route
if (i == 0)
printf(" Route: ");
else
printf(" ");
PrintAddress((SOCKADDR *)&hop, sizeof(hop));

if (i < routes-1)
printf(" ->n");
else
printf("n");
}
}
}
return;
}

//
// Function: SetTtl
//
// Description:
// Sets the TTL on the socket.
//
int SetTtl(SOCKET s, int ttl)
{
int optlevel = 0,
option = 0,
rc;

rc = NO_ERROR;
if (gAddressFamily == AF_INET)
{
optlevel = IPPROTO_IP;
option = IP_TTL;
}
else if (gAddressFamily == AF_INET6)
{
optlevel = IPPROTO_IPV6;
option = IPV6_UNICAST_HOPS;
}
else
{
rc = SOCKET_ERROR;
}
if (rc == NO_ERROR)
{
rc = setsockopt(
s,
optlevel,
option,
(char *)&ttl,
sizeof(ttl)
);
}
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "SetTtl: setsockopt failed: %dn",
WSAGetLastError());
}
return rc;
}

//
// Function: main
//
// Description:
// Setup the ICMP raw socket and create the ICMP header. Add
// the appropriate IP option header and start sending ICMP
// echo requests to the endpoint. For each send and receive we
// set a timeout value so that we don't wait forever for a
// response in case the endpoint is not responding. When we
// receive a packet decode it.
//

int __cdecl main(int argc, char **argv)
{

WSADATA wsd;
WSAOVERLAPPED recvol;
SOCKET s=INVALID_SOCKET;
char *icmpbuf=NULL;
struct addrinfo *dest=NULL,
*local=NULL;
IPV4_OPTION_HDR ipopt;
SOCKADDR_STORAGE from;
DWORD bytes,
flags;
int packetlen=0,
fromlen,
time=0,
rc,
i,
status = 0;

recvol.hEvent = WSA_INVALID_EVENT;

// Parse the command line
if (ValidateArgs(argc, argv) == FALSE)
{
// invalid arguments supplied.
status = -1;
goto EXIT;
}

// Load Winsock
if ((rc = WSAStartup(MAKEWORD(2,2), &wsd)) != 0)
{
printf("WSAStartup() failed: %dn", rc);
status = -1;
goto EXIT;
}

// Resolve the destination address
dest = ResolveAddress(
gDestination,
"0",
gAddressFamily,
0,
0
);
if (dest == NULL)
{
printf("bad name %sn", gDestination);
status = -1;
goto CLEANUP;
}
gAddressFamily = dest->ai_family;

if (gAddressFamily == AF_INET)
gProtocol = IPPROTO_ICMP;
else if (gAddressFamily == AF_INET6)
gProtocol = IPPROTO_ICMP6;

// Get the bind address
local = ResolveAddress(
NULL,
"0",
gAddressFamily,
0,
0
);
if (local == NULL)
{
printf("Unable to obtain the bind address!n");
status = -1;
goto CLEANUP;
}

// Create the raw socket
s = socket(gAddressFamily, SOCK_RAW, gProtocol);
if (s == INVALID_SOCKET)
{
printf("socket failed: %dn", WSAGetLastError());
status = -1;
goto CLEANUP;
}

SetTtl(s, gTtl);

// Figure out the size of the ICMP header and payload
if (gAddressFamily == AF_INET)
packetlen += sizeof(ICMP_HDR);
else if (gAddressFamily == AF_INET6)
packetlen += sizeof(ICMPV6_HDR) + sizeof(ICMPV6_ECHO_REQUEST);

// Add in the data size
packetlen += gDataSize;

// Allocate the buffer that will contain the ICMP request
icmpbuf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
packetlen);
if (icmpbuf == NULL)
{
fprintf(stderr, "HeapAlloc failed: %dn", GetLastError());
status = -1;
goto CLEANUP;
}

// Initialize the ICMP headers
if (gAddressFamily == AF_INET)
{
if (bRecordRoute)
{
// Setup the IP option header to go out on every ICMP packet
ZeroMemory(&ipopt, sizeof(ipopt));
ipopt.opt_code = IP_RECORD_ROUTE; // record route option
ipopt.opt_ptr = 4; // point to the first
addr offset
ipopt.opt_len = 39; // length of option header

rc = setsockopt(s, IPPROTO_IP, IP_OPTIONS,
(char *)&ipopt, sizeof(ipopt));
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "setsockopt(IP_OPTIONS) failed: %dn",
WSAGetLastError());
status = -1;
goto CLEANUP;
}
}

InitIcmpHeader(icmpbuf, gDataSize);
}
else if (gAddressFamily == AF_INET6)
{
InitIcmp6Header(icmpbuf, gDataSize);
}

// Bind the socket -- need to do this since we post a receive first
rc = bind(s, local->ai_addr, (int)local->ai_addrlen);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "bind failed: %dn", WSAGetLastError());
status = -1;
goto CLEANUP;
}

// Setup the receive operation
memset(&recvol, 0, sizeof(recvol));
recvol.hEvent = WSACreateEvent();
if (recvol.hEvent == WSA_INVALID_EVENT)
{
fprintf(stderr, "WSACreateEvent failed: %dn", WSAGetLastError());
status = -1;
goto CLEANUP;
}

// Post the first overlapped receive
fromlen = sizeof(from);
PostRecvfrom(s, recvbuf, recvbuflen, (SOCKADDR *)&from, &fromlen,
&recvol);

printf("nPinging ");
PrintAddress(dest->ai_addr, (int)dest->ai_addrlen);
printf(" with %d bytes of datann", gDataSize);

// Start sending the ICMP requests
for(i=0; i < DEFAULT_SEND_COUNT ;i++)
{
// Set the sequence number and compute the checksum
SetIcmpSequence(icmpbuf);
ComputeIcmpChecksum(s, icmpbuf, packetlen, dest);

time = GetTickCount();
rc = sendto(
s,
icmpbuf,
packetlen,
0,
dest->ai_addr,
(int)dest->ai_addrlen
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "sendto failed: %dn", WSAGetLastError());
status = -1;
goto CLEANUP;
}

// Waite for a response
rc = WaitForSingleObject((HANDLE)recvol.hEvent,
DEFAULT_RECV_TIMEOUT);
if (rc == WAIT_FAILED)
{
fprintf(stderr, "WaitForSingleObject failed: %dn",
GetLastError());
status = -1;
goto CLEANUP;
}
else if (rc == WAIT_TIMEOUT)
{
printf("Request timed out.n");
}
else
{
rc = WSAGetOverlappedResult(
s,
&recvol,
&bytes,
FALSE,
&flags
);
if (rc == FALSE)
{
fprintf(stderr, "WSAGetOverlappedResult failed: %dn",
WSAGetLastError());
}
time = GetTickCount() - time;

WSAResetEvent(recvol.hEvent);

printf("Reply from ");
PrintAddress((SOCKADDR *)&from, fromlen);
if (time == 0)
printf(": bytes=%d time<1ms TTL=%dn", gDataSize, gTtl);
else
printf(": bytes=%d time=%dms TTL=%dn", gDataSize,
time, gTtl);

PrintPayload(recvbuf, bytes);

if (i < DEFAULT_SEND_COUNT - 1)
{
fromlen = sizeof(from);
PostRecvfrom(s, recvbuf, recvbuflen, (SOCKADDR *)&from,
&fromlen, &recvol);
}
}
Sleep(1000);
}

CLEANUP:

//
// Cleanup
//
if (dest)
freeaddrinfo(dest);
if (local)
freeaddrinfo(local);
if (s != INVALID_SOCKET)
closesocket(s);
if (recvol.hEvent != WSA_INVALID_EVENT)
WSACloseEvent(recvol.hEvent);
if (icmpbuf)
HeapFree(GetProcessHeap(), 0, icmpbuf);

WSACleanup();

EXIT:
return status;
}



// From Network Programming for Microsoft Windows, Second Edition by
// Anthony Jones and James Ohlund.
// Copyright 2002. Reproduced by permission of Microsoft Press.
// All rights reserved.
//
//
// Sample: Protocol header definitions used by ping (raw sockets)
//
// Files:
// iphdr.h - this file
//
// Description:
// This file contains various protocol header definitions used by
// the raw socket ping sample.
//
// Compile:
// See ping.cpp
//
// Usage:
// See ping.cpp
//

// Align on a 1-byte boundary
#include <pshpack1.h>

// IPv4 header
typedef struct ip_hdr
{
unsigned char ip_verlen; // 4-bit IPv4 version
// 4-bit header length (in 32-bit
words)
unsigned char ip_tos; // IP type of service
unsigned short ip_totallength; // Total length
unsigned short ip_id; // Unique identifier
unsigned short ip_offset; // Fragment offset field
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP,UDP etc)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Source address
} IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;

// IPv4 option header
typedef struct ipv4_option_hdr
{
unsigned char opt_code; // option type
unsigned char opt_len; // length of the option header
unsigned char opt_ptr; // offset into options
unsigned long opt_addr[9]; // list of IPv4 addresses
} IPV4_OPTION_HDR, *PIPV4_OPTION_HDR, FAR *LPIPV4_OPTION_HDR;

// ICMP header
typedef struct icmp_hdr
{
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_sequence;
} ICMP_HDR, *PICMP_HDR, FAR *LPICMP_HDR;

// IPv6 protocol header
typedef struct ipv6_hdr
{
unsigned long ipv6_vertcflow; // 4-bit IPv6 version
// 8-bit traffic class
// 20-bit flow label
unsigned short ipv6_payloadlen; // payload length
unsigned char ipv6_nexthdr; // next header protocol value
unsigned char ipv6_hoplimit; // TTL
struct in6_addr ipv6_srcaddr; // Source address
struct in6_addr ipv6_destaddr; // Destination address
} IPV6_HDR, *PIPV6_HDR, FAR * LPIPV6_HDR;

// IPv6 fragment header
typedef struct ipv6_fragment_hdr
{
unsigned char ipv6_frag_nexthdr;
unsigned char ipv6_frag_reserved;
unsigned short ipv6_frag_offset;
unsigned long ipv6_frag_id;
} IPV6_FRAGMENT_HDR, *PIPV6_FRAGMENT_HDR, FAR * LPIPV6_FRAGMENT_HDR;

// ICMPv6 header
typedef struct icmpv6_hdr {
unsigned char icmp6_type;
unsigned char icmp6_code;
unsigned short icmp6_checksum;
} ICMPV6_HDR;

// ICMPv6 echo request body
typedef struct icmpv6_echo_request
{
unsigned short icmp6_echo_id;
unsigned short icmp6_echo_sequence;
} ICMPV6_ECHO_REQUEST;

// Define the UDP header
typedef struct udp_hdr
{
unsigned short src_portno; // Source port no.
unsigned short dst_portno; // Dest. port no.
unsigned short udp_length; // Udp packet length
unsigned short udp_checksum; // Udp checksum (optional)
} UDP_HDR, *PUDP_HDR;

// IPv4 option for record route
#define IP_RECORD_ROUTE 0x7

// ICMP6 protocol value (used in the socket call and IPv6 header)
#define IPPROTO_ICMP6 58

// ICMP types and codes
#define ICMPV4_ECHO_REQUEST_TYPE 8
#define ICMPV4_ECHO_REQUEST_CODE 0
#define ICMPV4_ECHO_REPLY_TYPE 0
#define ICMPV4_ECHO_REPLY_CODE 0
#define ICMPV4_MINIMUM_HEADER 8

// ICPM6 types and codes
#define ICMPV6_ECHO_REQUEST_TYPE 128
#define ICMPV6_ECHO_REQUEST_CODE 0
#define ICMPV6_ECHO_REPLY_TYPE 129
#define ICMPV6_ECHO_REPLY_CODE 0

// Restore byte alignment back to default
#include <poppack.h>



// From Network Programming for Microsoft Windows, Second Edition by
// Anthony Jones and James Ohlund.
// Copyright 2002. Reproduced by permission of Microsoft Press.
// All rights reserved.
//
//
// Common routines for resolving addresses and hostnames
//
// Files:
// resolve.cpp - Common routines
// resolve.h - Header file for common routines
//
// Description:
// This file contains common name resolution and name printing
// routines and is used by many of the samples on this CD.
//
// Compile:
// See ping.cpp
//
// Usage:
// See ping.cpp
//
#include <winsock2.h>
#include <ws2tcpip.h>
#include <strsafe.h>
#include <stdio.h>
#include <stdlib.h>

#include "resolve.h"

//
// Function: PrintAddress
//
// Description:
// This routine takes a SOCKADDR structure and its length and prints
// converts it to a string representation. This string is printed
// to the console via stdout.
//
int PrintAddress(SOCKADDR *sa, int salen)
{
char host[NI_MAXHOST],
serv[NI_MAXSERV];
int hostlen = NI_MAXHOST,
servlen = NI_MAXSERV,
rc;

rc = getnameinfo(
sa,
salen,
host,
hostlen,
serv,
servlen,
NI_NUMERICHOST | NI_NUMERICSERV
);
if (rc != 0)
{
fprintf(stderr, "%s: getnameinfo failed: %dn", __FILE__, rc);
return rc;
}

// If the port is zero then don't print it
if (strcmp(serv, "0") != 0)
{
if (sa->sa_family == AF_INET)
printf("[%s]:%s", host, serv);
else
printf("%s:%s", host, serv);
}
else
printf("%s", host);

return NO_ERROR;
}

//
// Function: FormatAddress
//
// Description:
// This is similar to the PrintAddress function except that instead of
// printing the string address to the console, it is formatted into
// the supplied string buffer.
//
int FormatAddress(SOCKADDR *sa, int salen, char *addrbuf, int addrbuflen)
{
char host[NI_MAXHOST],
serv[NI_MAXSERV];
int hostlen = NI_MAXHOST,
servlen = NI_MAXSERV,
rc;
HRESULT hRet;

rc = getnameinfo(
sa,
salen,
host,
hostlen,
serv,
servlen,
NI_NUMERICHOST | NI_NUMERICSERV
);
if (rc != 0)
{
fprintf(stderr, "%s: getnameinfo failed: %dn", __FILE__, rc);
return rc;
}

if ( (strlen(host) + strlen(serv) + 1) > (unsigned)addrbuflen)
return WSAEFAULT;

addrbuf[0] = '';

if (sa->sa_family == AF_INET)
{
if(FAILED(hRet = StringCchPrintf(addrbuf, addrbuflen, "%s:%s",
host, serv)))
{
fprintf(stderr,"%s StringCchPrintf failed:
0x%xn",__FILE__,hRet);
return (int)hRet;
}
}
else if (sa->sa_family == AF_INET6)
{
if(FAILED(hRet = StringCchPrintf(addrbuf, addrbuflen,
"[%s]:%s", host, serv)))
{
fprintf(stderr,"%s StringCchPrintf failed:
0x%xn",__FILE__,hRet);
return (int)hRet;
}
}



return NO_ERROR;
}

//
// Function: ResolveAddress
//
// Description:
// This routine resolves the specified address and returns a list of
addrinfo
// structure containing SOCKADDR structures representing the resolved
addresses.
// Note that if 'addr' is non-NULL, then getaddrinfo will resolve it
whether
// it is a string listeral address or a hostname.
//
struct addrinfo *ResolveAddress(char *addr, char *port, int af, int
type, int proto)
{
struct addrinfo hints,
*res = NULL;
int rc;

memset(&hints, 0, sizeof(hints));
hints.ai_flags = ((addr) ? 0 : AI_PASSIVE);
hints.ai_family = af;
hints.ai_socktype = type;
hints.ai_protocol = proto;

rc = getaddrinfo(
addr,
port,
&hints,
&res
);
if (rc != 0)
{
fprintf(stderr, "Invalid address %s, getaddrinfo failed: %dn",
addr, rc);
return NULL;
}
return res;
}

//
// Function: ReverseLookup
//
// Description:
// This routine takes a SOCKADDR and does a reverse lookup for the name
// corresponding to that address.
//
int ReverseLookup(SOCKADDR *sa, int salen, char *buf, int buflen)
{
char host[NI_MAXHOST];
int hostlen=NI_MAXHOST,
rc;
HRESULT hRet;

rc = getnameinfo(
sa,
salen,
host,
hostlen,
NULL,
0,
0
);
if (rc != 0)
{
fprintf(stderr, "getnameinfo failed: %dn", rc);
return rc;
}

buf[0] = '';
if(FAILED(hRet = StringCchCopy(buf, buflen, host)))
{
fprintf(stderr,"StringCchCopy failed: 0x%xn",hRet);
return (int)hRet;
}

return NO_ERROR;
}



// From Network Programming for Microsoft Windows, Second Edition by
// Anthony Jones and James Ohlund.
// Copyright 2002. Reproduced by permission of Microsoft Press.
// All rights reserved.
//
//
// Common routines for resolving addresses and hostnames
//
// Files:
// resolve.h - Header file for common routines
//
// Description:
// This file contains common name resolution and name printing
// routines and is used by many of the samples on this CD.
//
// Compile:
// See ping.cpp
//
// Usage:
// See ping.cpp
//
#ifndef _RESOLVE_H_
#define _RESOLVE_H_

#ifdef _cplusplus
extern "C" {
#endif

int PrintAddress(SOCKADDR *sa, int salen);
int FormatAddress(SOCKADDR *sa, int salen, char *addrbuf,
int addrbuflen);
int ReverseLookup(SOCKADDR *sa, int salen, char *namebuf,
int namebuflen);
struct addrinfo *ResolveAddress(char *addr, char *port, int af, int
type, int proto);

#ifdef _cplusplus
}
#endif

#endif