source IP in multihomed client host while bind is called - linux

Which is the source IP address in tcp socket if bind is called on a multihomed client host? Client has two interfaces eth0(IP0) and eth1(IP1) and the client tcp socket is bound to IP0. After socket, bind, connect in client, it sends a packet to server.The destination IP isservIP. But servIP and IP0 are not in a same subnet(Maybe servIP and IP1 are). Which is the source IP in the packet sent to server? And what will getsockname return?

There are two separate issues here:
1) Which IP to bind on?
When calling bind() you have an option to specify and address to bind on or you can leave this decision to TCP/IP stack on your computer. You can pass a specific address in 'addr' parameter or leave it as INADDR_ANY. You can find more information how to do it in manual page of ip(7). If you call bind() providing the valid IP address and call to bind() succeeds, then datagrams sent using the binded socket will have their source address set to the value provided in call to bind().
2) How the packet is routed?
The way your packet is routed depend only on the destination address and not the source address. It can be that your source address will be the one from eth0 and it will go out through eht1. This is because the routing system in your OS is using destination based routing as opposed to source based routing. You can always see which adapter will be used by issuing "route" command in the console of your OS and comparing the output with the destination address

Related

What happens to TCP socket when IP address changes?

Is there any error on a socket when writing to it after IP address change?
In my I'm using TCP socket, both read/write (non-passive), no TCP or application keep-alive.
To inspect this case I use socat to connect to a simple echo server on my local network. The connection is OK until I change the client IP address on my router and restart the network interface.
At this point, I can write to a socket without any errors despite the IP of the client was changed, but no messages are being delivered anymore. I wait for some minutes and change the IP back. All the 'stashed' messages which were unable to be sent are being sent.
As far as I understand, when client IP was changed TCP connection does not exist anymore.
Why there are no errors when writing to the socket when IP was changed? Is this specific to a Linux TCP stack or specified by TCP/IP?
A TCP connection is defined by source IP, source port, destination IP, and destination port. Changing the client's IP address on your router does not cause the connection on your client and server to cease to exist immediately; however, if you leave the router in this state long enough, the connection will eventually cease to exist after certain amount of retries and timeouts have occurred. The exact amount is determined via configurable kernel parameters both on your client and on your echo server. You can inspect these parameters with sysctl -a | grep tcp
After you've changed the client's IP address on your router, the client is still able to send packets to the server, and the server is also able to receive these packets, but the server's attempt to reply/acknowledge back to the client is unable to be routed back to the client. This leads to retries up to a certain limit on the client (which is why you saw no errors on the client side). Once you've reverted the client's IP back on your router, the server is able to communicate with the client again as the router is now able to correctly route the server's packet to the client.
This retry behavior is not specific to the Linux TCP stack. rfc 2988 defines the standard algorithm that senders are required to use to compute and manage their retransmission timer.

Does routing affect a socket with a bound source address?

Let's say I have two network interfaces:
eth0 with address 10.0.0.1
eth1 with address 192.168.0.1
Using route or ip route add I have set it to route:
All addresses to eth0
1.2.3.4 only to eth1
So packets to 1.2.3.4 should be routed to eth1, and everything else to eth0.
I then create a UDP socket and use bind() to set its local address to 192.168.0.1. Then I send a packet to 1.2.3.4.
Will it be be sent over eth1 per the routing table or eth0 because it is bound to that IP address? I tried, and it seems to be sent on eth1.
Is there a way I can force a socket to use eth0, which has a valid route to the destination, but not the most specific rule? I know about SO_BINDTODEVICE, but prefer to avoid using interface names in C code.
For sockets if you want the the Kernel and its routing table to pick the best interface for you using any available port you don't have to call bind() before sending datagram socket.
If you do bind a socket, it will be bound to a network device with that specific IP address. But does it make sense if packet can't reach destination address from that network device?

Resolve IP next hop with socket programming on Linux

Working with Linux.
Given a specific destination IP address, I need to populate the ARP cache with its next hop MAC address and interface.
Other mechanism in my software project will take this MAC address and push it to an FPGA.
If I open a TCP connection to the address it will be resolved and TCP handshake packets are sent. If I open a UDP socket and 'connect' it to the address it will not be resolved. If I send a single packet over the connected UDP socket it is resolved.
arp(7) documentation explains this: "... Requests are sent only when there is data queued for sending".
I can't call the 'arp' utility directly.
My question: is there a way to convince the system to populate an address by sending ARP in the background without the need for actually sending a packet?
I hope for some ioctl or setsockopt.
I prefer a generic solution that will also work for IPv6 neighbor resolution.
Thanks,
Gur

Does accept function return error(-1) if TCP server goes out of network

Does the accept function returns error(-1) if the Ethernet interface it is attached goes out of network?if not how does the application(TCP server) will know that its interface is not active any more ??
I am using one thread for accepting the connection and not using any "select" statement for doing so.Directly calling accept() function but somehow it is not retuning error if I remove the IP address from Ethernet interface.
using C and working environment is linux.
Usually you don't bind your server socket to a specific IP address (you use INADDR_ANY). So even if you remove your ethernet IP address, you could still contact your server using the loopback interface. Or some other interface with an IP address.
If you want to make sure that your server is reachable from the net, checking the interface status does not get you much. It's just a single hop on a long path through the network. You'd need a testing client somewhere else to check the reachability of your server.

multiple IP addresses, chooce the sender

I have eth0 and eth1. I am creating a simple tcp program with gsoap. the endpoint is 1.2.3.4.
The endpoint receives my data, but the IP of eth0 is shown in the sender details. I would like my receiver to see eth1 instead of eth0.
Is this possible?
Use the bind(2) call to select the source IP, or create an explicit route(8) to the server via eth1. Second option is probably preferable since you don't need to modify the client source code.

Resources