Tips & Tricks Blog
Notes, ideas and general comments on anything related to high-tech.

April 30, 2009

ICMP Over Raw Sockets Under Windows Vista

Filed under: Windows — Tags: , , ,

Microsoft has changed how the raw sockets behave several times throughout their OS release history. Starting from XP SP2 the transmissions through raw sockets are limited to prevent sending hand crafted frames of particular types (TCP, UDP with foreign source addresses, …) on client family of OSes. Fortunately the ICMP frames can still be sent and the applications that were using ICMP and  raw sockets are still compatible or easily portable to various Windows OSes.

The only reasonable alternative to the raw sockets when it comes to working with ICMP under Windows is to use the ICMP API DLL. That method is acceptable for simple use cases, but does not allow customizations or fine control over what is transmitted and received. If an application has to manage TTL, payload and types of the ICMP messages, examine the responses, needs to be portable or is built around winsock  for all other operations the ICMP API is not an acceptable or desired choice. 

The problem is that starting from Windows Vista the applications that under XP would successfully receive ICMP responses like “Destination Unreachable” or “TTL Expired” no longer see them. In order for such applications to work correctly under Windows Vista small adjustments have to be made. The following code snippet shows how to set up a raw socket under Vista to assure that it receives frames as it used to do under Windows XP or 2K.

/* Get the address of the interface to work with (using the first one found here) */
hostent *host_addr_list = gethostbyname(NULL);
if(host_addr_list == NULL)
{
  /* Handle error here */
}
else
{
  src.sin_addr.S_un.S_addr = *((u_long *)(host_addr_list->h_addr_list[0]));
}

/* Bind the socket */
if(bind(s, (sockaddr *)&src, sizeof(src)) != NO_ERROR)
{
  /* Handle error here */
}

/* Run the IOCTL that disables packet filtering on the socket. */
DWORD tmp, prm = 3; /* "RCVALL_IPLEVEL" (Vista SDK) */
if(WSAIoctl(s, SIO_RCVALL, &prm, sizeof(prm), NULL, 0,
            &tmp, NULL, NULL) == SOCKET_ERROR)
{
  /* Handle error here */
}

Note that you have to bind the socket to a specific interface address. This is required for the RCVALL_IPLEVEL IOCTL to work.



Home

OkOb.net Tips & Tricks Blog
Powered by WordPress