FredM 0 Posted April 26, 2023 Hi all, We are using the component TIdIpMcastClient class for a UDP client that joins a Multicast group (ff02::3 in our case). We have 2 ethernet interfaces (one with index 16, one with index 17). As prescribed, we fill in the IPV6 address of one of the interfaces to make sure the group is joined on the interface of choice. Now, the problem is that whatever we do, we always join the mcast group on the same interface (16), but we also want to join the group on the other interface (17). Below you can see that on interface 16 the group ff02::3 is joined, but we used the IP address of interface 17, where there is no trace of group ff02::3 (see second image below). Important note: when we fully disable interface 16, we áre able to join interface 17. Then after enabling 16 again, it is not possible to join 16 anymore. Here's our delphi code: Using: Delphi 10.3, update 2 Indy 10 Thank you for your help! Fred Share this post Link to post
Remy Lebeau 1436 Posted April 26, 2023 (edited) Makes me wonder if this is related to the following TIdIPMCastServer issue: #203: TIdIPMCastServer is missing a required call to setSockOpt for IPv6 In a nutshell, TIdIPMCastServer does not use the IPV6_MULTICAST_IF socket option to bind its outgoing sockets to any interface indexes. This seems to be required for sending, but is it also required for receiving? Indy does not currently support binding a socket to an interface index, only to an interface IP address. So, if binding to an index is needed in this case, you would have to manually perform SetSockOpt(IPV6_MULTICAST_IF) yourself, or maybe SetSockOpt(SO_BINDTODEVICE) instead. According to this post, it's also possible to bind a socket to an interface index by specifying the index as the Scope ID of the interface's IPv6 address, however Indy does not currently support scope IDs, either. Edited April 26, 2023 by Remy Lebeau Share this post Link to post
FredM 0 Posted April 27, 2023 Hi Remy, Thank you for your answer, much appreciated! Now, the binding to the interface index itself it not so important. As long as we can bind to a specific interface, it is not important how. In fact, we currently use the interface IP address. I mention the interface indexes just to give you a better idea what's going on. So e.g. interface 16 has ip address: fe80::1c64:aff:fec8:7fe6 interface 17 has ip address fe80::2cad:26ff:fe8f:bfca We set fe80::2cad:26ff:fe8f:bfca as the IP address of interface (17) to bind to, but it just binds to interface 16 for some reason. We saw this thread online, it does seem related (even though it's not Indy): https://www.codenewsfast.com/cnf/article/0/permalink.art-ng1921q7387 What do you think? Share this post Link to post
Remy Lebeau 1436 Posted April 27, 2023 9 hours ago, FredM said: We saw this thread online, it does seem related (even though it's not Indy): https://www.codenewsfast.com/cnf/article/0/permalink.art-ng1921q7387 That post's code is a mix of Indy and manual coding. In any case, that post is saying that a multicast receiving socket needs to be bound to 0.0.0.0 or ::0 and then join each desired interface to the multicast group. Searching around, I see many other posts with similar advice. Although TIdIPMCastClient can bind its listening sockets to 0.0.0.0/::0 (just set Binding.IP = ''), it then joins their bound IP to the group, so it would be joining 0.0.0.0/::0 to the group, which is clearly not going to work. I may have to add a new event to TIdIPMCastClient that is called after binding to let users decide which interfaces to join, and then update TIdSocketHandle.AddMulticastMembership() to let a caller specify the interface to join (TIdStack.AddMulticastMembership() already has an ALocalIP parameter for that purpose, which TIdSocketHandle sets it its currently bound IP). According to this, Linux can't receive multicast packets if the listening socket is not bound to 0.0.0.0/::0. On the other hand, I've seen several posts, such as this one, which say a receiving socket should be bound to the multicast group IP instead of a local interface, and then join the desired interfaces to the group. Must be a Linux/Posix thing, because that advice is in direct conflict with Microsoft's documentation for receiving multicast on Windows: Quote For multicast operations, the preferred method is to call the bind function to associate a socket with a local IP address and then join the multicast group. Although this order of operations is not mandatory, it is strongly recommended. So a multicast application would first select an IPv4 or IPv6 address on the local computer, the wildcard IPv4 address (INADDR_ANY), or the wildcard IPv6 address (in6addr_any). The the multicast application would then call the bind function with this address in the in the sa_data member of the name parameter to associate the local IP address with the socket. If a wildcard address was specified, then Windows will select the local IP address to use. After the bind function completes, an application would then join the multicast group of interest. For more information on how to join a multicast group, see the section on Multicast Programming. This socket can then be used to receive multicast packets from the multicast group using the recv, recvfrom, WSARecv, WSARecvEx, WSARecvFrom, or LPFN_WSARECVMSG (WSARecvMsg) functions. So, I'm not sure what to think at this point. It seems that everyone agrees that binding a receiver socket to 0.0.0.0/::0 and then having it join an interface to the group will "work", but I've seen several posts say that doing so may cause the socket to receive more UDP packets than the listener wants. Which I guess makes sense. Whereas many people say to bind the socket to the multicast group IP, but Microsoft says not to do that. <sigh> Share this post Link to post
adxf 0 Posted May 26, 2023 On 4/27/2023 at 12:00 PM, FredM said: Hi Remy, Thank you for your answer, much appreciated! Now, the binding to the interface index itself it not so important. As long as we can bind to a specific interface, it is not important how. In fact, we currently use the interface IP address. I mention the interface indexes just to give you a better idea what's going on. So e.g. interface 16 has ip address: fe80::1c64:aff:fec8:7fe6 interface 17 has ip address fe80::2cad:26ff:fe8f:bfca We set fe80::2cad:26ff:fe8f:bfca as the IP address of interface (17) to bind to, but it just binds to interface 16 for some reason. We saw this thread online, it does seem related (even though it's not Indy): https://www.codenewsfast.com/cnf/article/0/permalink.art-ng1921q7387 What do you think? Hi, FredM I have the same problem. Did you find a solution? Share this post Link to post