How does the OS resolve a request to connect to 0.0.0.0?

2

As I understand 0.0.0.0 means all network interfaces of this host (including 127.0.0.1).

Suppose I have three interfaces 192.0.2.40, 203.0.113.150 and 127.0.0.1 on some host (OS linux).

On 192.0.2.40:777, I have ServerA. On 203.0.113.150:777, I have ServerB. How does the OS resolve a request to connect to 0.0.0.0? I mean when the same port (777) is listening on different interfaces what server(ServerA or serverB) and why will be connected when I will do in terminal of this host telnet 0.0.0.0 777

Pavel

Posted 2018-03-23T07:18:40.480

Reputation: 445

@DavidPostill Could you say, is there information why linux OS redirects 0.0.0.0 to localhost in duplicate that you gave? I don't see, do you? – Pavel – 2018-03-26T13:40:04.237

Agreed, the so-called duplicate is anything but. – plugwash – 2018-09-19T14:07:44.800

Answers

5

It only means that as a source address (i.e. when binding a socket to a local interface). As the destination address it doesn't have this meaning – it's technically an illegal address.

However it seems that originally BSD treated it as a loopback connection and Linux carries it on.

For IPv4, an all-zeros destination is handled in net/ipv4/route.c at route lookup time:

struct rtable *ip_route_output_key_hash_rcu(...) {
    ...
    if (!fl4->daddr) {
        fl4->daddr = fl4->saddr;
        if (!fl4->daddr)
            fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
        dev_out = net->loopback_dev;
        fl4->flowi4_oif = LOOPBACK_IFINDEX;
        res->type = RTN_LOCAL;
        flags |= RTCF_LOCAL;
        goto make_route;
    }
    ...
}

Which translates to "If destination is empty, fill it in with 127.0.0.1 and route via the lo interface". The OS pretends that you tried to connect to localhost.

The same in IPv6 is handled at protocol level (individually by TCP and UDP). For example, net/ipv6/tcp_ipv6.c contains:

static int tcp_v6_connect(...) {
    ...
    /*
     *  connect() to INADDR_ANY means loopback (BSD'ism).
     */
    if (ipv6_addr_any(&usin->sin6_addr)) {
        if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
            ipv6_addr_set_v4mapped(htonl(INADDR_LOOPBACK),
                           &usin->sin6_addr);
        else
            usin->sin6_addr = in6addr_loopback;
    }
    ...
}

Meanwhile in net/ipv6/udp.c:

int udpv6_sendmsg(...) {
    ...
    if (!ipv6_addr_any(daddr))
        fl6.daddr = *daddr;
    else
        fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
    ...
}

user1686

Posted 2018-03-23T07:18:40.480

Reputation: 283 655

Thank you for your explanation. So, in my example when I do telnet 0.0.0.0 777 I will get connection refused. However, if I also had a ServerC on 127.0.0.0:777 I would connect to ServerC. Do I understand it right? – Pavel – 2018-03-23T08:05:19.690

I don't accept your answer as this is theory, but not the concrete answer to concrete question. – Pavel – 2018-03-26T13:40:47.550

3For a question "how does the OS [...]", the source code of that OS is as concrete as it could possibly get. – user1686 – 2018-03-26T14:10:12.667

@PavelK The answer is both concrete and correct and you should accept it. – Jenny D – 2018-03-27T07:48:28.757

@JennyD You never give up, don't you? However, that's enough. You can downvote but I won't. – Pavel – 2018-03-27T08:50:08.553

@PavelK I followed the question here because I was interested in the answer, and have upvoted the answer. I'm sorry that my attempts to be of assistance were so clumsy that I offended you; it was not my intention and I apologize. – Jenny D – 2018-03-27T09:32:25.143