Question About Inaddr_Any

Question about INADDR_ANY

It doesn't get requests for every IP address on the internet(a), it gets requests for every IP address that it services. For example, it may have multiple NICs, each with a separate IP address or it may have a single NIC capable of managing multiple IP addresses (it may even have multiple NICs, each capable of handling multiple IP addresses.

The key snippet to look at is:

... we normally want an application on a multi-homed host to be able to receive datagrams or connection requests that specify any of the host’s IP addresses (my italics).

In other words, you may have a multi-homed set-up where your machine services 10.0.0.15 and 10.0.0.16. Using INADDR_ANY will allow you to pick up traffic for both those addresses, without picking up requests for 10.0.0.17 which may be the machine on the other end of the bench (or other side of the planet).

The following table, with the top row being request destinations and the left column being the address you're listening on, shows whether you'll be given a request (Y) or not (N):

Request to>  10.0.0.15  10.0.0.16  10.0.0.17
Bind to: *-------------------------------
10.0.0.15 | Y N N
10.0.0.16 | N Y N
INADDR_ANY | Y Y N

(a) It doesn't even see the vast majority of requests on the net. The vast majority don't even make it to your nearest router (or probably even your ISP). Even those that do make it to your nearest router, your particular machine might not see if they're destined for another machine on the local segment (promiscuous mode notwithstanding).

Understanding INADDR_ANY for socket programming

  1. bind() of INADDR_ANY does NOT "generate a random IP". It binds the socket to all available interfaces.

  2. For a server, you typically want to bind to all interfaces - not just "localhost".

  3. If you wish to bind your socket to localhost only, the syntax would be my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");, then call bind(my_socket, (SOCKADDR *) &my_sockaddr, ...).

  4. As it happens, INADDR_ANY is a constant that happens to equal "zero":

    http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html

    # define INADDR_ANY ((unsigned long int) 0x00000000)
    ...
    # define INADDR_NONE 0xffffffff
    ...
    # define INPORT_ANY 0
    ...
  5. If you're not already familiar with it, I urge you to check out Beej's Guide to Sockets Programming:

    http://beej.us/guide/bgnet/

Since people are still reading this, an additional note:

man (7) ip:

When a process wants to receive new incoming packets or connections,
it should bind a socket to a local interface address using bind(2).

In this case, only one IP socket may be bound to any given local
(address, port) pair. When INADDR_ANY is specified in the bind call,
the socket will be bound to all local interfaces.

When listen(2) is called on an unbound socket, the socket is
automatically bound to a random free port with the local address set
to INADDR_ANY.

When connect(2) is called on an unbound socket, the socket is
automatically bound to a random free port or to a usable shared port
with the local address set to INADDR_ANY...

There are several special addresses: INADDR_LOOPBACK (127.0.0.1)
always refers to the local host via the loopback device; INADDR_ANY
(0.0.0.0) means any address for binding...

Also:

bind() — Bind a name to a
socket:

If the (sin_addr.s_addr) field is set to the constant INADDR_ANY, as
defined in netinet/in.h, the caller is requesting that the socket be
bound to all network interfaces on the host. Subsequently, UDP packets
and TCP connections from all interfaces (which match the bound name)
are routed to the application. This becomes important when a server
offers a service to multiple networks. By leaving the address
unspecified, the server can accept all UDP packets and TCP connection
requests made for its port, regardless of the network interface on
which the requests arrived.

INADDR_ANY details

Technically neither. Read the documentation on bind (MSDN) for further details.

Sockets - Using INADDR_ANY on client side

This is the answer as provided by nos in a comment. If nos comes back and posts it as an answer, I will mark nos' post as the answer and delete this one.

INADDR_ANY is normally defined as 0. That is the IP address 0.0.0.0.
RFC 1122 says that means "This host on this network". The linux IP
stack seems to just route this to the loopback interface. (e.g. try
ping 0.0.0.0 or even just ping 0). I'd say the author made a typo, and
should have used INADDR_LOOPBACK.

What is the purpose and result of using INADDR_ANY?

When INADDR_ANY is given as the address in a bind call, this causes the socket to listen on the given port for any network interface.

After calling bind in this way, you'll see an entry like this in the output of the netstat command:

udp        0      0 0.0.0.0:46162           0.0.0.0:*  

This is a UDP socket that was bound to INADDR_ANY with port 46162.

When used as the interface address when setting the IP_ADD_MEMBERSHIP option, INADDR_ANY indicates that the OS will chose an interface to join the given multicast group on, i.e. the "default" network interface.

It does not mean that it will join the group on all interfaces. To do that, you would need to itereate over all network interfaces and set the IP_ADD_MEMBERSHIP option on each one.

I've worked with Linux, Solaris, FreeBSD, and Windows, and none of them joins a multicast group on all interfaces when using INADDR_ANY.

Difference binding to INADDR_ANY and a specific IP

Binding to specific interfaces is something to use only in very special circumstances, when the application needs to "know" the local IP addresses and the immediate network layout. A routing daemon program is perhaps the best example.

Another, more pedestrian example: if you have a multi-homed machine (i.e. a machine with more than one connection to the Internet, possibly different ISPs) you can bind to a specific interface to make sure that the connection goes through a given connection. Binding separately to each network interface, the application could detect link down etc.

Implementations of protocols that need to "know" the local IP address (infamous examples: FTP, SIP, UPnP) tend to bind sockets to specific interfaces. (I consider them to be bad protocols, since they violate the isolation between transport and application layers).

Save for these cases, it is normally over-engineering to bind to specific interfaces, because addresses and interfaces may change, and the program must detect these conditions to update the respective sockets.

bind with INADDR_ANY

On Linux when you bind to INADDR_ANY then the socket stays bound to 0.0.0.0 and will accept connection to any local IP address no matter how that changes. Only when a TCP connection is established then the single connection is bound to the IP address it was received on. Other connections may still be received on any address.



Related Topics



Leave a reply



Submit