RE: Retrieving subnet mask

From: Christoffer Bergman (christoffer.bergman_at_audiodev.com)
Date: 02/27/04


Date: Fri, 27 Feb 2004 08:01:08 -0800

I managed to find the solution to the problem myself :)
There is an undocumented flag to WSAIoctl called SIO_GET_INTERFACE_LIST that retrieves IP, subnet and broadcast for all your ethernet cards (however, broadcast seems to always be 255.255.255.255). So I wrote this method to retrieve a correct (?!) broadcast address for a local IP number:

#define MAX_NBR_OF_ETHERNET_CARDS 32

/**
 * This function calculates a suitable broadcast address to use with
 * the supplied IP number.
 * It will do it by locating the subnet mask for that IP number. Then
 * it will calculate the broadcast address as:
 * broadcast = ip | ~(subnet)
 * The purpose of this function is that the request for broadcast address
 * in WSAIoctl() often returns 255.255.255.255 even if a more narrow broadcast
 * address should be used.
 *
 * @param dwIp The IP number in net byte order
 * @return A broadcast address for that IP (255.255.255.255 if that IP wasn't found)
 * @author Christoffer Bergman
 */
DWORD GetBroadcastAddress(DWORD dwIp)
{
        // Create a socket that is just used to get the IP info
        SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(s == INVALID_SOCKET) {
                return INADDR_BROADCAST;
        }

        // Gather the IP Info
        INTERFACE_INFO info[MAX_NBR_OF_ETHERNET_CARDS];
        DWORD dwBytesRead;
        if(WSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, 0,
                (void*)info, sizeof(info), &dwBytesRead, NULL, NULL) != 0) {
                closesocket(s);
                return INADDR_BROADCAST;
        }

        DWORD dwBroadcast = INADDR_BROADCAST;

        // Search all ip infos for the requested ip number
        for(int i = 0; i < (dwBytesRead / sizeof(INTERFACE_INFO)); i++) {
                // Notice: the INTERFACE_INFO contains a broadcast address
                // but that can't be used since it is always 255.255.255.255
                if(info[i].iiAddress.AddressIn.sin_addr.s_addr == dwIp) {
                        DWORD dwSubnet = info[i].iiNetmask.AddressIn.sin_addr.s_addr;
                        dwBroadcast = dwIp | ~(dwSubnet);
                        break;
                }
        }

        closesocket(s);

        return dwBroadcast;
}