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

java application cannot bind to IPv6 socket on dual stack machines, if IPv4 socket is already bound

XMLWordPrintable

    • sparc
    • solaris_9


      Java application cannot bind to IPv6 socket on dual stack machines, if IPv4
      socket is already bound and setReuseAddress is "false".

      The problem is strictly reproducible.

      1. Precondition
      ---------------
       Please make sure that you are on a dual stack machine and inet6 interface
       is up:
      % ifconfig -a
      lo0: flags=1000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4> mtu 8232 index 1
              inet 127.0.0.1 netmask ff000000
      eri0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 index 2
              inet 129.157.133.192 netmask ffffff00 broadcast 129.157.133.255
      eri0: flags=2000841<UP,RUNNING,MULTICAST,IPv6> mtu 1500 index 2
              inet6 fe80::203:baff:fe5b:7e89/10

       If inet6 interface is not up, use:
      # ifconfig eri0 inet6 plumb up


      2. Testcase
      -----------
       The testcase consists of a C program "v4serv.c" creating and binding to
       an IPv4 socket, and a Java program "NoReuse.java" creating and binding to
       an IPv6 socket (per default).

      % more v4serv.c
      #include <stdio.h>
      #include <sys/types.h>
      #include <netinet/in.h>
      #include <sys/socket.h>
      #include <netdb.h>

      main(int argc, char *argv[]) {

              struct sockaddr_in addr;
              int new_sock, sock;
              int yes=0;
              char buf[BUFSIZ];

              bzero(&addr, sizeof(addr));
              addr.sin_family = AF_INET;
              addr.sin_addr.s_addr = htonl(INADDR_ANY);
              addr.sin_port = htons(3300);

              if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                      perror("socket");
                      return -1;
              }

              setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(int));
              if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
                      perror("bind");
                      return -1;
              }

              listen(sock, 8);

              for(;;){
                      new_sock = accept(sock, NULL, NULL);
                      read(new_sock, buf, sizeof (buf));
                      printf("%s", buf);
                      close(new_sock);
              }

      }
      % more NoReuse.java
      import java.net.*;
      import java.io.*;

      class NoReuse{

          public static String messages[]
            = {"test1", "test2", "test3" };

              public static void main(String args[]){

                      try{

                              ServerSocket ss = new ServerSocket();
                              ss.setReuseAddress(false);
                              ss.bind( new InetSocketAddress(3300) );
                              Socket s = ss.accept();

                  BufferedWriter writer
                    = new BufferedWriter(
                        new OutputStreamWriter( s.getOutputStream() ) );
                  for( int i=0; i<messages.length; i++ ) {
                       writer.write( messages[i], 0, messages[i].length() );
                       writer.newLine();
                  }

                              writer.close();
                              s.close();

                      }catch(UnknownHostException e){
                              System.out.println(e.toString());
                      }catch(SocketException e){
                              System.out.println(e.toString());
                      }catch(IOException e){
                              System.out.println(e.toString());
                      }
              }
      }
      %


      3. Make
      -------
      % /opt/SUNWspro/bin/cc -V v4serv.c -o v4serv -lsocket -lnsl
      cc: Sun C 5.5 Patch 112760-11 2004/06/08
      acomp: Sun C 5.5 Patch 112760-11 2004/06/08
      "v4serv.c", line 7: warning: old-style declaration or incorrect type for: main
      "v4serv.c", line 14: warning: implicit function declaration: bzero
      "v4serv.c", line 34: warning: implicit function declaration: read
      "v4serv.c", line 36: warning: implicit function declaration: close
      ld: Software Generation Utilities - Solaris Link Editors: 5.9-1.343
      % /j2sdk1.4.2_07/bin/javac NoReuse.java
      %


      4. Run w/ setReuseAddress(false)
      --------------------------------
      4.1 First "v4serv" then "NoReuse"
      ---------------------------------
      % netstat -a | grep 3300
      % ./v4serv &
      [1] 16398
      % netstat -a | grep 3300
            *.3300 *.* 0 0 49152 0 LISTEN
      % /j2sdk1.4.2_07/bin/java NoReuse
      java.net.BindException: Address already in use
      %
       Does not work.

      4.2 First "NoReuse" then "v4serv"
      ---------------------------------
      % netstat -a | grep 3300
      % /j2sdk1.4.2_07/bin/java NoReuse &
      [1] 16410
      % netstat -a | grep 3300
            *.3300 *.* 0 0 49152 0 LISTEN
            *.3300 *.* 0 0 49152 0 LISTEN
      % ./v4serv
      % bind: Address already in use
      %
       Does not work.


      5. Run w/ setReuseAddress(true)
      -------------------------------
       change line 14 in NoReuse.java:
          14 ss.setReuseAddress(true);
      5.1 First "v4serv" then "NoReuse"
      ---------------------------------
      % netstat -a | grep 3300
      % ./v4serv &
      [1] 16438
      % netstat -a | grep 3300
            *.3300 *.* 0 0 49152 0 LISTEN
      % /net/redback/data/j2sdk1.4.2_07/bin/java NoReuse &
      [2] 16441
      % netstat -a | grep 3300
            *.3300 *.* 0 0 49152 0 LISTEN
            *.3300 *.* 0 0 49152 0 LISTEN
            *.3300 *.* 0 0 49152 0 LISTEN
      %
       Everything fine here.

      5.2 First "NoReuse" then "v4serv"
      ---------------------------------
      % netstat -a | grep 3300
      % /j2sdk1.4.2_07/bin/java NoReuse &
      [1] 16450
      % netstat -a | grep 3300
            *.3300 *.* 0 0 49152 0 LISTEN
            *.3300 *.* 0 0 49152 0 LISTEN
      % ./v4serv &
      [2] 16453
      % netstat -a | grep 3300
            *.3300 *.* 0 0 49152 0 LISTEN
            *.3300 *.* 0 0 49152 0 LISTEN
            *.3300 *.* 0 0 49152 0 LISTEN
      %
       Everything fine here.

      ###@###.### 2005-03-22 14:30:27 GMT

            msheppar Mark Sheppard
            thlenz Thomas Lenz (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: