diff --git a/make/java/net/FILES_c.gmk b/make/java/net/FILES_c.gmk index 2eb4daa2cbb689344b059c77dba87dbba965266c..0e638816d1046fe39d3b06af5e9a60d70f7a9a71 100644 --- a/make/java/net/FILES_c.gmk +++ b/make/java/net/FILES_c.gmk @@ -39,6 +39,10 @@ FILES_c = \ ResolverConfigurationImpl.c \ DefaultProxySelector.c +ifeq ($(PLATFORM), solaris) + FILES_c += SdpProvider.c +endif + ifeq ($(PLATFORM), linux) FILES_c += linux_close.c endif diff --git a/make/java/net/Makefile b/make/java/net/Makefile index b9a3defdb8ccae2429ade7227b77a2816bf6ac2f..203b059a3888e9514395af9d135f6a34fe401e63 100644 --- a/make/java/net/Makefile +++ b/make/java/net/Makefile @@ -108,11 +108,24 @@ CLASSES.export += java.lang.Integer java.io.FileDescriptor java.net.InetAddressI # LOCALE_SET_DEFINITION = jre -properties: $(LIBDIR) $(LIBDIR)/net.properties +MISC_FILES = $(LIBDIR) $(LIBDIR)/net.properties $(LIBDIR)/net.properties: $(SHARE_SRC)/lib/net.properties @$(RM) $@ $(CP) $< $@ -build: properties +# +# SDP configuration template +# +ifeq ($(PLATFORM), solaris) +SDP_PATH = sdp/sdp.conf.template +SDP_CONF = $(LIBDIR)/$(SDP_PATH) +$(SDP_CONF): $(PLATFORM_SRC)/lib/$(SDP_PATH) + @$(RM) $* + $(install-file) + +MISC_FILES += $(SDP_CONF) +endif + +build: $(MISC_FILES) diff --git a/make/java/net/mapfile-vers b/make/java/net/mapfile-vers index d9803f8f9446c5d5d891aeffaafb43e0c3b1f558..c30803cbfefb9806840a7d5a79ba6039e5588d80 100644 --- a/make/java/net/mapfile-vers +++ b/make/java/net/mapfile-vers @@ -90,6 +90,7 @@ SUNWprivate_1.1 { Java_sun_net_dns_ResolverConfigurationImpl_fallbackDomain0; Java_sun_net_spi_DefaultProxySelector_init; Java_sun_net_spi_DefaultProxySelector_getSystemProxy; + Java_sun_net_spi_SdpProvider_convert; NET_AllocSockaddr; NET_SockaddrToInetAddress; NET_SockaddrEqualsInetAddress; diff --git a/make/sun/net/FILES_java.gmk b/make/sun/net/FILES_java.gmk index 55b6477fc26711e460bb82b9d3b7bd5cde767981..1ab771a37f10cbb53414f4d8ea8356e135fc776f 100644 --- a/make/sun/net/FILES_java.gmk +++ b/make/sun/net/FILES_java.gmk @@ -39,6 +39,7 @@ FILES_java = \ sun/net/TransferProtocolClient.java \ sun/net/ConnectionResetException.java \ sun/net/NetProperties.java \ + sun/net/NetHooks.java \ sun/net/util/IPAddressUtil.java \ sun/net/dns/ResolverConfiguration.java \ sun/net/dns/ResolverConfigurationImpl.java \ @@ -123,3 +124,7 @@ FILES_java = \ ifeq ($(PLATFORM), windows) FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java endif + +ifeq ($(PLATFORM), solaris) + FILES_java += sun/net/spi/SdpProvider.java +endif diff --git a/src/share/classes/java/net/AbstractPlainSocketImpl.java b/src/share/classes/java/net/AbstractPlainSocketImpl.java index 597783bf730628fcf39cac13680ade28120e4e82..18af8d6db64b67b3cc05e409c2383f8bc1976d12 100644 --- a/src/share/classes/java/net/AbstractPlainSocketImpl.java +++ b/src/share/classes/java/net/AbstractPlainSocketImpl.java @@ -33,6 +33,7 @@ import java.io.FileDescriptor; import java.io.ByteArrayOutputStream; import sun.net.ConnectionResetException; +import sun.net.NetHooks; /** * Default Socket Implementation. This implementation does @@ -304,6 +305,11 @@ abstract class AbstractPlainSocketImpl extends SocketImpl */ synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException { + synchronized (fdLock) { + if (!closePending && (socket == null || !socket.isBound())) { + NetHooks.beforeTcpConnect(fd, address, port); + } + } try { FileDescriptor fd = acquireFD(); try { @@ -339,6 +345,11 @@ abstract class AbstractPlainSocketImpl extends SocketImpl protected synchronized void bind(InetAddress address, int lport) throws IOException { + synchronized (fdLock) { + if (!closePending && (socket == null || !socket.isBound())) { + NetHooks.beforeTcpBind(fd, address, lport); + } + } socketBind(address, lport); if (socket != null) socket.setBound(); diff --git a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java index b4fcb9c2c30b12ddb0c8979c29d2c744d50f3f26..492319301590ea115c0540502ea56d5e4888b97d 100644 --- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -37,6 +37,7 @@ import java.util.HashSet; import java.util.Collections; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import sun.net.NetHooks; /** * Base implementation of AsynchronousServerSocketChannel. @@ -131,6 +132,7 @@ abstract class AsynchronousServerSocketChannelImpl synchronized (stateLock) { if (localAddress != null) throw new AlreadyBoundException(); + NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); Net.listen(fd, backlog < 1 ? 50 : backlog); localAddress = Net.localAddress(fd); diff --git a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 09637fbae1bd1b93156ee7a81c5005b7a7090aca..84b81a0c8b0bf93f0b0e13826b0259f9e5f3791a 100644 --- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -38,6 +38,7 @@ import java.util.HashSet; import java.util.Collections; import java.util.concurrent.*; import java.util.concurrent.locks.*; +import sun.net.NetHooks; /** * Base implementation of AsynchronousSocketChannel @@ -387,6 +388,7 @@ abstract class AsynchronousSocketChannelImpl throw new AlreadyBoundException(); InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); + NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); } diff --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index d509198aee203ee3318f1328bbe068abfd822b67..0b0e4b6aee24f0d7473d2c49c609ab8e6fbddaff 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -31,6 +31,7 @@ import java.net.*; import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; +import sun.net.NetHooks; /** @@ -191,6 +192,7 @@ class ServerSocketChannelImpl SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkListen(isa.getPort()); + NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); Net.listen(fd, backlog < 1 ? 50 : backlog); synchronized (stateLock) { diff --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java index 20944774d4ee58e06c5f5441a828701abf15b893..ec4f8f5754b05fdb431c67b936e2e88cbf7785a0 100644 --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -32,6 +32,7 @@ import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.channels.spi.*; import java.util.*; +import sun.net.NetHooks; /** @@ -526,6 +527,7 @@ class SocketChannelImpl throw new AlreadyBoundException(); InetSocketAddress isa = (local == null) ? new InetSocketAddress(0) : Net.checkAddress(local); + NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort()); Net.bind(fd, isa.getAddress(), isa.getPort()); localAddress = Net.localAddress(fd); } @@ -577,6 +579,12 @@ class SocketChannelImpl if (!isOpen()) { return false; } + // notify hook only if unbound + if (localAddress == null) { + NetHooks.beforeTcpConnect(fd, + isa.getAddress(), + isa.getPort()); + } readerThread = NativeThread.current(); } for (;;) { diff --git a/src/solaris/classes/sun/net/NetHooks.java b/src/solaris/classes/sun/net/NetHooks.java new file mode 100644 index 0000000000000000000000000000000000000000..f847934190c4231e59a0628b964e5a0a718c837c --- /dev/null +++ b/src/solaris/classes/sun/net/NetHooks.java @@ -0,0 +1,122 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.net; + +import java.net.InetAddress; +import java.io.FileDescriptor; +import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; + +/** + * Defines static methods to be invoked prior to binding or connecting TCP sockets. + */ + +public final class NetHooks { + + /** + * A provider with hooks to allow sockets be converted prior to binding or + * connecting a TCP socket. + * + *

Concrete implementations of this class should define a zero-argument + * constructor and implement the abstract methods specified below. + */ + public static abstract class Provider { + /** + * Initializes a new instance of this class. + */ + protected Provider() {} + + /** + * Invoked prior to binding a TCP socket. + */ + public abstract void implBeforeTcpBind(FileDescriptor fdObj, + InetAddress address, + int port) + throws IOException; + + /** + * Invoked prior to connecting an unbound TCP socket. + */ + public abstract void implBeforeTcpConnect(FileDescriptor fdObj, + InetAddress address, + int port) + throws IOException; + } + + /** + * For now, we load the SDP provider on Solaris. In the future this may + * 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() { + @Override public Provider run() { + Class c; + try { + c = (Class)Class.forName(cn, true, null); + } catch (ClassNotFoundException x) { + throw new AssertionError(x); + } + 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; + + /** + * Invoke prior to binding a TCP socket. + */ + public static void beforeTcpBind(FileDescriptor fdObj, + InetAddress address, + int port) + throws IOException + { + if (provider != null) + provider.implBeforeTcpBind(fdObj, address, port); + } + + /** + * Invoke prior to connecting an unbound TCP socket. + */ + public static void beforeTcpConnect(FileDescriptor fdObj, + InetAddress address, + int port) + throws IOException + { + if (provider != null) + provider.implBeforeTcpConnect(fdObj, address, port); + } +} diff --git a/src/solaris/classes/sun/net/spi/SdpProvider.java b/src/solaris/classes/sun/net/spi/SdpProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..4ae7d9fa58cd7fb50161b75809d0b00d98aed608 --- /dev/null +++ b/src/solaris/classes/sun/net/spi/SdpProvider.java @@ -0,0 +1,339 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.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 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 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 loadRulesFromFile(String file) + throws IOException + { + Scanner scanner = new Scanner(new File(file)); + try { + List result = new ArrayList(); + 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; +} diff --git a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java index 78ed152d3a1eefc1656b75b5dd886f4f2bbabc0b..e80f202bdff96c2324a63f36d4d82bedc1faab9c 100644 --- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -32,6 +32,7 @@ import java.util.concurrent.*; import java.io.IOException; import java.io.FileDescriptor; import java.security.AccessController; +import sun.net.NetHooks; import sun.security.action.GetPropertyAction; /** @@ -305,6 +306,7 @@ class UnixAsynchronousSocketChannelImpl sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); // check and set state + boolean notifyBeforeTcpConnect; synchronized (stateLock) { if (state == ST_CONNECTED) throw new AlreadyConnectedException(); @@ -312,12 +314,16 @@ class UnixAsynchronousSocketChannelImpl throw new ConnectionPendingException(); state = ST_PENDING; pendingRemote = remote; + notifyBeforeTcpConnect = (localAddress == null); } AbstractFuture result = null; Throwable e = null; try { begin(); + // notify hook if unbound + if (notifyBeforeTcpConnect) + NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort()); int n = Net.connect(fd, isa.getAddress(), isa.getPort()); if (n == IOStatus.UNAVAILABLE) { // connection could not be established immediately diff --git a/src/solaris/lib/sdp/sdp.conf.template b/src/solaris/lib/sdp/sdp.conf.template new file mode 100644 index 0000000000000000000000000000000000000000..71cb5c2ce84d0447d2714121efac0b71b7544831 --- /dev/null +++ b/src/solaris/lib/sdp/sdp.conf.template @@ -0,0 +1,30 @@ +# +# Configuration file to enable InfiniBand Sockets Direct Protocol. +# +# Each line that does not start with a comment (#) is a rule to indicate when +# the SDP transport protocol should be used. The format of a rule is as follows: +# ("bind"|"connect") 1*LWSP-char (hostname|ipaddress["/"prefix]) 1*LWSP-char ("*"|port)["-"("*"|port)] +# +# A "bind" rule indicates that the SDP protocol transport should be used when +# a TCP socket binds to an address/port that matches the rule. A "connect" rule +# indicates that the SDP protocol transport should be used when an unbound +# TCP socket attempts to connect to an address/port that matches the rule. +# Addresses may be specified as hostnames or literal Internet Protocol (IP) +# addresses. When a literal IP address is used then a prefix length may be used +# to indicate the number of bits for matching (useful when a block of addresses +# or subnet is allocated to the InfiniBand fabric). + +# Use SDP for all sockets that bind to specific local addresses +#bind 192.168.1.1 * +#bind fe80::21b:24ff:fe3d:7896 * + +# Use SDP for all sockets that bind to the wildcard address in a port range +#bind 0.0.0.0 5000-5999 +#bind ::0 5000-5999 + +# Use SDP when connecting to all application services on 192.168.1.* +#connect 192.168.1.0/24 1024-* + +# Use SDP when connecting to the http server or MySQL database on hpccluster. +#connect hpccluster.foo.com 80 +#connect hpccluster.foo.com 3306 diff --git a/src/solaris/native/sun/net/spi/SdpProvider.c b/src/solaris/native/sun/net/spi/SdpProvider.c new file mode 100644 index 0000000000000000000000000000000000000000..00d7f4ba6dc5591d1d4fe671ef50408d5bedc8d4 --- /dev/null +++ b/src/solaris/native/sun/net/spi/SdpProvider.c @@ -0,0 +1,74 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +#include +#include + +#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 + int domain = ipv6_available() ? AF_INET6 : AF_INET; + 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 +} diff --git a/src/solaris/native/sun/nio/ch/FileChannelImpl.c b/src/solaris/native/sun/nio/ch/FileChannelImpl.c index 7b37e6168b81cd1283d47ef8258eb8ae89993ff8..c1c3cc9e82678ae1105705639161ed03b555e48a 100644 --- a/src/solaris/native/sun/nio/ch/FileChannelImpl.c +++ b/src/solaris/native/sun/nio/ch/FileChannelImpl.c @@ -231,6 +231,8 @@ Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this, if (result < 0) { if (errno == EAGAIN) return IOS_UNAVAILABLE; + if (errno == EOPNOTSUPP) + return IOS_UNSUPPORTED_CASE; if ((errno == EINVAL) && ((ssize_t)count >= 0)) return IOS_UNSUPPORTED_CASE; if (errno == EINTR) diff --git a/src/windows/classes/sun/net/NetHooks.java b/src/windows/classes/sun/net/NetHooks.java new file mode 100644 index 0000000000000000000000000000000000000000..0d8f60b3a42b9d7c0c63fd0febe0b6796f9ab82f --- /dev/null +++ b/src/windows/classes/sun/net/NetHooks.java @@ -0,0 +1,59 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.net; + +import java.net.InetAddress; +import java.io.FileDescriptor; +import java.io.IOException; + +/** + * Defines static methods to ensure that any installed net hooks are invoked + * prior to binding or connecting TCP sockets. + */ + +public final class NetHooks { + + /** + * Invoke prior to binding a TCP socket. + */ + public static void beforeTcpBind(FileDescriptor fdObj, + InetAddress address, + int port) + throws IOException + { + // nothing to do + } + + /** + * Invoke prior to connecting an unbound TCP socket. + */ + public static void beforeTcpConnect(FileDescriptor fdObj, + InetAddress address, + int port) + throws IOException + { + // nothing to do + } +} diff --git a/test/sun/net/sdp/ProbeIB.java b/test/sun/net/sdp/ProbeIB.java new file mode 100644 index 0000000000000000000000000000000000000000..ac2a4b72d74436cfb81f1db6e2e25f4e4fbbf322 --- /dev/null +++ b/test/sun/net/sdp/ProbeIB.java @@ -0,0 +1,59 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.io.File; +import java.io.IOException; +import java.net.NetworkInterface; +import java.net.InetAddress; +import java.util.Scanner; +import java.util.Enumeration; + +/** + * Probes for InfiniBand devices plumbed with IP addresses. + */ + +public class ProbeIB { + public static void main(String[] args) throws IOException { + Scanner s = new Scanner(new File("/etc/path_to_inst")); + 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); + if (ni != null) { + Enumeration addrs = ni.getInetAddresses(); + while (addrs.hasMoreElements()) { + System.out.println(addrs.nextElement().getHostAddress()); + } + } + } + } finally { + s.close(); + } + } +} diff --git a/test/sun/net/sdp/Sanity.java b/test/sun/net/sdp/Sanity.java new file mode 100644 index 0000000000000000000000000000000000000000..2c8d55e00afa3fa54a11a292f59f332ec77f1e0f --- /dev/null +++ b/test/sun/net/sdp/Sanity.java @@ -0,0 +1,168 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Enumeration; + +/** + * Sanity check Socket/ServerSocket and each of the stream-oriented channels + * on each IP address plumbed to the network adapters. + */ + +public class Sanity { + public static void main(String[] args) throws Exception { + Enumeration nifs = NetworkInterface.getNetworkInterfaces(); + while (nifs.hasMoreElements()) { + NetworkInterface ni = nifs.nextElement(); + Enumeration addrs = ni.getInetAddresses(); + while (addrs.hasMoreElements()) { + InetAddress addr = addrs.nextElement(); + test(addr); + } + } + } + + static void test(InetAddress addr) throws Exception { + System.out.println(addr.getHostAddress()); + + // ServerSocketChannel.bind + ServerSocketChannel ssc = ServerSocketChannel.open(); + try { + ssc.bind(new InetSocketAddress(addr, 0)); + int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); + + // SocketChannel.connect (implicit bind) + SocketChannel client = SocketChannel.open(); + 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 = SocketChannel.open(); + try { + client.bind(new InetSocketAddress(addr, 0)) + .connect(new InetSocketAddress(addr, port)); + ssc.accept().close(); + } finally { + client.close(); + } + } finally { + ssc.close(); + } + + // AsynchronousServerSocketChannel.bind + AsynchronousServerSocketChannel server = + AsynchronousServerSocketChannel.open(); + try { + server.bind(new InetSocketAddress(addr, 0)); + int port = ((InetSocketAddress)(server.getLocalAddress())).getPort(); + + // AsynchronousSocketChannel.connect (implicit bind) + AsynchronousSocketChannel client = AsynchronousSocketChannel.open(); + try { + client.connect(new InetSocketAddress(addr, port)).get(); + AsynchronousSocketChannel peer = server.accept().get(); + try { + testConnection(Channels.newOutputStream(client), + Channels.newInputStream(peer)); + } finally { + peer.close(); + } + } finally { + client.close(); + } + + // AsynchronousSocketChannel.connect (explicit bind) + client = AsynchronousSocketChannel.open(); + try { + client.bind(new InetSocketAddress(addr, 0)) + .connect(new InetSocketAddress(addr, port)).get(); + server.accept().get().close(); + } finally { + client.close(); + } + } finally { + server.close(); + } + + // ServerSocket.bind + ServerSocket ss = new ServerSocket(); + try { + ss.bind(new InetSocketAddress(addr, 0)); + int port = ss.getLocalPort(); + + // Socket.connect (implicit bind) + Socket s = new Socket(); + 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 = new Socket(); + 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; + } + } +} diff --git a/test/sun/net/sdp/sanity.sh b/test/sun/net/sdp/sanity.sh new file mode 100644 index 0000000000000000000000000000000000000000..baca9feccef476f71f2aa6fe6c59c7d72c3607ce --- /dev/null +++ b/test/sun/net/sdp/sanity.sh @@ -0,0 +1,72 @@ +# +# Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 4890703 +# @summary Unit test for Solaris SDP support +# @build ProbeIB Sanity +# @run shell sanity.sh + +# Check we are on Solaris and that SDP is enabled +OS=`uname -s` +if [ "$OS" != "SunOS" ]; then + 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" + exit 0 +fi + +if [ -z "$TESTJAVA" ]; then + JAVA=java + TESTCLASSES=. + TESTSRC=. +else + JAVA="${TESTJAVA}/bin/java" +fi + +CLASSPATH=${TESTCLASSES}:${TESTSRC} +export CLASSPATH + +# Probe for IP addresses plumbed to IB interfaces +$JAVA -Djava.net.preferIPv4Stack=true ProbeIB > ib_addrs + +# Create sdp.conf +SDPCONF=sdp.conf +rm ${SDPCONF} +touch ${SDPCONF} +cat ib_addrs | while read ADDR +do + echo "bind ${ADDR} *" > ${SDPCONF} + echo "connect ${ADDR} *" >> ${SDPCONF} +done + +# Sanity check +$JAVA -Djava.net.preferIPv4Stack=true -Dcom.sun.sdp.conf=${SDPCONF} -Dcom.sun.sdp.debug Sanity