Socket Binding on a Multihomed Host


On a multihomed host, which network interface does my socket bind to? In the following example, the socket is bound to INADDR_ANY, which means the system will choose one for the socket. The same thing happens for those sockets that do not explicitly call "bind()".


  // The sockaddr_in structure specifies the address family,
  // IP address, and port for the socket that is being bound.
  sockaddr_in service;
  service.sin_family = AF_INET;
  service.sin_addr.s_addr = htonl (INADDR_ANY);
  service.sin_port = htons(27015);

  //----------------------
  // Bind the socket.
  if (bind( ListenSocket,
    (SOCKADDR*) &service,
    sizeof(service)) == SOCKET_ERROR) {
    printf("bind() failed.\n");
    closesocket(ListenSocket);
    return -1;
  }


What's happening is a Windows system (including Windows CE) will choose a source IP address randomly for the socket and it really does not matter as the IP packets will be routed to the appropriate outgoing interface based on the destination IP address of the packet. The source IP address of the packet may not match the one that is chosen eventually.

According to Windows 2000 Implementation Details:


When an IP datagram is sent from a multihomed host, it is passed to the interface with the best apparent route to the destination. Accordingly, the datagram may contain the source IP address of one interface in the multihomed host, yet be placed on the media by a different interface. The source media access control address on the frame is that of the interface that actually transmitted the frame to the media, and the source IP address is the one that the sending application sourced it from, not necessarily one of the IP addresses associated with the sending interface in the Network Connections UI.




In fact, Windows, as well as most operating systems, is one of the so-called 'weak end model' systems on which an address refers to a host not an interface. This means when a packet arrives at one of the interfaces on a multihomed system, it will be picked up by the network stack so long as its destination address matches the address of one of the addresses. On the other hand, the strong model requires that the packet's destination address matches the underlying interface address it arrives at. As for sending packets, weak end systems will send packets from an interface that does not match the source IP address of the packet, and strong end systems will NOT do that. See RFC 1122: Requirements for Internet Hosts - Communication Layers  for details of the two models.  We are talking about IP address here - Windows, as well as most hosts on the Internet, adopts weak end model at network layer and strong end model at link layer.  Some operating system allows user to configure this feature. 


Back to the multihomed Windows Mobile devices where both GPRS adapter and WiFi adapter are available, how to force an application use WiFi and never reach the other?


For a Connection Manager application, it is easy to specify a connection name with the ConnMgrMapConRef() function for the connection to be established.


For a typical winsock application that does not use connection manager API, how can it choose WiFi connection? Use bind(), right?


In the sockaddr_in struct, you can set the source IP address. What if you don't know the IP address of the WiFi adapter? Well, as long as you know the adapter name, you can use ip helper API: GetAdaptersInfo() to retrieve a list of adapters from the current system. Then go find the WiFi adapter name, and call GetAdapterInfo() to retrieve its address.


Recall the 'weak system model'? Even if you call bind() to bind the socket to a specific local address (which means connection manager's AutoLSP is not associated with the socket), still your packets on this socket are subject to the routing decision in terms of choosing which physical interface will be used. 


That is, even if you bind to the IP address of the WiFi interface, your outgoing packets (assuming the destination address is not onlink with your WiFi interface; if it is, the onlink route will be used) in this socket may still go through the GPRS connection if the best route to the destination is via the GPRS interface


Luckily, due to the way CE network stack computes network metric for different interfaces, default route of the WiFi interface will always have a lower metric than that of the GPRS WWAN interface. Thus when you have both interfaces active, the best route will still be the default route for the WiFi interface.


Below is the routing table of Windows Mobile device with GPRS and WiFi active. The GPRS WWAN interface has an address of 10.178.149.237, and the WiFi interface 172.28.161.168.


\> route print
=============================================================================
Interface List
      0x2  00 09 2d e8 d3 d0     TNETWLN1
  0x10003  20 4c 4f 43 41 4c     WWAN1-internet2.voicestream.com-1
  0x10004  82 00 60 0f e8 00     RndisFn1
=============================================================================
=============================================================================
 Active Routes
 The no. of entries is ::: 18
      Destination       Netmask       GatewayAddress     Interface    Metric
 ----------------------------------------------------------------------------


     0.0.0.0          0.0.0.0     172.28.160.1   172.28.161.168      30
       0.0.0.0          0.0.0.0    10.178.149.18   10.178.149.237      50
     10.178.149.0    255.255.255.0   10.178.149.237   10.178.149.237      50
   10.178.149.237  255.255.255.255        127.0.0.1        127.0.0.1      50
   10.255.255.255  255.255.255.255   10.178.149.237   10.178.149.237      50
        127.0.0.0        255.0.0.0        127.0.0.1        127.0.0.1       1
      169.254.2.0    255.255.255.0      169.254.2.1          0.0.0.0      30
      169.254.2.1  255.255.255.255        127.0.0.1        127.0.0.1      30
  169.254.255.255  255.255.255.255      169.254.2.1          0.0.0.0      30
     172.28.160.0    255.255.252.0   172.28.161.168   172.28.161.168      30
   172.28.161.168  255.255.255.255        127.0.0.1        127.0.0.1      30
   172.28.255.255  255.255.255.255   172.28.161.168   172.28.161.168      30
        224.0.0.0        240.0.0.0   172.28.161.168   172.28.161.168      30
        224.0.0.0        240.0.0.0      169.254.2.1          0.0.0.0      30
        224.0.0.0        240.0.0.0   10.178.149.237   10.178.149.237      50
  255.255.255.255  255.255.255.255   172.28.161.168   172.28.161.168       1
  255.255.255.255  255.255.255.255   10.178.149.237   10.178.149.237       1
  255.255.255.255  255.255.255.255      169.254.2.1          0.0.0.0       1
=============================================================================


To confirm, I launched a UDP socket and started to send something to a remote site.  Then I changed the GPRS WWAN default route metric from 50 to 10. From that point forward, my UDP packets to the remote host were delivered to the GPRS WWAN adpater (I knew this by looking at the source MAC address in Ethernet frame header) , although the IP source and destination address remain the same as those previous packets.


 

Comments (3)
  1. R M says:

    It is indeed convenient that WiFi is defaulted to being used first, but what if you wish for the GPRS to have priority over your WiFi? What can you do to change it?

  2. raboyd says:

    Thanks for the good information. Is there anyway to force the packet to actually go out the bound interface regardless of route information? Maybe something in the registry to toggle to disable this feature?

    Thanks,

    Mona

  3. Alexz says:

    What about joining a multicast group from a multihomed host on a prefered interface?

Comments are closed.

Skip to main content