What happens when I call bind() multiple times on a single socket - sockets

bind() will assign a local address to a socket. What happens when I call the bind() function multiple times on the same socket with different addresses (possibly with different families)?
What I want to be able to do is to bind a single socket with a local IPv4 and a local IPv6 (assigned the same local hostname in /etc/hosts). Can this actually work?
Will the second call to bind() fail? Will it replace the first bound address with the second one? Will it actually bind the socket to multiple addresses, like when binding with 0.0.0.0 ?

What happens when I call the bind() function multiple times on the same socket with different addresses (possibly with different families)?
Subsequent calls will fail with an EINVAL error, per the documentation:
EINVAL
The socket is already bound to an address.
Also, you can't bind() a socket to an address family that is different than the family specified to socket():
EINVAL
addrlen is wrong, or addr is not a valid address for this socket's domain.
Which means you can't create an IPv4 (AF_INET) socket and bind() it to an IPv6 (AF_INET6) address, and vice versa.
What I want to be able to do is to bind a single socket with a local IPv4 and a local IPv6 (assigned the same local hostname in /etc/hosts). Can this actually work?
No. The only way to have a socket bound to both IPv4 and IPv6 is to create an IPv6 (AF_INET6) socket and disable its IPV6_V6ONLY option before bind()'ing it to address ::0 only. This is used to create a dual-stack listening socket that can accept incoming traffic from both IPv4 and IPv6 peers on all local interfaces.
If you want to bind() to specific addresses, you have to create a separate socket for each address.
Will the second call to bind() fail?
Yes.
Will it replace the first bound address with the second one?
No.
Will it actually bind the socket to multiple addresses, like when binding with 0.0.0.0 ?
No.

Related

read() form an unbinded socket?

What happens if one reads from an unbinded socket? More specifically on an UDP socket?
If the socket has been used to send information the socket will be binded to a port (and address) and therefore we will be listening on that (addr, port), but if the socket is completely unbinded what is the expected behavior?
How will that socket will respond to select/epoll in that case for read operation?
It's variously specified, or not specified.
From man 7 udp (Linux):
In order to receive packets, the socket can be bound to a local address first by using bind(2). Otherwise the socket layer will automatically assign a free local port out of the range defined by /proc/sys/net/ipv4/ip_local_port_range and bind the socket to INADDR_ANY.
From MSDN recv() function:
The local address of the socket must be known. For server applications, use an explicit bind function or an implicit accept or WSAAccept function. Explicit binding is discouraged for client applications. For client applications, the socket can become bound implicitly to a local address using connect, WSAConnect, sendto, WSASendTo, or WSAJoinLeaf.
and
WSAEINVAL: The socket has not been bound with bind, ...
I cannot answer for BSD, Solaris, HP-UX, AIX, ...

Can I bind a client socket to an ip not belongs to any interfaces?

For a client socket, I can use bind() to bind it to a specific source Ip address to select a specific interface. Or I can use connect() directly then it will pick the source ip based on routing table.
I wonder can I bind a client socket to an ip not belongs to any interfaces ? E.g.: I have two interfaces:
eth0 : ip0
eth1 : ip1
(1) If I bind the client socket to ip2. Is this feasible ?
(2) If (1) is feasible, assuming client socket sent packets thru eth0. Then I configure the iptables in this client host, to forward all incoming packets to ip0 (eth0). In this case, if there are packets sent back from server side with destination ip address is ip2 (assuming this packet will reach my client host). Will my client socket receive the packet ?
Thanks in advance.
I don't really understand your question, but here goes:
For client sockets, you typically want the the OS and its routing table to pick the best interface for you using any available port. In which case, you bind to INADDR_ANY (0) and port 0. Or don't explicitly call bind at at all. Just call connect() and it will do the right thing.
If you need the client connection to occur through a specific interface, then bind the socket to a specific IP address. And then the OS will attempt to use that interface for the subsequent connect call and all traffic after that.
Attempting to bind the socket to an IP that doesn't belong to a local interface is surely going to result in an error.
Not sure what you mean about the iptables stuff. Sounds dicey.
Please have a look at:
https://www.rsyslog.com/doc/v8-stable/configuration/modules/omfwd.html#ipfreebind
MAN:
https://man7.org/linux/man-pages/man7/ip.7.html
IP_FREEBIND (since Linux 2.4)
If enabled, this boolean option allows binding to an IP
address that is nonlocal or does not (yet) exist. This
permits listening on a socket, without requiring the
underlying network interface or the specified dynamic IP
address to be up at the time that the application is
trying to bind to it. This option is the per-socket
equivalent of the ip_nonlocal_bind /proc interface
described below.

What does it mean to bind() a socket to any address other than localhost?

I don't understand what it means to bind a socket to any address other than 127.0.0.1 (or ::1, etc.).
Am I not -- by definition -- binding the socket to a port on my own machine.. which is localhost?
What sense does it make to bind or listen to another machine or IP address's port?
Conceptually, it just doesn't make sense to me!
(This has proven surprisingly hard to Google... possibly because I'm not Googling the right terms.)
Binding of a socket is done to address and port in order to receive data on this socket (most cases) or to use this address/port as the source of the data when sending data (for example used with data connections in FTP server).
Usually there are several interfaces on a specific machine, i.e. the pseudo-interface loopback where the machine can reach itself, ethernet, WLAN, VPN... . Each of these interfaces can have multiple IP addresses assigned. For example, loopback usually has 127.0.0.1 and with IPv6 also ::1, but you can assign others too. Ethernet or WLAN have the IP addresses on the local network, i.e. 172.16.0.34 or whatever.
If you bind a socket for receiving data to a specific address you can only receive data sent to this specific IP address. For example, if you bind to 127.0.0.1 you will be able to receive data from your own system but not from some other system on the local network, because they cannot send data to your 127.0.0.1: for one any data to 127.0.0.1 will be sent to their own 127.0.0.1 and second your 127.0.0.1 is an address on your internal loopback interface which is not reachable from outside.
You can also bind a socket to a catch-all address like 0.0.0.0 (Ipv4) and :: (Ipv6). In this case it is not bound to a specific IP address but will be able to receive data send to any IP address of the machine.

sockets, its attributes and SO_REUSEADDR option

i have a few basic questions:
1.A socket is represented by a protocol, a local ip, local port, remote ip and remote port. Suppose such a connection exists between a client and a server. Now when i bind another client to same local port and ip, it got bound(i used SO_REUSEADDR) but connect operation by second client to the same remote ip and port failed.So, is there no way a third process can share the same socket?
2.When we call listen() on a socket bound to a local port and ip, it listens for connections. When a client connects, it creates a socket (say A). It completes 3 way handshake and then starts a different socket(say B) and also deletes the socket A (Source) .The new client is taken care of by the new socket B. So, what kind of a socket represents a listening socket i.e. what is the remote ip and port and is socket A different than that socket or just addition of remote ip and port to listening socket forms A?
3.I read that SO_REUSEADDR can establish a listening socket on a port if there is no socket listening on that port and ip and all sockets on that port and ip have SO_REUSEADDR option set.But then i also came across a text which said if a client is bound to a port and ip, another client can't bind to it(even if SO_REUSEADDR is used) unless the first client successfully calls connect(). There was no listening socket(it is a client so we there is no call to connect()) on that port and ip in this example. So, why isn't another client allowed?
Thanks in advance.
Correct: there is no way to create two different sockets with the same protocol, local port, local address, remote port, and remote address. There would be nothing to tell which packets belonged to which socket!
A listening socket does not have a remote address and remote port. That's OK, because there are no packets on the wire associated with this socket (yet). Actually, all sockets start out with neither a local nor remote address or port. These properties are only assigned later when bind() (for local) and connect()/accept() (for remote) are called.
Until you call connect() or listen() on a socket, there isn't any different between a server (listening) or client socket. They're the same thing. So it would be more correct here to say that no two sockets are allowed to share the same protocol, local address, and local port if neither has a remote address or port.
This isn't a problem in practice though, because you usually don't call bind() on a client socket, which means there is an implicit bind() to an ephemeral port at connect() time. These typical client sockets can't conflict with a listening socket because they go from having no addresses associated with them to having both local and remote addresses associated with them, skipping the state where they have only a local one.

Getting the IP of the interface that received a recvfrom() UDP packet (Microsoft)

Using recvfrom() on a socket bound to INADDR_ANY on a Microsoft multihomed PC.
when recvfrom() gets an UDP packet: how can I find the Interface (IP) that received the packet?
There is no way to know the receiving IP when a single listening socket is bound to multiple IPs. Instead of binding a single socket to INADDR_ANY, you can query the machine's list of local IPs using GetAdaptersInfo() and/or GetAdapterAddresses(), then create a separate listening socket for each IP. You can use getsockname() to know which IP a given socket is bound to, but only when that socket is bound to a specific IP, not multiple IPs.