changeset 2736:174916d435c9

6965072: Need API to create SDP sockets Reviewed-by: michaelm
author alanb
date Fri, 03 Sep 2010 13:11:54 +0100
parents b200263f1b68
children e17654f00d93
files make/com/Makefile make/com/oracle/Makefile make/com/oracle/net/Makefile make/docs/NON_CORE_PKGS.gmk make/java/net/FILES_c.gmk make/java/net/Makefile make/java/net/mapfile-vers make/java/nio/FILES_java.gmk make/sun/net/FILES_java.gmk src/share/classes/com/oracle/net/Sdp.java src/share/classes/java/net/SdpSocketImpl.java src/share/classes/java/net/ServerSocket.java src/share/classes/sun/net/sdp/SdpSupport.java src/share/classes/sun/nio/ch/Secrets.java src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java src/share/classes/sun/nio/ch/SocketChannelImpl.java src/solaris/classes/sun/net/NetHooks.java src/solaris/classes/sun/net/sdp/SdpProvider.java src/solaris/classes/sun/net/spi/SdpProvider.java src/solaris/classes/sun/nio/ch/InheritedChannel.java src/solaris/native/sun/net/sdp/SdpSupport.c src/solaris/native/sun/net/spi/SdpProvider.c test/com/oracle/net/Sanity.java test/com/oracle/net/sanity.sh test/sun/net/sdp/ProbeIB.java test/sun/net/sdp/sanity.sh
diffstat 26 files changed, 1196 insertions(+), 479 deletions(-) [+]
line wrap: on
line diff
--- a/make/com/Makefile	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/com/Makefile	Fri Sep 03 13:11:54 2010 +0100
@@ -31,7 +31,7 @@
 PRODUCT = com
 include $(BUILDDIR)/common/Defs.gmk
 
-SUBDIRS = sun
+SUBDIRS = sun oracle
 include $(BUILDDIR)/common/Subdirs.gmk
 
 all build clean clobber::
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/com/oracle/Makefile	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,34 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../..
+PRODUCT = oracle
+include $(BUILDDIR)/common/Defs.gmk
+
+SUBDIRS = net
+include $(BUILDDIR)/common/Subdirs.gmk
+
+all build clean clobber::
+	$(SUBDIRS-loop)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/com/oracle/net/Makefile	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+BUILDDIR = ../../..
+PRODUCT = oracle
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Files to compile
+#
+AUTO_FILES_JAVA_DIRS = com/oracle/net
+
+#
+# Rules
+#
+include $(BUILDDIR)/common/Classes.gmk
+
--- a/make/docs/NON_CORE_PKGS.gmk	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/docs/NON_CORE_PKGS.gmk	Fri Sep 03 13:11:54 2010 +0100
@@ -91,6 +91,8 @@
 TRACING_PKGS     = com.sun.tracing         \
                    com.sun.tracing.dtrace
 
+ORACLENET_PKGS   = com.oracle.net
+
 # non-core packages in rt.jar
 NON_CORE_PKGS    = $(DOMAPI_PKGS) \
                    $(MGMT_PKGS) \
@@ -101,5 +103,6 @@
                    $(HTTPSERVER_PKGS) \
                    $(SMARTCARDIO_PKGS) \
                    $(TRACING_PKGS) \
-                   $(SCTPAPI_PKGS)
+                   $(SCTPAPI_PKGS) \
+                   $(ORACLENET_PKGS)
 
--- a/make/java/net/FILES_c.gmk	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/java/net/FILES_c.gmk	Fri Sep 03 13:11:54 2010 +0100
@@ -39,10 +39,6 @@
 	ResolverConfigurationImpl.c \
 	DefaultProxySelector.c
 
-ifeq ($(PLATFORM), solaris)
-    FILES_c += SdpProvider.c
-endif
-
 ifeq ($(PLATFORM), linux)
     FILES_c += linux_close.c
 endif
--- a/make/java/net/Makefile	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/java/net/Makefile	Fri Sep 03 13:11:54 2010 +0100
@@ -44,6 +44,8 @@
     endif
     FILES_c += NTLMAuthSequence.c
     FILES_c += NetworkInterface_winXP.c
+else
+    FILES_c += SdpSupport.c
 endif
 
 FILES_export = \
@@ -84,7 +86,8 @@
 #
 # Find platform specific native code
 #
-vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
+vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm \
+    $(PLATFORM_SRC)/native/sun/net/sdp $(PLATFORM_SRC)/native/sun/net/spi
 
 #
 # Include rules
--- a/make/java/net/mapfile-vers	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/java/net/mapfile-vers	Fri Sep 03 13:11:54 2010 +0100
@@ -88,9 +88,10 @@
 		Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
 		Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
 		Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0;
+		Java_sun_net_sdp_SdpSupport_convert0;
+		Java_sun_net_sdp_SdpSupport_create0;
 		Java_sun_net_spi_DefaultProxySelector_init;
 		Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
-		Java_sun_net_spi_SdpProvider_convert;
 		NET_AllocSockaddr;
 		NET_SockaddrToInetAddress;
                 NET_SockaddrEqualsInetAddress;
--- a/make/java/nio/FILES_java.gmk	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/java/nio/FILES_java.gmk	Fri Sep 03 13:11:54 2010 +0100
@@ -199,6 +199,7 @@
 	sun/nio/ch/PipeImpl.java \
 	sun/nio/ch/PollArrayWrapper.java \
 	sun/nio/ch/Reflect.java \
+	sun/nio/ch/Secrets.java \
 	sun/nio/ch/SelectionKeyImpl.java \
 	sun/nio/ch/SelectorImpl.java \
 	sun/nio/ch/SelectorProviderImpl.java \
--- a/make/sun/net/FILES_java.gmk	Wed Sep 01 17:37:45 2010 -0700
+++ b/make/sun/net/FILES_java.gmk	Fri Sep 03 13:11:54 2010 +0100
@@ -53,6 +53,7 @@
 	sun/net/ftp/FtpProtocolException.java \
 	sun/net/ftp/impl/FtpClient.java \
 	sun/net/ftp/impl/DefaultFtpClientProvider.java \
+	sun/net/sdp/SdpSupport.java \
 	sun/net/spi/DefaultProxySelector.java \
 	sun/net/spi/nameservice/NameServiceDescriptor.java \
 	sun/net/spi/nameservice/NameService.java \
@@ -136,8 +137,6 @@
 
 ifeq ($(PLATFORM), windows)
     FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java 
+else
+    FILES_java += sun/net/sdp/SdpProvider.java
 endif
-
-ifeq ($(PLATFORM), solaris)
-    FILES_java += sun/net/spi/SdpProvider.java
-endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/oracle/net/Sdp.java	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.net;
+
+import java.net.Socket;
+import java.net.ServerSocket;
+import java.net.SocketImpl;
+import java.net.SocketImplFactory;
+import java.net.SocketException;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.InvocationTargetException;
+
+import sun.net.sdp.SdpSupport;
+
+/**
+ * This class consists exclusively of static methods that Sockets or Channels to
+ * sockets that support the InfiniBand Sockets Direct Protocol (SDP).
+ */
+
+public final class Sdp {
+    private Sdp() { }
+
+    /**
+     * The package-privage ServerSocket(SocketImpl) constructor
+     */
+    private static final Constructor<ServerSocket> serverSocketCtor;
+    static {
+        try {
+            serverSocketCtor = (Constructor<ServerSocket>)
+                ServerSocket.class.getDeclaredConstructor(SocketImpl.class);
+            setAccessible(serverSocketCtor);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * The package-private SdpSocketImpl() constructor
+     */
+    private static final Constructor<SocketImpl> socketImplCtor;
+    static {
+        try {
+            Class<?> cl = Class.forName("java.net.SdpSocketImpl", true, null);
+            socketImplCtor = (Constructor<SocketImpl>)cl.getDeclaredConstructor();
+            setAccessible(socketImplCtor);
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError(e);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError(e);
+        }
+    }
+
+    private static void setAccessible(final AccessibleObject o) {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                o.setAccessible(true);
+                return null;
+            }
+        });
+    }
+
+    /**
+     * SDP enabled Socket.
+     */
+    private static class SdpSocket extends Socket {
+        SdpSocket(SocketImpl impl) throws SocketException {
+            super(impl);
+        }
+    }
+
+    /**
+     * Creates a SDP enabled SocketImpl
+     */
+    private static SocketImpl createSocketImpl() {
+        try {
+            return socketImplCtor.newInstance();
+        } catch (InstantiationException x) {
+            throw new AssertionError(x);
+        } catch (IllegalAccessException x) {
+            throw new AssertionError(x);
+        } catch (InvocationTargetException x) {
+            throw new AssertionError(x);
+        }
+    }
+
+    /**
+     * Creates an unconnected and unbound SDP socket. The {@code Socket} is
+     * associated with a {@link java.net.SocketImpl} of the system-default type.
+     *
+     * @return  a new Socket
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static Socket openSocket() throws IOException {
+        SocketImpl impl = createSocketImpl();
+        return new SdpSocket(impl);
+    }
+
+    /**
+     * Creates an unbound SDP server socket. The {@code ServerSocket} is
+     * associated with a {@link java.net.SocketImpl} of the system-default type.
+     *
+     * @return  a new ServerSocket
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static ServerSocket openServerSocket() throws IOException {
+        // create ServerSocket via package-private constructor
+        SocketImpl impl = createSocketImpl();
+        try {
+            return serverSocketCtor.newInstance(impl);
+        } catch (IllegalAccessException x) {
+            throw new AssertionError(x);
+        } catch (InstantiationException x) {
+            throw new AssertionError(x);
+        } catch (InvocationTargetException x) {
+            Throwable cause = x.getCause();
+            if (cause instanceof IOException)
+                throw (IOException)cause;
+            if (cause instanceof RuntimeException)
+                throw (RuntimeException)cause;
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * Opens a socket channel to a SDP socket.
+     *
+     * <p> The channel will be associated with the system-wide default
+     * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
+     *
+     * @return  a new SocketChannel
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported or not supported by the default selector
+     *          provider
+     * @throws  IOException
+     *          If an I/O error occurs.
+     */
+    public static SocketChannel openSocketChannel() throws IOException {
+        FileDescriptor fd = SdpSupport.createSocket();
+        return sun.nio.ch.Secrets.newSocketChannel(fd);
+    }
+
+    /**
+     * Opens a socket channel to a SDP socket.
+     *
+     * <p> The channel will be associated with the system-wide default
+     * {@link java.nio.channels.spi.SelectorProvider SelectorProvider}.
+     *
+     * @return  a new ServerSocketChannel
+     *
+     * @throws  UnsupportedOperationException
+     *          If SDP is not supported or not supported by the default selector
+     *          provider
+     * @throws  IOException
+     *          If an I/O error occurs
+     */
+    public static ServerSocketChannel openServerSocketChannel()
+        throws IOException
+    {
+        FileDescriptor fd = SdpSupport.createSocket();
+        return sun.nio.ch.Secrets.newServerSocketChannel(fd);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/net/SdpSocketImpl.java	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net;
+
+import java.io.IOException;
+import java.io.FileDescriptor;
+
+import sun.net.sdp.SdpSupport;
+
+/**
+ * SocketImpl that supports the SDP protocol
+ */
+class SdpSocketImpl extends PlainSocketImpl {
+    SdpSocketImpl() { }
+
+    @Override
+    protected void create(boolean stream) throws IOException {
+        if (!stream)
+            throw new UnsupportedOperationException("Must be a stream socket");
+        fd = SdpSupport.createSocket();
+        if (socket != null)
+            socket.setCreated();
+        if (serverSocket != null)
+            serverSocket.setCreated();
+    }
+}
--- a/src/share/classes/java/net/ServerSocket.java	Wed Sep 01 17:37:45 2010 -0700
+++ b/src/share/classes/java/net/ServerSocket.java	Fri Sep 03 13:11:54 2010 +0100
@@ -69,6 +69,15 @@
     private boolean oldImpl = false;
 
     /**
+     * Package-private constructor to create a ServerSocket associated with
+     * the given SocketImpl.
+     */
+    ServerSocket(SocketImpl impl) {
+        this.impl = impl;
+        impl.setServerSocket(this);
+    }
+
+    /**
      * Creates an unbound server socket.
      *
      * @exception IOException IO error when opening the socket.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/net/sdp/SdpSupport.java	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.sdp;
+
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+
+import sun.misc.SharedSecrets;
+import sun.misc.JavaIOFileDescriptorAccess;
+
+
+/**
+ * This class defines methods for creating SDP sockets or "converting" existing
+ * file descriptors, referencing (unbound) TCP sockets, to SDP.
+ */
+
+public final class SdpSupport {
+    private static final String os = AccessController
+        .doPrivileged(new sun.security.action.GetPropertyAction("os.name"));
+    private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux")));
+    private static final JavaIOFileDescriptorAccess fdAccess =
+        SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private SdpSupport() { }
+
+    /**
+     * Creates a SDP socket, returning file descriptor referencing the socket.
+     */
+    public static FileDescriptor createSocket() throws IOException {
+        if (!isSupported)
+            throw new UnsupportedOperationException("SDP not supported on this platform");
+        int fdVal = create0();
+        FileDescriptor fd = new FileDescriptor();
+        fdAccess.set(fd, fdVal);
+        return fd;
+    }
+
+    /**
+     * Converts an existing file descriptor, that references an unbound TCP socket,
+     * to SDP.
+     */
+    public static void convertSocket(FileDescriptor fd) throws IOException {
+        if (!isSupported)
+            throw new UnsupportedOperationException("SDP not supported on this platform");
+        int fdVal = fdAccess.get(fd);
+        convert0(fdVal);
+    }
+
+    private static native int create0() throws IOException;
+
+    private static native void convert0(int fd) throws IOException;
+
+    static {
+        AccessController.doPrivileged(
+            new sun.security.action.LoadLibraryAction("net"));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/nio/ch/Secrets.java	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.nio.ch;
+
+import java.nio.channels.SocketChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * Provides access to implementation private constructors and methods.
+ */
+
+public final class Secrets {
+    private Secrets() { }
+
+    private static SelectorProvider provider() {
+        SelectorProvider p = SelectorProvider.provider();
+        if (!(p instanceof SelectorProviderImpl))
+            throw new UnsupportedOperationException();
+        return p;
+    }
+
+    public static SocketChannel newSocketChannel(FileDescriptor fd) {
+        try {
+            return new SocketChannelImpl(provider(), fd, false);
+        } catch (IOException ioe) {
+            throw new AssertionError(ioe);
+        }
+    }
+
+    public static ServerSocketChannel newServerSocketChannel(FileDescriptor fd) {
+        try {
+            return new ServerSocketChannelImpl(provider(), fd, false);
+        } catch (IOException ioe) {
+            throw new AssertionError(ioe);
+        }
+    }
+}
--- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Wed Sep 01 17:37:45 2010 -0700
+++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri Sep 03 13:11:54 2010 +0100
@@ -80,21 +80,24 @@
     // -- End of fields protected by stateLock
 
 
-    public ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
+    ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
         super(sp);
         this.fd =  Net.serverSocket(true);
         this.fdVal = IOUtil.fdVal(fd);
         this.state = ST_INUSE;
     }
 
-    public ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd)
+    ServerSocketChannelImpl(SelectorProvider sp,
+                            FileDescriptor fd,
+                            boolean bound)
         throws IOException
     {
         super(sp);
         this.fd =  fd;
         this.fdVal = IOUtil.fdVal(fd);
         this.state = ST_INUSE;
-        localAddress = Net.localAddress(fd);
+        if (bound)
+            localAddress = Net.localAddress(fd);
     }
 
     public ServerSocket socket() {
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Wed Sep 01 17:37:45 2010 -0700
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Fri Sep 03 13:11:54 2010 +0100
@@ -103,6 +103,19 @@
         this.state = ST_UNCONNECTED;
     }
 
+    SocketChannelImpl(SelectorProvider sp,
+                      FileDescriptor fd,
+                      boolean bound)
+        throws IOException
+    {
+        super(sp);
+        this.fd = fd;
+        this.fdVal = IOUtil.fdVal(fd);
+        this.state = ST_UNCONNECTED;
+        if (bound)
+            this.localAddress = Net.localAddress(fd);
+    }
+
     // Constructor for sockets obtained from server sockets
     //
     SocketChannelImpl(SelectorProvider sp,
--- a/src/solaris/classes/sun/net/NetHooks.java	Wed Sep 01 17:37:45 2010 -0700
+++ b/src/solaris/classes/sun/net/NetHooks.java	Fri Sep 03 13:11:54 2010 +0100
@@ -73,28 +73,7 @@
      * be changed to use the ServiceLoader facility to allow the deployment of
      * other providers.
      */
-    private static Provider loadProvider(final String cn) {
-        return AccessController
-            .doPrivileged(new PrivilegedAction<Provider>() {
-                @Override public Provider run() {
-                    Class<Provider> c;
-                    try {
-                        c = (Class<Provider>)Class.forName(cn, true, null);
-                    } catch (ClassNotFoundException x) {
-                        return null;
-                    }
-                    try {
-                        return c.newInstance();
-                    } catch (IllegalAccessException x) {
-                        throw new AssertionError(x);
-                    } catch (InstantiationException x) {
-                        throw new AssertionError(x);
-                    }
-            }});
-    }
-    private static final Provider provider = AccessController
-        .doPrivileged(new GetPropertyAction("os.name")).equals("SunOS") ?
-            loadProvider("sun.net.spi.SdpProvider") : null;
+    private static final Provider provider = new sun.net.sdp.SdpProvider();
 
     /**
      * Invoke prior to binding a TCP socket.
@@ -104,8 +83,7 @@
                                      int port)
         throws IOException
     {
-        if (provider != null)
-            provider.implBeforeTcpBind(fdObj, address, port);
+        provider.implBeforeTcpBind(fdObj, address, port);
     }
 
     /**
@@ -116,7 +94,6 @@
                                         int port)
         throws IOException
     {
-        if (provider != null)
-            provider.implBeforeTcpConnect(fdObj, address, port);
+        provider.implBeforeTcpConnect(fdObj, address, port);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/classes/sun/net/sdp/SdpProvider.java	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.sdp;
+
+import sun.net.NetHooks;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.UnknownHostException;
+import java.util.*;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.security.AccessController;
+
+import sun.net.sdp.SdpSupport;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * A NetHooks provider that converts sockets from the TCP to SDP protocol prior
+ * to binding or connecting.
+ */
+
+public class SdpProvider extends NetHooks.Provider {
+    // maximum port
+    private static final int MAX_PORT = 65535;
+
+    // indicates if SDP is enabled and the rules for when the protocol is used
+    private final boolean enabled;
+    private final List<Rule> rules;
+
+    // logging for debug purposes
+    private PrintStream log;
+
+    public SdpProvider() {
+        // if this property is not defined then there is nothing to do.
+        String file = AccessController.doPrivileged(
+            new GetPropertyAction("com.sun.sdp.conf"));
+        if (file == null) {
+            this.enabled = false;
+            this.rules = null;
+            return;
+        }
+
+        // load configuration file
+        List<Rule> list = null;
+        if (file != null) {
+            try {
+                list = loadRulesFromFile(file);
+            } catch (IOException e) {
+                fail("Error reading %s: %s", file, e.getMessage());
+            }
+        }
+
+        // check if debugging is enabled
+        PrintStream out = null;
+        String logfile = AccessController.doPrivileged(
+            new GetPropertyAction("com.sun.sdp.debug"));
+        if (logfile != null) {
+            out = System.out;
+            if (logfile.length() > 0) {
+                try {
+                    out = new PrintStream(logfile);
+                } catch (IOException ignore) { }
+            }
+        }
+
+        this.enabled = !list.isEmpty();
+        this.rules = list;
+        this.log = out;
+    }
+
+    // supported actions
+    private static enum Action {
+        BIND,
+        CONNECT;
+    }
+
+    // a rule for matching a bind or connect request
+    private static interface Rule {
+        boolean match(Action action, InetAddress address, int port);
+    }
+
+    // rule to match port[-end]
+    private static class PortRangeRule implements Rule {
+        private final Action action;
+        private final int portStart;
+        private final int portEnd;
+        PortRangeRule(Action action, int portStart, int portEnd) {
+            this.action = action;
+            this.portStart = portStart;
+            this.portEnd = portEnd;
+        }
+        Action action() {
+            return action;
+        }
+        @Override
+        public boolean match(Action action, InetAddress address, int port) {
+            return (action == this.action &&
+                    port >= this.portStart &&
+                    port <= this.portEnd);
+        }
+    }
+
+    // rule to match address[/prefix] port[-end]
+    private static class AddressPortRangeRule extends PortRangeRule {
+        private final byte[] addressAsBytes;
+        private final int prefixByteCount;
+        private final byte mask;
+        AddressPortRangeRule(Action action, InetAddress address,
+                             int prefix, int port, int end)
+        {
+            super(action, port, end);
+            this.addressAsBytes = address.getAddress();
+            this.prefixByteCount = prefix >> 3;
+            this.mask = (byte)(0xff << (8 - (prefix % 8)));
+        }
+        @Override
+        public boolean match(Action action, InetAddress address, int port) {
+            if (action != action())
+                return false;
+            byte[] candidate = address.getAddress();
+            // same address type?
+            if (candidate.length != addressAsBytes.length)
+                return false;
+            // check bytes
+            for (int i=0; i<prefixByteCount; i++) {
+                if (candidate[i] != addressAsBytes[i])
+                    return false;
+            }
+            // check remaining bits
+            if ((prefixByteCount < addressAsBytes.length) &&
+                ((candidate[prefixByteCount] & mask) !=
+                 (addressAsBytes[prefixByteCount] & mask)))
+                    return false;
+            return super.match(action, address, port);
+        }
+    }
+
+    // parses port:[-end]
+    private static int[] parsePortRange(String s) {
+        int pos = s.indexOf('-');
+        try {
+            int[] result = new int[2];
+            if (pos < 0) {
+                boolean all = s.equals("*");
+                result[0] = all ? 0 : Integer.parseInt(s);
+                result[1] = all ? MAX_PORT : result[0];
+            } else {
+                String low = s.substring(0, pos);
+                if (low.length() == 0) low = "*";
+                String high = s.substring(pos+1);
+                if (high.length() == 0) high = "*";
+                result[0] = low.equals("*") ? 0 : Integer.parseInt(low);
+                result[1] = high.equals("*") ? MAX_PORT : Integer.parseInt(high);
+            }
+            return result;
+        } catch (NumberFormatException e) {
+            return new int[0];
+        }
+    }
+
+    private static void fail(String msg, Object... args) {
+        Formatter f = new Formatter();
+        f.format(msg, args);
+        throw new RuntimeException(f.out().toString());
+    }
+
+    // loads rules from the given file
+    // Each non-blank/non-comment line must have the format:
+    // ("bind" | "connect") 1*LWSP-char (hostname | ipaddress["/" prefix])
+    //     1*LWSP-char ("*" | port) [ "-" ("*" | port) ]
+    private static List<Rule> loadRulesFromFile(String file)
+        throws IOException
+    {
+        Scanner scanner = new Scanner(new File(file));
+        try {
+            List<Rule> result = new ArrayList<Rule>();
+            while (scanner.hasNextLine()) {
+                String line = scanner.nextLine().trim();
+
+                // skip blank lines and comments
+                if (line.length() == 0 || line.charAt(0) == '#')
+                    continue;
+
+                // must have 3 fields
+                String[] s = line.split("\\s+");
+                if (s.length != 3) {
+                    fail("Malformed line '%s'", line);
+                    continue;
+                }
+
+                // first field is the action ("bind" or "connect")
+                Action action = null;
+                for (Action a: Action.values()) {
+                    if (s[0].equalsIgnoreCase(a.name())) {
+                        action = a;
+                        break;
+                    }
+                }
+                if (action == null) {
+                    fail("Action '%s' not recognized", s[0]);
+                    continue;
+                }
+
+                // * port[-end]
+                int[] ports = parsePortRange(s[2]);
+                if (ports.length == 0) {
+                    fail("Malformed port range '%s'", s[2]);
+                    continue;
+                }
+
+                // match all addresses
+                if (s[1].equals("*")) {
+                    result.add(new PortRangeRule(action, ports[0], ports[1]));
+                    continue;
+                }
+
+                // hostname | ipaddress[/prefix]
+                int pos = s[1].indexOf('/');
+                try {
+                    if (pos < 0) {
+                        // hostname or ipaddress (no prefix)
+                        InetAddress[] addresses = InetAddress.getAllByName(s[1]);
+                        for (InetAddress address: addresses) {
+                            int prefix =
+                                (address instanceof Inet4Address) ? 32 : 128;
+                            result.add(new AddressPortRangeRule(action, address,
+                                prefix, ports[0], ports[1]));
+                        }
+                    } else {
+                        // ipaddress/prefix
+                        InetAddress address = InetAddress
+                            .getByName(s[1].substring(0, pos));
+                        int prefix = -1;
+                        try {
+                            prefix = Integer.parseInt(s[1].substring(pos+1));
+                            if (address instanceof Inet4Address) {
+                                // must be 1-31
+                                if (prefix < 0 || prefix > 32) prefix = -1;
+                            } else {
+                                // must be 1-128
+                                if (prefix < 0 || prefix > 128) prefix = -1;
+                            }
+                        } catch (NumberFormatException e) {
+                        }
+
+                        if (prefix > 0) {
+                            result.add(new AddressPortRangeRule(action,
+                                        address, prefix, ports[0], ports[1]));
+                        } else {
+                            fail("Malformed prefix '%s'", s[1]);
+                            continue;
+                        }
+                    }
+                } catch (UnknownHostException uhe) {
+                    fail("Unknown host or malformed IP address '%s'", s[1]);
+                    continue;
+                }
+            }
+            return result;
+        } finally {
+            scanner.close();
+        }
+    }
+
+    // converts unbound TCP socket to a SDP socket if it matches the rules
+    private void convertTcpToSdpIfMatch(FileDescriptor fdObj,
+                                               Action action,
+                                               InetAddress address,
+                                               int port)
+        throws IOException
+    {
+        boolean matched = false;
+        for (Rule rule: rules) {
+            if (rule.match(action, address, port)) {
+                SdpSupport.convertSocket(fdObj);
+                matched = true;
+                break;
+            }
+        }
+        if (log != null) {
+            String addr = (address instanceof Inet4Address) ?
+                address.getHostAddress() : "[" + address.getHostAddress() + "]";
+            if (matched) {
+                log.format("%s to %s:%d (socket converted to SDP protocol)\n", action, addr, port);
+            } else {
+                log.format("%s to %s:%d (no match)\n", action, addr, port);
+            }
+        }
+    }
+
+    @Override
+    public void implBeforeTcpBind(FileDescriptor fdObj,
+                              InetAddress address,
+                              int port)
+        throws IOException
+    {
+        if (enabled)
+            convertTcpToSdpIfMatch(fdObj, Action.BIND, address, port);
+    }
+
+    @Override
+    public void implBeforeTcpConnect(FileDescriptor fdObj,
+                                InetAddress address,
+                                int port)
+        throws IOException
+    {
+        if (enabled)
+            convertTcpToSdpIfMatch(fdObj, Action.CONNECT, address, port);
+    }
+}
--- a/src/solaris/classes/sun/net/spi/SdpProvider.java	Wed Sep 01 17:37:45 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.spi;
-
-import sun.net.NetHooks;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.UnknownHostException;
-import java.util.*;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.PrintStream;
-
-import sun.misc.SharedSecrets;
-import sun.misc.JavaIOFileDescriptorAccess;
-
-/**
- * A NetHooks provider that converts sockets from the TCP to SDP protocol prior
- * to binding or connecting.
- */
-
-public class SdpProvider extends NetHooks.Provider {
-    private static final JavaIOFileDescriptorAccess fdAccess =
-        SharedSecrets.getJavaIOFileDescriptorAccess();
-
-    // maximum port
-    private static final int MAX_PORT = 65535;
-
-    // indicates if SDP is enabled and the rules for when the protocol is used
-    private final boolean enabled;
-    private final List<Rule> rules;
-
-    // logging for debug purposes
-    private PrintStream log;
-
-    public SdpProvider() {
-        // if this property is not defined then there is nothing to do.
-        String file = System.getProperty("com.sun.sdp.conf");
-        if (file == null) {
-            this.enabled = false;
-            this.rules = null;
-            return;
-        }
-
-        // load configuration file
-        List<Rule> list = null;
-        if (file != null) {
-            try {
-                list = loadRulesFromFile(file);
-            } catch (IOException e) {
-                fail("Error reading %s: %s", file, e.getMessage());
-            }
-        }
-
-        // check if debugging is enabled
-        PrintStream out = null;
-        String logfile = System.getProperty("com.sun.sdp.debug");
-        if (logfile != null) {
-            out = System.out;
-            if (logfile.length() > 0) {
-                try {
-                    out = new PrintStream(logfile);
-                } catch (IOException ignore) { }
-            }
-        }
-
-        this.enabled = !list.isEmpty();
-        this.rules = list;
-        this.log = out;
-    }
-
-    // supported actions
-    private static enum Action {
-        BIND,
-        CONNECT;
-    }
-
-    // a rule for matching a bind or connect request
-    private static interface Rule {
-        boolean match(Action action, InetAddress address, int port);
-    }
-
-    // rule to match port[-end]
-    private static class PortRangeRule implements Rule {
-        private final Action action;
-        private final int portStart;
-        private final int portEnd;
-        PortRangeRule(Action action, int portStart, int portEnd) {
-            this.action = action;
-            this.portStart = portStart;
-            this.portEnd = portEnd;
-        }
-        Action action() {
-            return action;
-        }
-        @Override
-        public boolean match(Action action, InetAddress address, int port) {
-            return (action == this.action &&
-                    port >= this.portStart &&
-                    port <= this.portEnd);
-        }
-    }
-
-    // rule to match address[/prefix] port[-end]
-    private static class AddressPortRangeRule extends PortRangeRule {
-        private final byte[] addressAsBytes;
-        private final int prefixByteCount;
-        private final byte mask;
-        AddressPortRangeRule(Action action, InetAddress address,
-                             int prefix, int port, int end)
-        {
-            super(action, port, end);
-            this.addressAsBytes = address.getAddress();
-            this.prefixByteCount = prefix >> 3;
-            this.mask = (byte)(0xff << (8 - (prefix % 8)));
-        }
-        @Override
-        public boolean match(Action action, InetAddress address, int port) {
-            if (action != action())
-                return false;
-            byte[] candidate = address.getAddress();
-            // same address type?
-            if (candidate.length != addressAsBytes.length)
-                return false;
-            // check bytes
-            for (int i=0; i<prefixByteCount; i++) {
-                if (candidate[i] != addressAsBytes[i])
-                    return false;
-            }
-            // check remaining bits
-            if ((prefixByteCount < addressAsBytes.length) &&
-                ((candidate[prefixByteCount] & mask) !=
-                 (addressAsBytes[prefixByteCount] & mask)))
-                    return false;
-            return super.match(action, address, port);
-        }
-    }
-
-    // parses port:[-end]
-    private static int[] parsePortRange(String s) {
-        int pos = s.indexOf('-');
-        try {
-            int[] result = new int[2];
-            if (pos < 0) {
-                boolean all = s.equals("*");
-                result[0] = all ? 0 : Integer.parseInt(s);
-                result[1] = all ? MAX_PORT : result[0];
-            } else {
-                String low = s.substring(0, pos);
-                if (low.length() == 0) low = "*";
-                String high = s.substring(pos+1);
-                if (high.length() == 0) high = "*";
-                result[0] = low.equals("*") ? 0 : Integer.parseInt(low);
-                result[1] = high.equals("*") ? MAX_PORT : Integer.parseInt(high);
-            }
-            return result;
-        } catch (NumberFormatException e) {
-            return new int[0];
-        }
-    }
-
-    private static void fail(String msg, Object... args) {
-        Formatter f = new Formatter();
-        f.format(msg, args);
-        throw new RuntimeException(f.out().toString());
-    }
-
-    // loads rules from the given file
-    // Each non-blank/non-comment line must have the format:
-    // ("bind" | "connect") 1*LWSP-char (hostname | ipaddress["/" prefix])
-    //     1*LWSP-char ("*" | port) [ "-" ("*" | port) ]
-    private static List<Rule> loadRulesFromFile(String file)
-        throws IOException
-    {
-        Scanner scanner = new Scanner(new File(file));
-        try {
-            List<Rule> result = new ArrayList<Rule>();
-            while (scanner.hasNextLine()) {
-                String line = scanner.nextLine().trim();
-
-                // skip blank lines and comments
-                if (line.length() == 0 || line.charAt(0) == '#')
-                    continue;
-
-                // must have 3 fields
-                String[] s = line.split("\\s+");
-                if (s.length != 3) {
-                    fail("Malformed line '%s'", line);
-                    continue;
-                }
-
-                // first field is the action ("bind" or "connect")
-                Action action = null;
-                for (Action a: Action.values()) {
-                    if (s[0].equalsIgnoreCase(a.name())) {
-                        action = a;
-                        break;
-                    }
-                }
-                if (action == null) {
-                    fail("Action '%s' not recognized", s[0]);
-                    continue;
-                }
-
-                // * port[-end]
-                int[] ports = parsePortRange(s[2]);
-                if (ports.length == 0) {
-                    fail("Malformed port range '%s'", s[2]);
-                    continue;
-                }
-
-                // match all addresses
-                if (s[1].equals("*")) {
-                    result.add(new PortRangeRule(action, ports[0], ports[1]));
-                    continue;
-                }
-
-                // hostname | ipaddress[/prefix]
-                int pos = s[1].indexOf('/');
-                try {
-                    if (pos < 0) {
-                        // hostname or ipaddress (no prefix)
-                        InetAddress[] addresses = InetAddress.getAllByName(s[1]);
-                        for (InetAddress address: addresses) {
-                            int prefix =
-                                (address instanceof Inet4Address) ? 32 : 128;
-                            result.add(new AddressPortRangeRule(action, address,
-                                prefix, ports[0], ports[1]));
-                        }
-                    } else {
-                        // ipaddress/prefix
-                        InetAddress address = InetAddress
-                            .getByName(s[1].substring(0, pos));
-                        int prefix = -1;
-                        try {
-                            prefix = Integer.parseInt(s[1].substring(pos+1));
-                            if (address instanceof Inet4Address) {
-                                // must be 1-31
-                                if (prefix < 0 || prefix > 32) prefix = -1;
-                            } else {
-                                // must be 1-128
-                                if (prefix < 0 || prefix > 128) prefix = -1;
-                            }
-                        } catch (NumberFormatException e) {
-                        }
-
-                        if (prefix > 0) {
-                            result.add(new AddressPortRangeRule(action,
-                                        address, prefix, ports[0], ports[1]));
-                        } else {
-                            fail("Malformed prefix '%s'", s[1]);
-                            continue;
-                        }
-                    }
-                } catch (UnknownHostException uhe) {
-                    fail("Unknown host or malformed IP address '%s'", s[1]);
-                    continue;
-                }
-            }
-            return result;
-        } finally {
-            scanner.close();
-        }
-    }
-
-    // converts unbound TCP socket to a SDP socket if it matches the rules
-    private void convertTcpToSdpIfMatch(FileDescriptor fdObj,
-                                               Action action,
-                                               InetAddress address,
-                                               int port)
-        throws IOException
-    {
-        boolean matched = false;
-        for (Rule rule: rules) {
-            if (rule.match(action, address, port)) {
-                int fd = fdAccess.get(fdObj);
-                convert(fd);
-                matched = true;
-                break;
-            }
-        }
-        if (log != null) {
-            String addr = (address instanceof Inet4Address) ?
-                address.getHostAddress() : "[" + address.getHostAddress() + "]";
-            if (matched) {
-                log.format("%s to %s:%d (socket converted to SDP protocol)\n", action, addr, port);
-            } else {
-                log.format("%s to %s:%d (no match)\n", action, addr, port);
-            }
-        }
-    }
-
-    @Override
-    public void implBeforeTcpBind(FileDescriptor fdObj,
-                              InetAddress address,
-                              int port)
-        throws IOException
-    {
-        if (enabled)
-            convertTcpToSdpIfMatch(fdObj, Action.BIND, address, port);
-    }
-
-    @Override
-    public void implBeforeTcpConnect(FileDescriptor fdObj,
-                                InetAddress address,
-                                int port)
-        throws IOException
-    {
-        if (enabled)
-            convertTcpToSdpIfMatch(fdObj, Action.CONNECT, address, port);
-    }
-
-    // -- native methods --
-    private static native void convert(int fd) throws IOException;
-}
--- a/src/solaris/classes/sun/nio/ch/InheritedChannel.java	Wed Sep 01 17:37:45 2010 -0700
+++ b/src/solaris/classes/sun/nio/ch/InheritedChannel.java	Fri Sep 03 13:11:54 2010 +0100
@@ -96,7 +96,7 @@
                                          FileDescriptor fd)
             throws IOException
         {
-            super(sp, fd);
+            super(sp, fd, true);
         }
 
         protected void implCloseSelectableChannel() throws IOException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/solaris/native/sun/net/sdp/SdpSupport.c	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+#if defined(__solaris__)
+  #if !defined(PROTO_SDP)
+    #define PROTO_SDP       257
+  #endif
+#elif defined(__linux__)
+  #if !defined(AF_INET_SDP)
+    #define AF_INET_SDP     27
+  #endif
+#endif
+
+#include "jni.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#define RESTARTABLE(_cmd, _result) do { \
+  do { \
+    _result = _cmd; \
+  } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+
+/**
+ * Creates a SDP socket.
+ */
+static int create(JNIEnv* env)
+{
+    int s;
+
+#if defined(__solaris__)
+  #ifdef AF_INET6
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
+  #else
+    int domain = AF_INET;
+  #endif
+    s = socket(domain, SOCK_STREAM, PROTO_SDP);
+#elif defined(__linux__)
+    /**
+     * IPv6 not supported by SDP on Linux
+     */
+    if (ipv6_available()) {
+        JNU_ThrowIOException(env, "IPv6 not supported");
+        return;
+    }
+    s = socket(AF_INET_SDP, SOCK_STREAM, 0);
+#else
+    /* not supported on other platforms at this time */
+    s = -1;
+    errno = EPROTONOSUPPORT;
+#endif
+
+    if (s < 0)
+        JNU_ThrowIOExceptionWithLastError(env, "socket");
+    return s;
+}
+
+/**
+ * Creates a SDP socket, returning file descriptor referencing the socket.
+ */
+JNIEXPORT jint JNICALL
+Java_sun_net_sdp_SdpSupport_create0(JNIEnv *env, jclass cls)
+{
+    return create(env);
+}
+
+/**
+ * Converts an existing file descriptor, that references an unbound TCP socket,
+ * to SDP.
+ */
+JNIEXPORT void JNICALL
+Java_sun_net_sdp_SdpSupport_convert0(JNIEnv *env, jclass cls, int fd)
+{
+    int s = create(env);
+    if (s >= 0) {
+        socklen_t len;
+        int arg, res;
+        struct linger linger;
+
+        /* copy socket options that are relevant to SDP */
+        len = sizeof(arg);
+        if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0)
+            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len);
+        len = sizeof(arg);
+        if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0)
+            setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len);
+        len = sizeof(linger);
+        if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)&linger, &len) == 0)
+            setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&linger, len);
+
+        RESTARTABLE(dup2(s, fd), res);
+        if (res < 0)
+            JNU_ThrowIOExceptionWithLastError(env, "dup2");
+        RESTARTABLE(close(s), res);
+    }
+}
--- a/src/solaris/native/sun/net/spi/SdpProvider.c	Wed Sep 01 17:37:45 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#if defined(__solaris__) && !defined(PROTO_SDP)
-#define PROTO_SDP       257
-#endif
-
-#include "jni.h"
-#include "jni_util.h"
-#include "net_util.h"
-
-#define RESTARTABLE(_cmd, _result) do { \
-  do { \
-    _result = _cmd; \
-  } while((_result == -1) && (errno == EINTR)); \
-} while(0)
-
-JNIEXPORT void JNICALL
-Java_sun_net_spi_SdpProvider_convert(JNIEnv *env, jclass cls, jint fd)
-{
-#ifdef PROTO_SDP
-#ifdef AF_INET6
-    int domain = ipv6_available() ? AF_INET6 : AF_INET;
-#else
-    int domain = AF_INET;
-#endif
-    int s = socket(domain, SOCK_STREAM, PROTO_SDP);
-    if (s < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "socket");
-    } else {
-        int arg, len, res;
-        struct linger linger;
-
-        /* copy socket options that are relevant to SDP */
-        len = sizeof(arg);
-        if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0)
-            setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len);
-        len = sizeof(arg);
-        if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0)
-            setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len);
-        len = sizeof(linger);
-        if (getsockopt(fd, SOL_SOCKET, SO_LINGER, (void*)&linger, &len) == 0)
-            setsockopt(s, SOL_SOCKET, SO_LINGER, (char*)&linger, len);
-
-        RESTARTABLE(dup2(s, fd), res);
-        if (res < 0)
-            JNU_ThrowIOExceptionWithLastError(env, "dup2");
-        RESTARTABLE(close(s), res);
-    }
-#else
-    JNU_ThrowInternalError(env, "should not reach here");
-#endif
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/oracle/net/Sanity.java	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.oracle.net.Sdp;
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.*;
+
+/**
+ * Exercise com.oracle.net.Sdp with each IP address plumbed to InfiniBand
+ * interfaces listed in a given file.
+ */
+
+public class Sanity {
+    public static void main(String[] args) throws Exception {
+        // The file is a list of interfaces to test.
+        Scanner s = new Scanner(new File(args[0]));
+        try {
+            while (s.hasNextLine()) {
+                String link = s.nextLine();
+                NetworkInterface ni = NetworkInterface.getByName(link);
+                if (ni != null) {
+                    Enumeration<InetAddress> addrs = ni.getInetAddresses();
+                    while (addrs.hasMoreElements()) {
+                        InetAddress addr = addrs.nextElement();
+                        System.out.format("Testing %s: %s\n", link, addr.getHostAddress());
+                        test(addr);
+                    }
+                }
+            }
+        } finally {
+            s.close();
+        }
+    }
+
+    static void test(InetAddress addr) throws Exception {
+        // Test SocketChannel and ServerSocketChannel
+        ServerSocketChannel ssc = Sdp.openServerSocketChannel();
+        try {
+            ssc.socket().bind(new InetSocketAddress(addr, 0));
+            int port = ssc.socket().getLocalPort();
+
+            // SocketChannel.connect (implicit bind)
+            SocketChannel client = Sdp.openSocketChannel();
+            try {
+                client.connect(new InetSocketAddress(addr, port));
+                SocketChannel peer = ssc.accept();
+                try {
+                    testConnection(Channels.newOutputStream(client),
+                                   Channels.newInputStream(peer));
+                } finally {
+                    peer.close();
+                }
+            } finally {
+                client.close();
+            }
+
+            // SocketChannel.connect (explicit bind)
+            client = Sdp.openSocketChannel();
+            try {
+                client.socket().bind(new InetSocketAddress(addr, 0));
+                client.connect(new InetSocketAddress(addr, port));
+                ssc.accept().close();
+            } finally {
+                client.close();
+            }
+        } finally {
+            ssc.close();
+        }
+
+        // Test Socket and ServerSocket
+        ServerSocket ss = Sdp.openServerSocket();
+        try {
+            ss.bind(new InetSocketAddress(addr, 0));
+            int port = ss.getLocalPort();
+
+            // Socket.connect (implicit bind)
+            Socket s = Sdp.openSocket();
+            try {
+                s.connect(new InetSocketAddress(addr, port));
+                Socket peer = ss.accept();
+                try {
+                    testConnection(s.getOutputStream(), peer.getInputStream());
+                } finally {
+                    peer.close();
+                }
+            } finally {
+                s.close();
+            }
+
+            // Socket.connect (explicit bind)
+            s = Sdp.openSocket();
+            try {
+                s.bind(new InetSocketAddress(addr, 0));
+                s.connect(new InetSocketAddress(addr, port));
+                ss.accept().close();
+            } finally {
+                s.close();
+            }
+        } finally {
+            ss.close();
+        }
+    }
+
+    static void testConnection(OutputStream out, InputStream in)
+        throws IOException
+    {
+        byte[] msg = "hello".getBytes();
+        out.write(msg);
+
+        byte[] ba = new byte[100];
+        int nread = 0;
+        while (nread < msg.length) {
+            int n = in.read(ba);
+            if (n < 0)
+                throw new IOException("EOF not expected!");
+            nread += n;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/com/oracle/net/sanity.sh	Fri Sep 03 13:11:54 2010 +0100
@@ -0,0 +1,66 @@
+#
+# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+# @test
+# @bug 6965072
+# @summary Unit test for SDP support
+# @build  Sanity
+# @run shell sanity.sh
+
+IB_LINKS=ib.links
+
+OS=`uname -s`
+case "$OS" in
+    SunOS )
+        /usr/sbin/dladm show-part -o LINK -p > ${IB_LINKS}
+        if [ $? != 0 ]; then
+            echo "Unable to get InfiniBand parition link information"
+            exit 0
+        fi
+        ;;
+    Linux )
+        if [ ! -f /proc/net/sdp ]; then
+            echo "InfiniBand SDP module not installed"
+            exit 0
+        fi
+        egrep "^[ \t]+ib" /proc/net/dev|cut -d':' -f1|tr -d '\t ' > ${IB_LINKS}
+        ;; 
+    * )
+        echo "This test only runs on Solaris or Linux"
+        exit 0
+        ;;
+esac
+
+if [ -z "$TESTJAVA" ]; then
+    JAVA=java
+    TESTCLASSES=.
+    TESTSRC=.
+else
+    JAVA="${TESTJAVA}/bin/java"
+fi
+
+CLASSPATH=${TESTCLASSES}:${TESTSRC}
+export CLASSPATH
+
+# Run sanity test (IPv4-only for now)
+$JAVA -Djava.net.preferIPv4Stack=true Sanity ${IB_LINKS}
--- a/test/sun/net/sdp/ProbeIB.java	Wed Sep 01 17:37:45 2010 -0700
+++ b/test/sun/net/sdp/ProbeIB.java	Fri Sep 03 13:11:54 2010 +0100
@@ -34,21 +34,16 @@
 
 public class ProbeIB {
     public static void main(String[] args) throws IOException {
-        Scanner s = new Scanner(new File("/etc/path_to_inst"));
+        Scanner s = new Scanner(new File(args[0]));
         try {
             while (s.hasNextLine()) {
-                String line = s.nextLine();
-                if (line.startsWith("#"))
-                    continue;
-                String[] fields = line.split("\\s+");
-                if (!fields[2].equals("\"ibd\""))
-                    continue;
-                String name = fields[2].substring(1, fields[2].length()-1) + fields[1];
-                NetworkInterface ni = NetworkInterface.getByName(name);
+                String link = s.nextLine();
+                NetworkInterface ni = NetworkInterface.getByName(link);
                 if (ni != null) {
                     Enumeration<InetAddress> addrs = ni.getInetAddresses();
                     while (addrs.hasMoreElements()) {
-                        System.out.println(addrs.nextElement().getHostAddress());
+                        InetAddress addr = addrs.nextElement();
+                        System.out.println(addr.getHostAddress());
                     }
                 }
             }
--- a/test/sun/net/sdp/sanity.sh	Wed Sep 01 17:37:45 2010 -0700
+++ b/test/sun/net/sdp/sanity.sh	Fri Sep 03 13:11:54 2010 +0100
@@ -33,14 +33,15 @@
     echo "This is a Solaris-only test"
     exit 0
 fi
-SDPADM=/usr/sbin/sdpadm
-if [ ! -f ${SDPADM} ]; then
-    echo "SDP not available"
-    exit 0
-fi
-${SDPADM} status|grep Enabled
-if [ $? != 0 ]; then 
-    echo "SDP not enabled"
+
+IB_LINKS=ib.links
+IB_ADDRS=ib.addrs
+
+# Display IB partition link information
+# (requires Solaris 11, will fail on Solaris 10)
+/usr/sbin/dladm show-part -o LINK -p > ${IB_LINKS}
+if [ $? != 0 ]; then
+    echo "Unable to get IB parition link information"
     exit 0
 fi
 
@@ -56,13 +57,13 @@
 export CLASSPATH
 
 # Probe for IP addresses plumbed to IB interfaces
-$JAVA -Djava.net.preferIPv4Stack=true ProbeIB > ib_addrs
+$JAVA -Djava.net.preferIPv4Stack=true ProbeIB ${IB_LINKS} > ${IB_ADDRS}
 
 # Create sdp.conf
 SDPCONF=sdp.conf
 rm ${SDPCONF}
 touch ${SDPCONF}
-cat ib_addrs | while read ADDR
+cat ${IB_ADDRS} | while read ADDR
 do
    echo "bind ${ADDR} *" > ${SDPCONF}
    echo "connect ${ADDR} *" >> ${SDPCONF}