dlls/ws2_32/socket.c
/***********************************************************************
 *		WS_get_local_ips		(INTERNAL)
 *
 * Returns the list of local IP addresses by going through the network
 * adapters and using the local routing table to sort the addresses
 * from highest routing priority to lowest routing priority. This
 * functionality is inferred from the description for obtaining local
 * IP addresses given in the Knowledge Base Article Q160215.
 *
 * Please note that the returned hostent is only freed when the thread
 * closes and is replaced if another hostent is requested.
 */
WS_get_local_ips                (INTERNAL)
Returns the list of local IP addresses by going through the network
adapters and using the local routing table to sort the addresses
from highest routing priority to lowest routing priority. This
functionality is inferred from the description for obtaining local
IP addresses given in the Knowledge Base Article Q160215.

Please note that the returned hostent is only freed when the thread
closes and is replaced if another hostent is requested.
WS_get_local_ips ( INTERNAL ) Returns the list of local IP addresses by going through the network adapters and using the local routing table to sort the addresses from highest routing priority to lowest routing priority . This functionality is inferred from the description for obtaining local IP addresses given in the Knowledge Base Article Q160215 . Please note that the returned hostent is only freed when the thread closes and is replaced if another hostent is requested .
static struct WS_hostent* WS_get_local_ips( char *hostname )
{
    int last_metric, numroutes = 0, i, j;
    DWORD n;
    PIP_ADAPTER_INFO adapters = NULL, k;
    struct WS_hostent *hostlist = NULL;
    PMIB_IPFORWARDTABLE routes = NULL;
    struct route *route_addrs = NULL;
    DWORD adap_size, route_size;
    if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
        return NULL;
    if (GetIpForwardTable(NULL, &route_size, FALSE) != ERROR_INSUFFICIENT_BUFFER)
        return NULL;
    adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
    routes = HeapAlloc(GetProcessHeap(), 0, route_size);
    route_addrs = HeapAlloc(GetProcessHeap(), 0, 0); 
    if (adapters == NULL || routes == NULL || route_addrs == NULL)
        goto cleanup;
    if (GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
        goto cleanup;
    if (GetIpForwardTable(routes, &route_size, FALSE) != NO_ERROR)
        goto cleanup;
    for (n = 0; n < routes->dwNumEntries; n++)
    {
        IF_INDEX ifindex;
        DWORD ifmetric, exists = FALSE;
        if (routes->table[n].u1.ForwardType != MIB_IPROUTE_TYPE_DIRECT)
            continue;
        ifindex = routes->table[n].dwForwardIfIndex;
        ifmetric = routes->table[n].dwForwardMetric1;
        for (j = 0; j < numroutes; j++)
        {
            if (route_addrs[j].interface == ifindex)
            {
                if (route_addrs[j].metric > ifmetric)
                    route_addrs[j].metric = ifmetric;
                exists = TRUE;
            }
        }
        if (exists)
            continue;
        route_addrs = HeapReAlloc(GetProcessHeap(), 0, route_addrs, (numroutes+1)*sizeof(struct route));
        if (route_addrs == NULL)
            goto cleanup; 
        route_addrs[numroutes].interface = ifindex;
        route_addrs[numroutes].metric = ifmetric;
        memcpy(&(route_addrs[numroutes].addr.s_addr), magic_loopback_addr, 4);
        numroutes++;
    }
   if (numroutes == 0)
       goto cleanup; 
    for (i = 0; i < numroutes; i++)
    {
        for (k = adapters; k != NULL; k = k->Next)
        {
            char *ip = k->IpAddressList.IpAddress.String;
            if (route_addrs[i].interface == k->Index)
                route_addrs[i].addr.s_addr = (in_addr_t) inet_addr(ip);
        }
    }
    hostlist = WS_create_he(hostname, 1, 0, numroutes+1, sizeof(struct in_addr));
    if (hostlist == NULL)
        goto cleanup; 
    hostlist->h_addr_list[numroutes] = NULL; 
    hostlist->h_aliases[0] = NULL; 
    hostlist->h_addrtype = AF_INET;
    hostlist->h_length = sizeof(struct in_addr); 
    last_metric = -1;
    for (i = 0; i < numroutes; i++)
    {
       struct in_addr addr;
       int metric = 0xFFFF;
       memcpy(&addr, magic_loopback_addr, 4);
       for (j = 0; j < numroutes; j++)
       {
           int this_metric = route_addrs[j].metric;
           if (this_metric > last_metric && this_metric < metric)
           {
               addr = route_addrs[j].addr;
               metric = this_metric;
           }
       }
       last_metric = metric;
       (*(struct in_addr *) hostlist->h_addr_list[i]) = addr;
    }
cleanup:
    HeapFree(GetProcessHeap(), 0, route_addrs);
    HeapFree(GetProcessHeap(), 0, adapters);
    HeapFree(GetProcessHeap(), 0, routes);
    return hostlist;
}
static struct WS_hostent * WS_get_local_ips ( char * hostname ) { int last_metric , numroutes = 0 , i , j ; DWORD n ; PIP_ADAPTER_INFO adapters = NULL , k ; struct WS_hostent * hostlist = NULL ; PMIB_IPFORWARDTABLE routes = NULL ; struct route * route_addrs = NULL ; DWORD adap_size , route_size ; if ( GetAdaptersInfo ( NULL , & adap_size ) != ERROR_BUFFER_OVERFLOW ) return NULL ; if ( GetIpForwardTable ( NULL , & route_size , FALSE ) != ERROR_INSUFFICIENT_BUFFER ) return NULL ; adapters = HeapAlloc ( GetProcessHeap ( ) , 0 , adap_size ) ; routes = HeapAlloc ( GetProcessHeap ( ) , 0 , route_size ) ; route_addrs = HeapAlloc ( GetProcessHeap ( ) , 0 , 0 ) ; if ( adapters == NULL || routes == NULL || route_addrs == NULL ) goto cleanup ; if ( GetAdaptersInfo ( adapters , & adap_size ) != NO_ERROR ) goto cleanup ; if ( GetIpForwardTable ( routes , & route_size , FALSE ) != NO_ERROR ) goto cleanup ; for ( n = 0 ; n < routes -> dwNumEntries ; n ++ ) { IF_INDEX ifindex ; DWORD ifmetric , exists = FALSE ; if ( routes -> table [ n ] . u1 . ForwardType != MIB_IPROUTE_TYPE_DIRECT ) continue ; ifindex = routes -> table [ n ] . dwForwardIfIndex ; ifmetric = routes -> table [ n ] . dwForwardMetric1 ; for ( j = 0 ; j < numroutes ; j ++ ) { if ( route_addrs [ j ] . interface == ifindex ) { if ( route_addrs [ j ] . metric > ifmetric ) route_addrs [ j ] . metric = ifmetric ; exists = TRUE ; } } if ( exists ) continue ; route_addrs = HeapReAlloc ( GetProcessHeap ( ) , 0 , route_addrs , ( numroutes + 1 ) * sizeof ( struct route ) ) ; if ( route_addrs == NULL ) goto cleanup ; route_addrs [ numroutes ] . interface = ifindex ; route_addrs [ numroutes ] . metric = ifmetric ; memcpy ( & ( route_addrs [ numroutes ] . addr . s_addr ) , magic_loopback_addr , 4 ) ; numroutes ++ ; } if ( numroutes == 0 ) goto cleanup ; for ( i = 0 ; i < numroutes ; i ++ ) { for ( k = adapters ; k != NULL ; k = k -> Next ) { char * ip = k -> IpAddressList . IpAddress . String ; if ( route_addrs [ i ] . interface == k -> Index ) route_addrs [ i ] . addr . s_addr = ( in_addr_t ) inet_addr ( ip ) ; } } hostlist = WS_create_he ( hostname , 1 , 0 , numroutes + 1 , sizeof ( struct in_addr ) ) ; if ( hostlist == NULL ) goto cleanup ; hostlist -> h_addr_list [ numroutes ] = NULL ; hostlist -> h_aliases [ 0 ] = NULL ; hostlist -> h_addrtype = AF_INET ; hostlist -> h_length = sizeof ( struct in_addr ) ; last_metric = -1 ; for ( i = 0 ; i < numroutes ; i ++ ) { struct in_addr addr ; int metric = 0xFFFF ; memcpy ( & addr , magic_loopback_addr , 4 ) ; for ( j = 0 ; j < numroutes ; j ++ ) { int this_metric = route_addrs [ j ] . metric ; if ( this_metric > last_metric && this_metric < metric ) { addr = route_addrs [ j ] . addr ; metric = this_metric ; } } last_metric = metric ; ( * ( struct in_addr * ) hostlist -> h_addr_list [ i ] ) = addr ; } cleanup : HeapFree ( GetProcessHeap ( ) , 0 , route_addrs ) ; HeapFree ( GetProcessHeap ( ) , 0 , adapters ) ; HeapFree ( GetProcessHeap ( ) , 0 , routes ) ; return hostlist ; }
WS_get_local_ips                (INTERNAL)
 Returns the list of local IP addresses by going through the network
 adapters and using the local routing table to sort the addresses
 from highest routing priority to lowest routing priority.
WS_get_local_ips ( INTERNAL ) Returns the list of local IP addresses by going through the network adapters and using the local routing table to sort the addresses from highest routing priority to lowest routing priority .
/* Obtain the size of the adapter list and routing table, also allocate memory */ /* HeapReAlloc doesn't work on NULL */ /* Obtain the adapter list and the full routing table */ /* Store the interface associated with each route */ /* Only store the lowest valued metric for an interface */ /* Memory allocation error, fail gracefully */ /* If no IP is found in the next step (for whatever reason)
         * then fall back to the magic loopback address.
         */ /* No routes, fall back to the Magic IP */ /* Find the IP address associated with each found interface */ /* Allocate a hostent and enough memory for all the IPs,
     * including the NULL at the end of the list.
     */ /* Failed to allocate a hostent for the list of IPs */ /* NULL-terminate the address list */ /* NULL-terminate the alias list */ /* = 4 */ /* Reorder the entries when placing them in the host list, Windows expects
     * the IP list in order from highest priority to lowest (the critical thing
     * is that most applications expect the first IP to be the default route).
     */ /* Cleanup all allocated memory except the address list,
     * the address list is used by the calling app.
     */