Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8210493

Bind to node- or linklocal ipv6 multicast address fails

XMLWordPrintable

    • b20
    • x86
    • linux
    • Verified

      ADDITIONAL SYSTEM INFORMATION :
      $ java -version
      openjdk version "1.8.0_181"
      OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-2~0-b13)
      OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)


      A DESCRIPTION OF THE PROBLEM :
      If a java program tries to bind a datagram/UDP socket to a link- or node-local multicast
      address and also sets the needed interface index, the bind operation on the socket
      fails with "java.net.SocketException: Invalid argument".

      The need to bind the socket to the IPv6 multicast address is to avoid receiving traffic
      from all multicast groups, that are joined on the system. Since a join joins the system
      (not the socket) to the group, all sockets bound to a port, which receive multicast
      traffic will receive all of that traffic, no matter the destination address. The bind
      prevents that. IP_MULTICAST_ALL sadly only works for IPv4, and IPV6_MULTICAST_ALL
      has a bug in the Linux kernel, see https://marc.info/?l=linux-netdev&m=153656806202701&w=2

      This is because the JDK networking native code only transfers the interface index to
      the scope_id field in the struct sockaddr_in6, if the address to bind to is a link-local
      address (IN6_IS_ADDR_LINKLOCAL()).

      A bind to a multicast address of link- or node-local scope needs the scope_id field as well.
      (There might be an additional problem here, when binding to a higher scoped multicast address and trying to use
      the non-default-route interface)

      The patch below fixes/adds this in the JDK networking native code. It is applicable
      with few changes to all java versions I have looked at.

      This is a copy/forward of the Debian bug #907541 (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=907541). I am reporting this here in the hope of getting a fix into upstream quicker.

      This bugs affects ALL currently available Java versions (at least 7,8,10 and 11)

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the test-code. It throws an exception, which it should not.
      The hard-coded network Interface name in the test code might have to be adapted in order for the test to work.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The bind should succeed.
      ACTUAL -
      Exception is thrown

      ---------- BEGIN SOURCE ----------
      class mcast_test {

          private static final byte[] ADDR = new byte[]{
              (byte) 0xff, (byte) 0x12, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
              (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x47, (byte) 0x49,
              (byte) 0x47, (byte) 0x50
          };

          public static void main(String[] args) throws Exception {
              Inet6Address addr = Inet6Address.getByAddress("", ADDR, NetworkInterface.getByName("enp6s0"));
              System.out.println(addr);
              DatagramSocket s = new DatagramSocket(new InetSocketAddress( addr, 29550));
          }
      };

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      This is a patch against java 8, as it is distributed by debian in its unstable distribution. After applying this patch, the VM behaves as expected.

      diff -Naur jdk/src/solaris/native/java/net/net_util_md.c jdk.new/src/solaris/native/java/net/net_util_md.c
      --- a/jdk/src/solaris/native/java/net/net_util_md.c 2018-05-17 22:24:20.000000000 +0200
      +++ b/jdk/src/solaris/native/java/net/net_util_md.c 2018-08-28 10:54:00.022607297 +0200
      @@ -838,7 +838,9 @@
                * cases the used value is cached for further use.
                */
       #ifdef __linux__
      - if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))) {
      + if (IN6_IS_ADDR_LINKLOCAL(&(him6->sin6_addr))
      + || IN6_IS_ADDR_MC_NODELOCAL(&(him6->sin6_addr))
      + || IN6_IS_ADDR_MC_LINKLOCAL(&(him6->sin6_addr))) {
                   int cached_scope_id = 0, scope_id = 0;
       
                   if (ia6_cachedscopeidID) {



      FREQUENCY : always


            prappo Pavel Rappo (Inactive)
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

              Created:
              Updated:
              Resolved: