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() toretrieve 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.