0

I'm implementing a UDP server using Netty 3.6.5.Final and JDK7 (Nio.2) on Suse Linux and I've run up against the wall. The problem specifically deals with the differences in binding to the wildcard address (0.0.0.0) on windows and MacOS vs. Linux.

I have a multicast group for sending data and a group for receiving data, both bound to the same port. When I try to publish on the outbound group, I get the packet back on the inbound group, which is no bueno. On windows/mac this is not an issue. One Linux it get the "promiscuous" behavior.

On Linux, binding on the wildcard address causes ALL UDP traffic on the bound port to be delivered regardless of group membership (hence the example from above). For MacOS/Windows, you only get traffic from groups you've subscribed to via joinGroup(). The latter is the desired behavior.

The quasi-solution for Linux is to bind to the multicast group address you are interested in receiving traffic from. This works great for the first group you join (which happens to be the group address you've bound to). However, if you want to join additional groups via joinGroup() using the same subscriber, the additional group traffic is not delivered.

I've also tried binding to the IP address of the default NIC and NO traffic is delivered at all.

So I've tried:

if(SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_WINDOWS) {
    socketAddress = new InetSocketAddress(port);
} else {
    socketAddress = new InetSocketAddress(getUnixBindAddress(), port);
}
groupChannel = (DatagramChannel)bootstrap.bind(socketAddress);      

Where getUnixBindAddress() grabs the default NIC IP address. No traffic is delivered in this case.

I've also tried:

if(SystemUtils.IS_OS_MAC_OSX || SystemUtils.IS_OS_WINDOWS) {
    socketAddress = new InetSocketAddress(port);
} else {
    socketAddress = new InetSocketAddress(multicastAddress, port);
}
groupChannel = (DatagramChannel)bootstrap.bind(socketAddress);      

Where multicastAddress is the address of the first group to be joined. Only traffic from the first joined group is delivered.

My joinGroup() call looks like this:

ChannelFuture future = groupChannel.joinGroup(new InetSocketAddress(group.getGroupAddress(), group.getPort()), networkInterface);
future.syncUninterruptibly();

And the bootstrap code like this:

bootstrap = new ConnectionlessBootstrap(new NioDatagramChannelFactory(
    Executors.newSingleThreadExecutor(), InternetProtocolFamily.IPv4));
bootstrap.setOption("broadcast", false);
bootstrap.setOption("loopbackModeDisabled", true);
bootstrap.setOption("reuseAddress", true);
bootstrap.setPipelineFactory(this);

If anyone has any insight on how to make multiple group subscriptions work on for Netty on Linux, I'd be most grateful.

-Brian

1 Answers1

0

It turns out that on Linux the default behavior is to multiplex the traffic such that when bound to 0.0.0.0 ALL multicast traffic is received for all groups on that port.

Due to the default behavior, an application MUST filter traffic out from undesired groups. This is necessary for security reasons by ensuring that only expected traffic is received by the application.

There is also a socket option called IP_MULTICAST_ALL that apparently can be set (it's not standard in Java so I'm not sure how), which will force the stack to implement the desired, non-standard, behavior.