We have an issue with creating an ordinary TCP socket connection to a device that is connected on a link-local net (simple peer to peer Ethernet). Our code is in C++ and we use the normal POSIX socket API.
The scenario is like this:
- We have a device with ordinary Ethernet connected to a USB-Ethernet adaptor.
- We plug in the USB-Ethernet adaptor in a Mac or iPad.
- The device establishes link-local IP address and announces a service via mDNS/DNS-SD
- The Mac/iPad Bonjour system picks up the device service and we get the information in our app.
- Our app want to connect to the service using a normal TCP socket connection to the device's link-local address.
So far this is normal and working as expected. However from here something unexpected happens:
- We create a "socket()" and do a "connect()".
- WireShark shows that the TCP connection is established on the correct interface, with the correct destination IP/port, but with a source IP/port from a different interface. Fx. the TCP SYN from the Mac has destination ip 169.254.5.253 (correct) but source IP 192.168.1.101 (wrong - that IP does not exist on that interface). Consequently the TCP connection never get established.
Workaround: We have found out that using "bind()" to bind the socket to a specific source link-local IP on the relevant interface works. Then the TCP SYN comes out with correct source IP. However binding an outgoing TCP that is a very unusual thing to and we are surprised that it doesn't just work without it.
Other information: Parts of this issue seems to be timing related. Without the "bind()" it sometimes works if we retry the connect after timeout. Occasionally it works the first time. Having a Ethernet switch in between also sometimes helps.
Have we missed something or is this a problem in macOS/iOS?
Thanks! :)