dlls/ws2_32/socket.c
/***********************************************************************
 *               interface_bind         (INTERNAL)
 *
 * Take bind() calls on any name corresponding to a local network adapter and restrict the given socket to
 * operating only on the specified interface.  This restriction consists of two components:
 *  1) An outgoing packet restriction suggesting the egress interface for all packets.
 *  2) An incoming packet restriction dropping packets not meant for the interface.
 * If the function succeeds in placing these restrictions (returns TRUE) then the name for the bind() may
 * safely be changed to INADDR_ANY, permitting the transmission and receipt of broadcast packets on the
 * socket. This behavior is only relevant to UDP sockets and is needed for applications that expect to be able
 * to receive broadcast packets on a socket that is bound to a specific network interface.
 */
interface_bind         (INTERNAL)
Take bind() calls on any name corresponding to a local network adapter and restrict the given socket to
operating only on the specified interface.  This restriction consists of two components:
1) An outgoing packet restriction suggesting the egress interface for all packets.
2) An incoming packet restriction dropping packets not meant for the interface.
If the function succeeds in placing these restrictions (returns TRUE) then the name for the bind() may
safely be changed to INADDR_ANY, permitting the transmission and receipt of broadcast packets on the
socket. This behavior is only relevant to UDP sockets and is needed for applications that expect to be able
to receive broadcast packets on a socket that is bound to a specific network interface.
interface_bind ( INTERNAL ) Take bind () calls on any name corresponding to a local network adapter and restrict the given socket to operating only on the specified interface . This restriction consists of two components : 1 ) An outgoing packet restriction suggesting the egress interface for all packets . 2 ) An incoming packet restriction dropping packets not meant for the interface . If the function succeeds in placing these restrictions ( returns TRUE ) then the name for the bind () may safely be changed to INADDR_ANY permitting the transmission and receipt of broadcast packets on the socket . This behavior is only relevant to UDP sockets and is needed for applications that expect to be able to receive broadcast packets on a socket that is bound to a specific network interface .
static BOOL interface_bind( SOCKET s, int fd, struct sockaddr *addr )
{
    struct sockaddr_in *in_sock = (struct sockaddr_in *) addr;
    unsigned int sock_type = 0;
    socklen_t optlen = sizeof(sock_type);
    in_addr_t bind_addr = in_sock->sin_addr.s_addr;
    PIP_ADAPTER_INFO adapters = NULL, adapter;
    BOOL ret = FALSE;
    DWORD adap_size;
    int enable = 1;
    if (bind_addr == htonl(WS_INADDR_ANY) || bind_addr == htonl(WS_INADDR_LOOPBACK))
        return FALSE; 
    if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &sock_type, &optlen) == -1 || sock_type != SOCK_DGRAM)
        return FALSE; 
    if (GetAdaptersInfo(NULL, &adap_size) != ERROR_BUFFER_OVERFLOW)
        goto cleanup;
    adapters = HeapAlloc(GetProcessHeap(), 0, adap_size);
    if (adapters == NULL || GetAdaptersInfo(adapters, &adap_size) != NO_ERROR)
        goto cleanup;
    for (adapter = adapters; adapter != NULL; adapter = adapter->Next)
    {
        in_addr_t adapter_addr = (in_addr_t) inet_addr(adapter->IpAddressList.IpAddress.String);
        if (bind_addr == adapter_addr)
        {
#if defined(IP_BOUND_IF)
            if (setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &adapter->Index, sizeof(adapter->Index)) != 0)
                goto cleanup;
            ret = TRUE;
#elif defined(LINUX_BOUND_IF)
            in_addr_t ifindex = (in_addr_t) htonl(adapter->Index);
            struct interface_filter specific_interface_filter;
            struct sock_fprog filter_prog;
            if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)) != 0)
                goto cleanup; 
            specific_interface_filter = generic_interface_filter;
            specific_interface_filter.iface_rule.k = adapter->Index;
            specific_interface_filter.ip_rule.k = htonl(adapter_addr);
            filter_prog.len = sizeof(generic_interface_filter)/sizeof(struct sock_filter);
            filter_prog.filter = (struct sock_filter *) &specific_interface_filter;
            if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) != 0)
                goto cleanup; 
            ret = TRUE;
#else
            FIXME("Broadcast packets on interface-bound sockets are not currently supported on this platform, "
                  "receiving broadcast packets will not work on socket %04lx.\n", s);
#endif
            break;
        }
    }
    if (ret && setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) == 0)
        TRACE("Socket %04lx bound to interface index %d\n", s, adapter->Index);
    else
        ret = FALSE;
cleanup:
    if(!ret)
        ERR("Failed to bind to interface, receiving broadcast packets will not work on socket %04lx.\n", s);
    HeapFree(GetProcessHeap(), 0, adapters);
    return ret;
}
static BOOL interface_bind ( SOCKET s , int fd , struct sockaddr * addr ) { struct sockaddr_in * in_sock = ( struct sockaddr_in * ) addr ; unsigned int sock_type = 0 ; socklen_t optlen = sizeof ( sock_type ) ; in_addr_t bind_addr = in_sock -> sin_addr . s_addr ; PIP_ADAPTER_INFO adapters = NULL , adapter ; BOOL ret = FALSE ; DWORD adap_size ; int enable = 1 ; if ( bind_addr == htonl ( WS_INADDR_ANY ) || bind_addr == htonl ( WS_INADDR_LOOPBACK ) ) return FALSE ; if ( getsockopt ( fd , SOL_SOCKET , SO_TYPE , & sock_type , & optlen ) == -1 || sock_type != SOCK_DGRAM ) return FALSE ; if ( GetAdaptersInfo ( NULL , & adap_size ) != ERROR_BUFFER_OVERFLOW ) goto cleanup ; adapters = HeapAlloc ( GetProcessHeap ( ) , 0 , adap_size ) ; if ( adapters == NULL || GetAdaptersInfo ( adapters , & adap_size ) != NO_ERROR ) goto cleanup ; for ( adapter = adapters ; adapter != NULL ; adapter = adapter -> Next ) { in_addr_t adapter_addr = ( in_addr_t ) inet_addr ( adapter -> IpAddressList . IpAddress . String ) ; if ( bind_addr == adapter_addr ) { #if defined ( IP_BOUND_IF ) if ( setsockopt ( fd , IPPROTO_IP , IP_BOUND_IF , & adapter -> Index , sizeof ( adapter -> Index ) ) != 0 ) goto cleanup ; ret = TRUE ; #elif defined ( LINUX_BOUND_IF ) in_addr_t ifindex = ( in_addr_t ) htonl ( adapter -> Index ) ; struct interface_filter specific_interface_filter ; struct sock_fprog filter_prog ; if ( setsockopt ( fd , IPPROTO_IP , IP_UNICAST_IF , & ifindex , sizeof ( ifindex ) ) != 0 ) goto cleanup ; specific_interface_filter = generic_interface_filter ; specific_interface_filter . iface_rule . k = adapter -> Index ; specific_interface_filter . ip_rule . k = htonl ( adapter_addr ) ; filter_prog . len = sizeof ( generic_interface_filter ) / sizeof ( struct sock_filter ) ; filter_prog . filter = ( struct sock_filter * ) & specific_interface_filter ; if ( setsockopt ( fd , SOL_SOCKET , SO_ATTACH_FILTER , & filter_prog , sizeof ( filter_prog ) ) != 0 ) goto cleanup ; ret = TRUE ; #else FIXME ( " " " \n " , s ) ; #endif break ; } } if ( ret && setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR , & enable , sizeof ( enable ) ) == 0 ) TRACE ( " \n " , s , adapter -> Index ) ; else ret = FALSE ; cleanup : if ( ! ret ) ERR ( " \n " , s ) ; HeapFree ( GetProcessHeap ( ) , 0 , adapters ) ; return ret ; }
interface_bind         (INTERNAL)
 Take bind() calls on any name corresponding to a local network adapter and restrict the given socket to
 operating only on the specified interface.
interface_bind ( INTERNAL ) Take bind () calls on any name corresponding to a local network adapter and restrict the given socket to operating only on the specified interface .
/* Not binding to a network adapter, special interface binding unnecessary. */ /* Special interface binding is only necessary for UDP datagrams. */ /* Search the IPv4 adapter list for the appropriate binding interface */ /* IP_BOUND_IF sets both the incoming and outgoing restriction at once */ /* Failed to suggest egress interface */ /* Failed to specify incoming packet filter */ /* Will soon be switching to INADDR_ANY: permit address reuse */