Home > Software design >  How to connect to a IPv6 link local address discovered using IPv4 and set the correct network interf
How to connect to a IPv6 link local address discovered using IPv4 and set the correct network interf

Time:06-24

Our Delphi/Indy application discovers devices using mDNS on IPv4 but some of the addresses found are link-local IPv6 addresses (specified in AAAA records along with other A records). We want to provide the option of using either IPv4 or IPv6 addresses to connect to the devices because some people insist on setting static IPv4 addresses which due to a change in location or configuration become incompatible with the subnet where they are located.

But when the application attempts to establish a TCP connection to one of these link-local IPv6 addresses, the first attempt usually fails because Windows doesn't know which interface to use. (This same behaviour can be observed when just ping-ing the address from the command line. The problem is solved by writing % followed by the appropriate zone ID at the end of the link-local address.)

The TIdTCPClient object being used to connect to the device therefore needs to be associated with the correct network interface. I understand that this can be done by setting the BoundIP property but I do not have the IPv6 address of the interface where the device was discovered because this was done using IPv4. Is there a way of using the TIdSocketHandle object that was provided in the OnUDPRead event when the device was discovered and using that to set the appropriate thing in the TIdTCPClient object?

CodePudding user response:

But when the application attempts to establish a TCP connection to one of these link-local IPv6 addresses, the first attempt usually fails because Windows doesn't know which interface to use.

Are you setting the TIdTCPClient.IPVersion property to Id_IPv6? Indy does not currently determine the IP version to connect with based on the IP address specified (ticket), you have to explicitly specify the IP version up front.

Most of the time, it should be good enough to let Windows decide which interface to use when connecting to an IP address. That is what its routing tables are meant for.

This same behaviour can be observed when just ping-ing the address from the command line. The problem is solved by writing % followed by the appropriate zone ID at the end of the link-local address.

Indy does not currently support zone/scope IDs for IPv6 addresses (ticket).

Is there a way of using the TIdSocketHandle object that was provided in the OnUDPRead event when the device was discovered

Not likely, because you said the discovery was made over IPv4, which means the TIdSocketHandle's UDP socket was bound to an IPv4 interface, not an IPv6 interface. The only possibility would be if the interface in question has both IPv4 and IPv6 addresses assigned to it, in which case you could use Win32 APIs to match up the TIdSocketHandle.IP to a specific interface, and then enumerate the IPv6 addresses on that same interface.

Otherwise, you can use Indy's TIdStack.GetLocalAddressList() method to get all of the local IPv6 interface IPs, and then bind the TIdTCPClient to each one in a loop until a connection to the target device is successful.

  • Related