Jump to content
FredM

TIdIpMcastClient - Group join on second interface issue

Recommended Posts

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).

interfaces.thumb.jpeg.31846a14dd8b36fea345419f630175ed.jpeg

 

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).

mcast_group_joins_16.thumb.jpeg.f9f2586007b230c869534ffea258ce03.jpeg

mcast_group_joins_17.thumb.jpeg.7b3d50f4cc27160485994204e2af3891.jpeg


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:

delphi_code.thumb.jpeg.c26790ed3c9c6243645c6275fd2e1dd0.jpeg

 

Using:
Delphi 10.3, update 2
Indy 10


Thank you for your help!

 

Fred

Share this post


Link to post

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 by Remy Lebeau

Share this post


Link to post

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
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
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×