view patches/security/20130618/7170730-windows_network_stack.patch @ 2907:d7eca687b7d2

Add 2013/06/18 security patches. 2013-06-22 Andrew John Hughes <gnu.andrew@member.fsf.org> * patches/idresolver_fix.patch: Removed. Part of 6469266. * Makefile.am: (SECURITY_PATCHES): Add new ones. (SPECIAL_SECURITY_PATCH_1): Renamed from SPECIAL_SECURITY_PATCH. (SPECIAL_SECURITY_PATCH_2): Add 8009071, which needs to be applied after some AWT backports. (ICEDTEA_PATCHES): Use SPECIAL_SECURITY_PATCH_{1,2}. Move 8005615, 8007393 & 8007611 to SECURITY_PATCHES as must be applied before 8004584. Add 7171223 to end. * patches/openjdk/6307603-xrender-01.patch, * patches/openjdk/6469266-xmlsec_1.4.2.patch, * patches/openjdk/6656651-windows_lcd_glyphs.patch, * patches/openjdk/6786028-wcag_bold_tags.patch, * patches/openjdk/6786682-wcag_lang.patch, * patches/openjdk/6786688-wcag_table.patch, * patches/openjdk/6786690-wcag_dl.patch, * patches/openjdk/6802694-no_deprecated.patch, * patches/openjdk/6851834-restructure.patch, * patches/openjdk/6888167-medialib_memory_leaks.patch, * patches/openjdk/6961178-doclet_xml.patch, * patches/openjdk/6990754-use_native_memory_for_symboltable.patch, * patches/openjdk/7006270-regressions.patch, * patches/openjdk/7008809-report_class_in_arraystoreexception.patch, * patches/openjdk/7014851-unused_parallel_compaction_code.patch, * patches/openjdk/7017732-move_static_fields_to_class.patch, * patches/openjdk/7036747-elfstringtable.patch, * patches/openjdk/7086585-flexible_field_injection.patch, * patches/openjdk/7171223-strict_aliasing.patch, * patches/openjdk/7195301-no_instanceof_node.patch, * patches/security/20130618/6741606-apache_santuario.patch, * patches/security/20130618/7158805-nested_subroutine_rewriting.patch, * patches/security/20130618/7170730-windows_network_stack.patch, * patches/security/20130618/8000638-improve_deserialization.patch, * patches/security/20130618/8000642-better_transportation_handling.patch, * patches/security/20130618/8001032-restrict_object_access-corba.patch, * patches/security/20130618/8001032-restrict_object_access-jdk.patch, * patches/security/20130618/8001033-refactor_address_handling.patch, * patches/security/20130618/8001034-memory_management.patch, * patches/security/20130618/8001038-resourcefully_handle_resources.patch, * patches/security/20130618/8001043-clarify_definition_restrictions.patch, * patches/security/20130618/8001309-better_handling_of_annotation_interfaces.patch, * patches/security/20130618/8001318-6_fixup.patch, * patches/security/20130618/8001318-socket_getlocaladdress_consistency.patch, * patches/security/20130618/8001330-checking_order_improvement.patch, * patches/security/20130618/8001330-improve_checking_order.patch, * patches/security/20130618/8003703-update_rmi_connection_dialog.patch, * patches/security/20130618/8004584-augment_applet_contextualization.patch, * patches/security/20130618/8005007-better_glyph_processing.patch, * patches/security/20130618/8006328-6_fixup.patch, * patches/security/20130618/8006328-sound_class_robustness.patch, * patches/security/20130618/8006611-improve_scripting.patch, * patches/security/20130618/8007467-improve_jmx_internal_api_robustness.patch, * patches/security/20130618/8007471-6_fixup.patch, * patches/security/20130618/8007471-improve_mbean_notifications.patch, * patches/security/20130618/8007812-getenclosingmethod.patch, * patches/security/20130618/8008120-improve_jmx_class_checking.patch, * patches/security/20130618/8008124-better_compliance_testing.patch, * patches/security/20130618/8008128-better_jmx_api_coherence.patch, * patches/security/20130618/8008132-better_serialization.patch, * patches/security/20130618/8008585-jmx_data_handling.patch, * patches/security/20130618/8008593-better_urlclassloader.patch, * patches/security/20130618/8008603-jmx_provider_provision.patch, * patches/security/20130618/8008611-6_fixup.patch, * patches/security/20130618/8008611-jmx_annotations.patch, * patches/security/20130618/8008615-jmx_internal_api_robustness.patch, * patches/security/20130618/8008623-mbeanserver_handling.patch, * patches/security/20130618/8008744-6741606_rework.patch, * patches/security/20130618/8008982-jmx_interface_changes.patch, * patches/security/20130618/8009004-rmi_connection_improvement.patch, * patches/security/20130618/8009013-t2k_glyphs.patch, * patches/security/20130618/8009034-jmx_notification_improvement.patch, * patches/security/20130618/8009038-jmx_notification_support_improvement.patch, * patches/security/20130618/8009067-improve_key_storing.patch, * patches/security/20130618/8009071-improve_shape_handling.patch, * patches/security/20130618/8009235-improve_tsa_data_handling.patch, * patches/security/20130618/8009554-serialjavaobject.patch, * patches/security/20130618/8011243-improve_imaginglib.patch, * patches/security/20130618/8011248-better_component_rasters.patch, * patches/security/20130618/8011253-better_short_component_rasters.patch, * patches/security/20130618/8011257-better_byte_component_rasters.patch, * patches/security/20130618/8011557-improve_reflection.patch, * patches/security/20130618/8012375-javadoc_framing.patch, * patches/security/20130618/8012421-better_positioning.patch, * patches/security/20130618/8012438-better_image_validation.patch, * patches/security/20130618/8012597-better_image_channel_validation.patch, * patches/security/20130618/8012601-better_layout_validation.patch, * patches/security/20130618/8014281-better_xml_signature_checking.patch, * patches/security/20130618/8015997-more_javadoc_framing.patch, * patches/security/20130618/diamond_fix.patch, * patches/security/20130618/handle_npe.patch, * patches/security/20130618/hs_merge-01.patch, * patches/security/20130618/hs_merge-02.patch, * patches/security/20130618/hs_merge-03.patch, * patches/security/20130618/hs_merge-04.patch, * patches/security/20130618/javac_issue.patch, * patches/security/20130618/langtools_generics.patch, * patches/security/20130618/langtools_merge-01.patch, * patches/security/20130618/langtools_merge-02.patch, * patches/security/20130618/langtools_merge-03.patch: 2013/06/18 security patches.
author Andrew John Hughes <gnu.andrew@redhat.com>
date Sat, 22 Jun 2013 16:38:24 -0500
parents
children
line wrap: on
line source

# HG changeset patch
# User andrew
# Date 1371235188 -3600
# Node ID 8664ebe88635d671ed0134e9348d5e6caea81d0d
# Parent  7ecadad337414327d0d0ca6a8efcc40b7e8a9d29
7170730: Improve Windows network stack support.
Summary: Enable exclusive binding of ports on Windows
Contributed-by: Severin Gehwolf <sgehwolf@redhat.com>

diff --git a/make/java/nio/mapfile-linux b/make/java/nio/mapfile-linux
--- openjdk/jdk/make/java/nio/mapfile-linux
+++ openjdk/jdk/make/java/nio/mapfile-linux
@@ -61,7 +61,8 @@
 		Java_sun_nio_ch_NativeThread_init;
 		Java_sun_nio_ch_NativeThread_signal;
 		Java_sun_nio_ch_Net_socket0;
-		Java_sun_nio_ch_Net_bind;
+		Java_sun_nio_ch_Net_bind0;
+		Java_sun_nio_ch_Net_isExclusiveBindAvailable;
 		Java_sun_nio_ch_Net_connect;
 		Java_sun_nio_ch_Net_localPort;
 		Java_sun_nio_ch_Net_localInetAddress;
diff --git a/make/java/nio/mapfile-solaris b/make/java/nio/mapfile-solaris
--- openjdk/jdk/make/java/nio/mapfile-solaris
+++ openjdk/jdk/make/java/nio/mapfile-solaris
@@ -59,7 +59,8 @@
 		Java_sun_nio_ch_NativeThread_init;
 		Java_sun_nio_ch_NativeThread_signal;
 		Java_sun_nio_ch_Net_socket0;
-		Java_sun_nio_ch_Net_bind;
+		Java_sun_nio_ch_Net_bind0;
+		Java_sun_nio_ch_Net_isExclusiveBindAvailable;
 		Java_sun_nio_ch_Net_connect;
 		Java_sun_nio_ch_Net_localPort;
 		Java_sun_nio_ch_Net_localInetAddress;
diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
--- openjdk/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
+++ openjdk/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java
@@ -473,6 +473,10 @@
                             {
                                 Net.setIntOption(fd, opt, arg);
                             }
+                            boolean getIsBoundCondition()
+                            {
+                                return localAddress != null;
+                            }
                         };
                 options = new SocketOptsImpl.IP(d);
             }
diff --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java
--- openjdk/jdk/src/share/classes/sun/nio/ch/Net.java
+++ openjdk/jdk/src/share/classes/sun/nio/ch/Net.java
@@ -36,8 +36,42 @@
     private Net() { }
 
 
+    // set to true if exclusive binding is on for Windows
+    private static final boolean exclusiveBind;
+
+    static {
+        int availLevel = isExclusiveBindAvailable();
+        if (availLevel >= 0) {
+            String exclBindProp =
+                java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedAction<String>() {
+                        public String run() {
+                            return System.getProperty(
+                                    "sun.net.useExclusiveBind");
+                        }
+                    });
+            if (exclBindProp != null) {
+                exclusiveBind = exclBindProp.length() == 0 ?
+                        true : Boolean.parseBoolean(exclBindProp);
+            } else if (availLevel == 1) {
+                exclusiveBind = true;
+            } else {
+                exclusiveBind = false;
+            }
+        } else {
+            exclusiveBind = false;
+        }
+    }
+
     // -- Miscellaneous utilities --
 
+    /**
+     * Returns true if exclusive binding is on
+     */
+    static boolean useExclusiveBind() {
+        return exclusiveBind;
+    }
+
     static InetSocketAddress checkAddress(SocketAddress sa) {
         if (sa == null)
             throw new IllegalArgumentException();
@@ -119,10 +153,21 @@
         return IOUtil.newFD(socket0(stream, true));
     }
 
+    /*
+     * Returns 1 for Windows versions that support exclusive binding by default, 0
+     * for those that do not, and -1 for Solaris/Linux/Mac OS
+     */
+    private static native int isExclusiveBindAvailable();
+
     // Due to oddities SO_REUSEADDR on windows reuse is ignored
     private static native int socket0(boolean stream, boolean reuse);
 
-    static native void bind(FileDescriptor fd, InetAddress addr, int port)
+    static void bind(FileDescriptor fd, InetAddress addr, int port)
+        throws IOException {
+        bind0(fd, exclusiveBind, addr, port);
+    }
+
+    private static native void bind0(FileDescriptor fd, boolean useExclBind, InetAddress addr, int port)
         throws IOException;
 
     static native int connect(FileDescriptor fd,
diff --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
--- openjdk/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
+++ openjdk/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
@@ -207,6 +207,10 @@
                             void setInt(int opt, int arg) throws IOException {
                                 Net.setIntOption(fd, opt, arg);
                             }
+                            boolean getIsBoundCondition() {
+                                // always return true
+                                return true;
+                            }
                         };
                 options = new SocketOptsImpl.IP.TCP(d);
             }
diff --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java
--- openjdk/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java
+++ openjdk/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java
@@ -423,6 +423,11 @@
                             {
                                 Net.setIntOption(fd, opt, arg);
                             }
+                            boolean getIsBoundCondition()
+                            {
+                                // always return true
+                                return true;
+                            }
                         };
                 options = new SocketOptsImpl.IP.TCP(d);
             }
diff --git a/src/share/classes/sun/nio/ch/SocketOptsImpl.java b/src/share/classes/sun/nio/ch/SocketOptsImpl.java
--- openjdk/jdk/src/share/classes/sun/nio/ch/SocketOptsImpl.java
+++ openjdk/jdk/src/share/classes/sun/nio/ch/SocketOptsImpl.java
@@ -35,10 +35,17 @@
 class SocketOptsImpl
     implements SocketOpts
 {
+    // set true when socket is bound and SO_REUSEADDRESS is emulated
+    private boolean reuseAddressEmulated;
+
+    // set true/false when socket is already bound and SO_REUSEADDR is emulated
+    private boolean isReuseAddress;
 
     static abstract class Dispatcher {
         abstract int getInt(int opt) throws IOException;
         abstract void setInt(int opt, int arg) throws IOException;
+        // Only used meaningfully by DatagramChannelImpl
+        abstract boolean getIsBoundCondition();
         // Others that pass addresses, etc., will come later
     }
 
@@ -167,11 +174,21 @@
     // SO_REUSEADDR
 
     public boolean reuseAddress() throws IOException {
+        if (reuseAddressEmulated) {
+            return isReuseAddress;
+        }
+        // no special handling
         return getBoolean(SocketOptions.SO_REUSEADDR);
     }
 
     public SocketOpts reuseAddress(boolean b) throws IOException {
-        setBoolean(SocketOptions.SO_REUSEADDR, b);
+        if ( Net.useExclusiveBind() && d.getIsBoundCondition() ) {
+            reuseAddressEmulated = true;
+            this.isReuseAddress = b;
+        } else {
+            // no special handling
+            setBoolean(SocketOptions.SO_REUSEADDR, b);
+        }
         return this;
     }
 
diff --git a/src/solaris/native/sun/nio/ch/Net.c b/src/solaris/native/sun/nio/ch/Net.c
--- openjdk/jdk/src/solaris/native/sun/nio/ch/Net.c
+++ openjdk/jdk/src/solaris/native/sun/nio/ch/Net.c
@@ -55,6 +55,11 @@
     /* Here because Windows native code does need to init IDs */
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
+    return -1;
+}
+
 JNIEXPORT int JNICALL
 Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean stream,
                             jboolean reuse)
@@ -84,8 +89,8 @@
 }
 
 JNIEXPORT void JNICALL
-Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */
-                         jobject fdo, jobject ia, int port)
+Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz, /* ## Needs rest of PSI gunk */
+                         jobject fdo, jboolean exclBind, jobject ia, int port)
 {
     SOCKADDR sa;
     int sa_len = SOCKADDR_LEN;
diff --git a/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java b/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java
--- openjdk/jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java
+++ openjdk/jdk/src/windows/classes/java/net/DefaultDatagramSocketImplFactory.java
@@ -56,24 +56,45 @@
     /* If the version supports a dual stack TCP implementation */
     private static boolean useDualStackImpl = false;
 
+    /* sun.net.useExclusiveBind */
+    private static String exclBindProp;
+
+    /* True if exclusive binding is on for Windows */
+    private static boolean exclusiveBind = true;
+
+
     static {
         // Determine Windows Version.
-        java.security.AccessController.doPrivileged( new PrivilegedAction<Object>() {
-                public Object run() {
-                    version = 0;
-                    try {
-                        version = Float.parseFloat(System.getProperties().getProperty("os.version"));
-                        preferIPv4Stack = Boolean.parseBoolean(
-                                          System.getProperties().getProperty("java.net.preferIPv4Stack"));
-                    } catch (NumberFormatException e ) {
-                        assert false : e;
+        java.security.AccessController.doPrivileged(
+                new PrivilegedAction<Object>() {
+                    public Object run() {
+                        version = 0;
+                        try {
+                            version = Float.parseFloat(System.getProperties()
+                                    .getProperty("os.version"));
+                            preferIPv4Stack = Boolean.parseBoolean(
+                                              System.getProperties()
+                                              .getProperty(
+                                                   "java.net.preferIPv4Stack"));
+                            exclBindProp = System.getProperty(
+                                    "sun.net.useExclusiveBind");
+                        } catch (NumberFormatException e ) {
+                            assert false : e;
+                        }
+                        return null; // nothing to return
                     }
-                    return null; // nothing to return
-                } });
+                });
 
         // (version >= 6.0) implies Vista or greater.
         if (version >= 6.0 && !preferIPv4Stack) {
-            useDualStackImpl = true;
+                useDualStackImpl = true;
+        }
+        if (exclBindProp != null) {
+            // sun.net.useExclusiveBind is true
+            exclusiveBind = exclBindProp.length() == 0 ? true
+                    : Boolean.parseBoolean(exclBindProp);
+        } else if (version < 6.0) {
+            exclusiveBind = false;
         }
 
         // impl.prefix
@@ -105,10 +126,12 @@
                 throw new SocketException("can't instantiate DatagramSocketImpl");
             }
         } else {
+            if (isMulticast)
+                exclusiveBind = false;
             if (useDualStackImpl && !isMulticast)
-                return new DualStackPlainDatagramSocketImpl();
+                return new DualStackPlainDatagramSocketImpl(exclusiveBind);
             else
-                return new TwoStacksPlainDatagramSocketImpl();
+                return new TwoStacksPlainDatagramSocketImpl(exclusiveBind);
         }
     }
 }
diff --git a/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java
--- openjdk/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java
+++ openjdk/jdk/src/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java
@@ -46,6 +46,22 @@
 {
     static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
 
+    // true if this socket is exclusively bound
+    private final boolean exclusiveBind;
+
+    /*
+     * Set to true if SO_REUSEADDR is set after the socket is bound to
+     * indicate SO_REUSEADDR is being emulated
+     */
+    private boolean reuseAddressEmulated;
+
+    // emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
+    private boolean isReuseAddress;
+
+    DualStackPlainDatagramSocketImpl(boolean exclBind) {
+        exclusiveBind = exclBind;
+    }
+
     protected void datagramSocketCreate() throws SocketException {
         if (fd == null)
             throw new SocketException("Socket closed");
@@ -62,7 +78,7 @@
         if (laddr == null)
             throw new NullPointerException("argument address");
 
-        socketBind(nativefd, laddr, lport);
+        socketBind(nativefd, laddr, lport, exclusiveBind);
         if (lport == 0) {
             localPort = socketLocalPort(nativefd);
         } else {
@@ -142,6 +158,7 @@
         fdAccess.set(fd, -1);
     }
 
+    @SuppressWarnings("fallthrough")
     protected void socketSetOption(int opt, Object val) throws SocketException {
         int nativefd = checkAndReturnNativeFD();
 
@@ -154,6 +171,13 @@
                 optionValue = ((Integer)val).intValue();
                 break;
             case SO_REUSEADDR :
+                if (exclusiveBind && localPort != 0)  {
+                    // socket already bound, emulate SO_REUSEADDR
+                    reuseAddressEmulated = true;
+                    isReuseAddress = (Boolean)val;
+                    return;
+                }
+                //Intentional fallthrough
             case SO_BROADCAST :
                 optionValue = ((Boolean)val).booleanValue() ? 1 : 0;
                 break;
@@ -171,6 +195,8 @@
         if (opt == SO_BINDADDR) {
             return socketLocalAddress(nativefd);
         }
+        if (opt == SO_REUSEADDR && reuseAddressEmulated)
+            return isReuseAddress;
 
         int value = socketGetIntOption(nativefd, opt);
         Object returnValue = null;
@@ -238,8 +264,8 @@
 
     private static native int socketCreate(boolean v6Only);
 
-    private static native void socketBind(int fd, InetAddress localAddress, int localport)
-        throws SocketException;
+    private static native void socketBind(int fd, InetAddress localAddress,
+            int localport, boolean exclBind) throws SocketException;
 
     private static native void socketConnect(int fd, InetAddress address, int port)
         throws SocketException;
diff --git a/src/windows/classes/java/net/DualStackPlainSocketImpl.java b/src/windows/classes/java/net/DualStackPlainSocketImpl.java
--- openjdk/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java
+++ openjdk/jdk/src/windows/classes/java/net/DualStackPlainSocketImpl.java
@@ -42,10 +42,20 @@
 {
     static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
 
-    public DualStackPlainSocketImpl() {}
 
-    public DualStackPlainSocketImpl(FileDescriptor fd) {
+    // true if this socket is exclusively bound
+    private final boolean exclusiveBind;
+
+    // emulates SO_REUSEADDR when exclusiveBind is true
+    private boolean isReuseAddress;
+
+    public DualStackPlainSocketImpl(boolean exclBind) {
+        exclusiveBind = exclBind;
+    }
+
+    public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
         this.fd = fd;
+        exclusiveBind = exclBind;
     }
 
     void socketCreate(boolean stream) throws IOException {
@@ -93,7 +103,7 @@
         if (address == null)
             throw new NullPointerException("inet address argument is null.");
 
-        bind0(nativefd, address, port);
+        bind0(nativefd, address, port, exclusiveBind);
         if (port == 0) {
             localport = localPort0(nativefd);
         } else {
@@ -161,6 +171,8 @@
         shutdown0(nativefd, howto);
     }
 
+    // Intentional fallthrough after SO_REUSEADDR
+    @SuppressWarnings("fallthrough")
     void socketSetOption(int opt, boolean on, Object value)
         throws SocketException {
         int nativefd = checkAndReturnNativeFD();
@@ -174,8 +186,13 @@
         switch(opt) {
             case TCP_NODELAY :
             case SO_OOBINLINE :
+            case SO_REUSEADDR :
+                if (exclusiveBind) {
+                    // SO_REUSEADDR emulated when using exclusive bind
+                    isReuseAddress = on;
+                    return;
+                }
             case SO_KEEPALIVE :
-            case SO_REUSEADDR :
                 optionValue = on ? 1 : 0;
                 break;
             case SO_SNDBUF :
@@ -206,6 +223,10 @@
             return 0;  // return value doesn't matter.
         }
 
+        // SO_REUSEADDR emulated when using exclusive bind
+        if (opt == SO_REUSEADDR && exclusiveBind)
+            return isReuseAddress? 1 : -1;
+
         int value = getIntOption(nativefd, opt);
 
         switch (opt) {
@@ -245,7 +266,8 @@
 
     static native int socket0(boolean stream, boolean v6Only) throws IOException;
 
-    static native void bind0(int fd, InetAddress localAddress, int localport)
+    static native void bind0(int fd, InetAddress localAddress, int localport,
+                             boolean exclBind)
         throws IOException;
 
     static native int connect0(int fd, InetAddress remote, int remotePort)
diff --git a/src/windows/classes/java/net/PlainSocketImpl.java b/src/windows/classes/java/net/PlainSocketImpl.java
--- openjdk/jdk/src/windows/classes/java/net/PlainSocketImpl.java
+++ openjdk/jdk/src/windows/classes/java/net/PlainSocketImpl.java
@@ -54,6 +54,12 @@
     /* If the version supports a dual stack TCP implementation */
     private static boolean useDualStackImpl = false;
 
+    /* sun.net.useExclusiveBind */
+    private static String exclBindProp;
+
+    /* True if exclusive binding is on for Windows */
+    private static boolean exclusiveBind = true;
+
     static {
         java.security.AccessController.doPrivileged( new PrivilegedAction<Object>() {
                 public Object run() {
@@ -62,6 +68,7 @@
                         version = Float.parseFloat(System.getProperties().getProperty("os.version"));
                         preferIPv4Stack = Boolean.parseBoolean(
                                           System.getProperties().getProperty("java.net.preferIPv4Stack"));
+                        exclBindProp = System.getProperty("sun.net.useExclusiveBind");
                     } catch (NumberFormatException e ) {
                         assert false : e;
                     }
@@ -70,7 +77,15 @@
 
         // (version >= 6.0) implies Vista or greater.
         if (version >= 6.0 && !preferIPv4Stack) {
-            useDualStackImpl = true;
+                useDualStackImpl = true;
+        }
+
+        if (exclBindProp != null) {
+            // sun.net.useExclusiveBind is true
+            exclusiveBind = exclBindProp.length() == 0 ? true
+                    : Boolean.parseBoolean(exclBindProp);
+        } else if (version < 6.0) {
+            exclusiveBind = false;
         }
     }
 
@@ -79,9 +94,9 @@
      */
     PlainSocketImpl() {
         if (useDualStackImpl) {
-            impl = new DualStackPlainSocketImpl();
+            impl = new DualStackPlainSocketImpl(exclusiveBind);
         } else {
-            impl = new TwoStacksPlainSocketImpl();
+            impl = new TwoStacksPlainSocketImpl(exclusiveBind);
         }
     }
 
@@ -90,9 +105,9 @@
      */
     PlainSocketImpl(FileDescriptor fd) {
         if (useDualStackImpl) {
-            impl = new DualStackPlainSocketImpl(fd);
+            impl = new DualStackPlainSocketImpl(fd, exclusiveBind);
         } else {
-            impl = new TwoStacksPlainSocketImpl(fd);
+            impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind);
         }
     }
 
diff --git a/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
--- openjdk/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
+++ openjdk/jdk/src/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
@@ -66,6 +66,22 @@
         init();
     }
 
+    // true if this socket is exclusively bound
+    private final boolean exclusiveBind;
+
+    /*
+     * Set to true if SO_REUSEADDR is set after the socket is bound to
+     * indicate SO_REUSEADDR is being emulated
+     */
+    private boolean reuseAddressEmulated;
+
+    // emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
+    private boolean isReuseAddress;
+
+    TwoStacksPlainDatagramSocketImpl(boolean exclBind) {
+        exclusiveBind = exclBind;
+    }
+
     protected synchronized void create() throws SocketException {
         fd1 = new FileDescriptor();
         super.create();
@@ -79,6 +95,14 @@
         }
     }
 
+    @Override
+    protected synchronized void bind0(int lport, InetAddress laddr)
+        throws SocketException
+    {
+        bind0(lport, laddr, exclusiveBind);
+
+    }
+
     protected synchronized void receive(DatagramPacket p)
         throws IOException {
         try {
@@ -98,8 +122,24 @@
                 return anyLocalBoundAddr;
             }
             return socketGetOption(optID);
-        } else
+        } else if (optID == SO_REUSEADDR && reuseAddressEmulated) {
+            return isReuseAddress;
+        } else {
             return super.getOption(optID);
+        }
+    }
+
+    protected void socketSetOption(int opt, Object val)
+        throws SocketException
+    {
+        if (opt == SO_REUSEADDR && exclusiveBind && localPort != 0)  {
+            // socket already bound, emulate
+            reuseAddressEmulated = true;
+            isReuseAddress = (Boolean)val;
+        } else {
+            socketNativeSetOption(opt, val);
+        }
+
     }
 
     protected boolean isClosed() {
@@ -117,7 +157,8 @@
 
     /* Native methods */
 
-    protected synchronized native void bind0(int lport, InetAddress laddr)
+    protected synchronized native void bind0(int lport, InetAddress laddr,
+                                             boolean exclBind)
         throws SocketException;
 
     protected native void send(DatagramPacket p) throws IOException;
@@ -147,7 +188,7 @@
 
     protected native void datagramSocketClose();
 
-    protected native void socketSetOption(int opt, Object val)
+    protected native void socketNativeSetOption(int opt, Object val)
         throws SocketException;
 
     protected native Object socketGetOption(int opt) throws SocketException;
diff --git a/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java b/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java
--- openjdk/jdk/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java
+++ openjdk/jdk/src/windows/classes/java/net/TwoStacksPlainSocketImpl.java
@@ -65,14 +65,23 @@
      */
     private int lastfd = -1;
 
+    // true if this socket is exclusively bound
+    private final boolean exclusiveBind;
+
+    // emulates SO_REUSEADDR when exclusiveBind is true
+    private boolean isReuseAddress;
+
     static {
         initProto();
     }
 
-    public TwoStacksPlainSocketImpl() {}
+    public TwoStacksPlainSocketImpl(boolean exclBind) {
+        exclusiveBind = exclBind;
+    }
 
-    public TwoStacksPlainSocketImpl(FileDescriptor fd) {
+    public TwoStacksPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
         this.fd = fd;
+        exclusiveBind = exclBind;
     }
 
     /**
@@ -110,13 +119,33 @@
             InetAddressContainer in = new InetAddressContainer();
             socketGetOption(opt, in);
             return in.addr;
+        } else if (opt == SO_REUSEADDR && exclusiveBind) {
+            // SO_REUSEADDR emulated when using exclusive bind
+            return isReuseAddress;
         } else
             return super.getOption(opt);
     }
 
+    @Override
+    void socketBind(InetAddress address, int port) throws IOException {
+        socketBind(address, port, exclusiveBind);
+    }
+
+    @Override
+    void socketSetOption(int opt, boolean on, Object value)
+        throws SocketException
+    {
+        // SO_REUSEADDR emulated when using exclusive bind
+        if (opt == SO_REUSEADDR && exclusiveBind)
+            isReuseAddress = on;
+        else
+            socketNativeSetOption(opt, on, value);
+    }
+
     /**
      * Closes the socket.
      */
+    @Override
     protected void close() throws IOException {
         synchronized(fdLock) {
             if (fd != null || fd1 != null) {
@@ -146,6 +175,7 @@
         }
     }
 
+    @Override
     void reset() throws IOException {
         if (fd != null || fd1 != null) {
             socketClose();
@@ -158,6 +188,7 @@
     /*
      * Return true if already closed or close is pending
      */
+    @Override
     public boolean isClosedOrPending() {
         /*
          * Lock on fdLock to ensure that we wait if a
@@ -181,7 +212,7 @@
     native void socketConnect(InetAddress address, int port, int timeout)
         throws IOException;
 
-    native void socketBind(InetAddress address, int port)
+    native void socketBind(InetAddress address, int port, boolean exclBind)
         throws IOException;
 
     native void socketListen(int count) throws IOException;
@@ -194,7 +225,7 @@
 
     native void socketShutdown(int howto) throws IOException;
 
-    native void socketSetOption(int cmd, boolean on, Object value)
+    native void socketNativeSetOption(int cmd, boolean on, Object value)
         throws SocketException;
 
     native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
diff --git a/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c b/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c
--- openjdk/jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c
+++ openjdk/jdk/src/windows/native/java/net/DualStackPlainDatagramSocketImpl.c
@@ -112,7 +112,7 @@
  * Signature: (ILjava/net/InetAddress;I)V
  */
 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketBind
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
+  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port, jboolean exclBind) {
     SOCKETADDRESS sa;
     int rv;
     int sa_len = sizeof(sa);
@@ -121,8 +121,7 @@
                                  &sa_len, JNI_TRUE) != 0) {
         return;
     }
-
-    rv = bind(fd, (struct sockaddr *)&sa, sa_len);
+    rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
 
     if (rv == SOCKET_ERROR) {
         if (WSAGetLastError() == WSAEACCES) {
diff --git a/src/windows/native/java/net/DualStackPlainSocketImpl.c b/src/windows/native/java/net/DualStackPlainSocketImpl.c
--- openjdk/jdk/src/windows/native/java/net/DualStackPlainSocketImpl.c
+++ openjdk/jdk/src/windows/native/java/net/DualStackPlainSocketImpl.c
@@ -82,7 +82,9 @@
  * Signature: (ILjava/net/InetAddress;I)V
  */
 JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
+  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
+   jboolean exclBind)
+{
     SOCKETADDRESS sa;
     int rv;
     int sa_len = sizeof(sa);
@@ -92,7 +94,7 @@
       return;
     }
 
-    rv = NET_Bind(fd, (struct sockaddr *)&sa, sa_len);
+    rv = NET_WinBind(fd, (struct sockaddr *)&sa, sa_len, exclBind);
 
     if (rv == SOCKET_ERROR)
         NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind");
diff --git a/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c
--- openjdk/jdk/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c
+++ openjdk/jdk/src/windows/native/java/net/TwoStacksPlainDatagramSocketImpl.c
@@ -421,7 +421,8 @@
 
 JNIEXPORT void JNICALL
 Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this,
-                                           jint port, jobject addressObj) {
+                                           jint port, jobject addressObj,
+                                           jboolean exclBind) {
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     jobject fd1Obj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
 
@@ -464,7 +465,7 @@
         v6bind.addr = &lcladdr;
         v6bind.ipv4_fd = fd;
         v6bind.ipv6_fd = fd1;
-        if (NET_BindV6(&v6bind) != -1) {
+        if (NET_BindV6(&v6bind, exclBind) != -1) {
             /* check if the fds have changed */
             if (v6bind.ipv4_fd != fd) {
                 fd = v6bind.ipv4_fd;
@@ -491,7 +492,7 @@
             return;
         }
     } else {
-        if (bind(fd, (struct sockaddr *)&lcladdr, lcladdrlen) == -1) {
+        if (NET_WinBind(fd, (struct sockaddr *)&lcladdr, lcladdrlen, exclBind) == -1) {
             if (WSAGetLastError() == WSAEACCES) {
                 WSASetLastError(WSAEADDRINUSE);
             }
@@ -1780,11 +1781,11 @@
 
 /*
  * Class:     java_net_TwoStacksPlainDatagramSocketImpl
- * Method:    socketSetOption
+ * Method:    socketNativeSetOption
  * Signature: (ILjava/lang/Object;)V
  */
 JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainDatagramSocketImpl_socketSetOption(JNIEnv *env,jobject this,
+Java_java_net_TwoStacksPlainDatagramSocketImpl_socketNativeSetOption(JNIEnv *env,jobject this,
                                                       jint opt,jobject value) {
 
     int fd=-1, fd1=-1;
diff --git a/src/windows/native/java/net/TwoStacksPlainSocketImpl.c b/src/windows/native/java/net/TwoStacksPlainSocketImpl.c
--- openjdk/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c
+++ openjdk/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c
@@ -393,7 +393,8 @@
  */
 JNIEXPORT void JNICALL
 Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this,
-                                         jobject iaObj, jint localport) {
+                                         jobject iaObj, jint localport,
+                                         jboolean exclBind) {
 
     /* fdObj is the FileDescriptor field on this */
     jobject fdObj, fd1Obj;
@@ -437,13 +438,12 @@
                           (struct sockaddr *)&him, &len, JNI_FALSE) != 0) {
       return;
     }
-
     if (ipv6_supported) {
         struct ipv6bind v6bind;
         v6bind.addr = &him;
         v6bind.ipv4_fd = fd;
         v6bind.ipv6_fd = fd1;
-        rv = NET_BindV6(&v6bind);
+        rv = NET_BindV6(&v6bind, exclBind);
         if (rv != -1) {
             /* check if the fds have changed */
             if (v6bind.ipv4_fd != fd) {
@@ -468,7 +468,7 @@
             }
         }
     } else {
-        rv = NET_Bind(fd, (struct sockaddr *)&him, len);
+        rv = NET_WinBind(fd, (struct sockaddr *)&him, len, exclBind);
     }
 
     if (rv == -1) {
@@ -829,11 +829,12 @@
  *
  *
  * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    socketSetOption
+ * Method:    socketNativeSetOption
  * Signature: (IZLjava/lang/Object;)V
  */
 JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_socketSetOption(JNIEnv *env, jobject this,
+Java_java_net_TwoStacksPlainSocketImpl_socketNativeSetOption(JNIEnv *env,
+                                              jobject this,
                                               jint cmd, jboolean on,
                                               jobject value) {
     int fd, fd1;
diff --git a/src/windows/native/java/net/net_util_md.c b/src/windows/native/java/net/net_util_md.c
--- openjdk/jdk/src/windows/native/java/net/net_util_md.c
+++ openjdk/jdk/src/windows/native/java/net/net_util_md.c
@@ -415,12 +415,24 @@
                int optlen)
 {
     int rv;
+    int parg;
+    int plen = sizeof(parg);
 
     if (level == IPPROTO_IP && optname == IP_TOS) {
         int *tos = (int *)optval;
         *tos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK);
     }
 
+    if (optname == SO_REUSEADDR) {
+        /*
+         * Do not set SO_REUSEADDE if SO_EXCLUSIVEADDUSE is already set
+         */
+        rv = NET_GetSockOpt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&parg, &plen);
+        if (rv == 0 && parg == 1) {
+            return rv;
+        }
+    }
+
     rv = setsockopt(s, level, optname, optval, optlen);
 
     if (rv == SOCKET_ERROR) {
@@ -484,15 +496,32 @@
 }
 
 /*
+ * Sets SO_ECLUSIVEADDRUSE if SO_REUSEADDR is not already set.
+ */
+void setExclusiveBind(int fd) {
+    int parg;
+    int plen = sizeof(parg);
+    int rv = 0;
+    rv = NET_GetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&parg, &plen);
+    if (rv == 0 && parg == 0) {
+        parg = 1;
+        rv = NET_SetSockOpt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&parg, plen);
+    }
+}
+
+/*
  * Wrapper for bind winsock call - transparent converts an
  * error related to binding to a port that has exclusive access
  * into an error indicating the port is in use (facilitates
  * better error reporting).
+ *
+ * Should be only called by the wrapper method NET_WinBind
  */
 JNIEXPORT int JNICALL
 NET_Bind(int s, struct sockaddr *him, int len)
 {
-    int rv = bind(s, him, len);
+    int rv;
+    rv = bind(s, him, len);
 
     if (rv == SOCKET_ERROR) {
         /*
@@ -507,6 +536,18 @@
     return rv;
 }
 
+/*
+ * Wrapper for NET_Bind call. Sets SO_EXCLUSIVEADDRUSE
+ * if required, and then calls NET_BIND
+ */
+JNIEXPORT int JNICALL
+NET_WinBind(int s, struct sockaddr *him, int len, jboolean exclBind)
+{
+    if (exclBind == JNI_TRUE)
+        setExclusiveBind(s);
+    return NET_Bind(s, him, len);
+}
+
 JNIEXPORT int JNICALL
 NET_SocketClose(int fd) {
     struct linger l;
@@ -653,7 +694,7 @@
  */
 
 JNIEXPORT int JNICALL
-NET_BindV6(struct ipv6bind* b) {
+NET_BindV6(struct ipv6bind* b, jboolean exclBind) {
     int fd=-1, ofd=-1, rv, len;
     /* need to defer close until new sockets created */
     int close_fd=-1, close_ofd=-1;
@@ -666,8 +707,8 @@
     if (family == AF_INET && (b->addr->him4.sin_addr.s_addr != INADDR_ANY)) {
         /* bind to v4 only */
         int ret;
-        ret = NET_Bind (b->ipv4_fd, (struct sockaddr *)b->addr,
-                                sizeof (struct sockaddr_in));
+        ret = NET_WinBind (b->ipv4_fd, (struct sockaddr *)b->addr,
+                                sizeof (struct sockaddr_in), exclBind);
         if (ret == SOCKET_ERROR) {
             CLOSE_SOCKETS_AND_RETURN;
         }
@@ -678,8 +719,8 @@
     if (family == AF_INET6 && (!IN6_IS_ADDR_ANY(&b->addr->him6.sin6_addr))) {
         /* bind to v6 only */
         int ret;
-        ret = NET_Bind (b->ipv6_fd, (struct sockaddr *)b->addr,
-                                sizeof (struct SOCKADDR_IN6));
+        ret = NET_WinBind (b->ipv6_fd, (struct sockaddr *)b->addr,
+                                sizeof (struct SOCKADDR_IN6), exclBind);
         if (ret == SOCKET_ERROR) {
             CLOSE_SOCKETS_AND_RETURN;
         }
@@ -708,7 +749,7 @@
         oaddr.him4.sin_addr.s_addr = INADDR_ANY;
     }
 
-    rv = NET_Bind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr));
+    rv = NET_WinBind(fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr), exclBind);
     if (rv == SOCKET_ERROR) {
         CLOSE_SOCKETS_AND_RETURN;
     }
@@ -720,8 +761,8 @@
     }
     bound_port = GET_PORT (b->addr);
     SET_PORT (&oaddr, bound_port);
-    if ((rv=NET_Bind (ofd, (struct sockaddr *) &oaddr,
-                                SOCKETADDRESS_LEN (&oaddr))) == SOCKET_ERROR) {
+    if ((rv=NET_WinBind (ofd, (struct sockaddr *) &oaddr,
+                         SOCKETADDRESS_LEN (&oaddr), exclBind)) == SOCKET_ERROR) {
         int retries;
         int sotype, arglen=sizeof(sotype);
 
@@ -757,7 +798,8 @@
 
             /* bind random port on first socket */
             SET_PORT (&oaddr, 0);
-            rv = NET_Bind (ofd, (struct sockaddr *)&oaddr, SOCKETADDRESS_LEN(&oaddr));
+            rv = NET_WinBind (ofd, (struct sockaddr *)&oaddr, SOCKETADDRESS_LEN(&oaddr),
+                              exclBind);
             if (rv == SOCKET_ERROR) {
                 CLOSE_SOCKETS_AND_RETURN;
             }
@@ -773,7 +815,8 @@
             }
             bound_port = GET_PORT (&oaddr);
             SET_PORT (b->addr, bound_port);
-            rv = NET_Bind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr));
+            rv = NET_WinBind (fd, (struct sockaddr *)b->addr, SOCKETADDRESS_LEN(b->addr),
+                              exclBind);
 
             if (rv != SOCKET_ERROR) {
                 if (family == AF_INET) {
diff --git a/src/windows/native/java/net/net_util_md.h b/src/windows/native/java/net/net_util_md.h
--- openjdk/jdk/src/windows/native/java/net/net_util_md.h
+++ openjdk/jdk/src/windows/native/java/net/net_util_md.h
@@ -307,7 +307,7 @@
  */
 JNIEXPORT int JNICALL NET_Timeout2(int fd, int fd1, long timeout, int *fdret);
 
-JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind* b);
+JNIEXPORT int JNICALL NET_BindV6(struct ipv6bind* b, jboolean exclBind);
 
 #define NET_WAIT_READ   0x01
 #define NET_WAIT_WRITE  0x02
@@ -315,6 +315,9 @@
 
 extern jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
 
+JNIEXPORT int JNICALL NET_WinBind(int s, struct sockaddr *him, int len,
+                                   jboolean exclBind);
+
 /* XP versions of the native routines */
 
 JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByName0_XP
diff --git a/src/windows/native/sun/nio/ch/Net.c b/src/windows/native/sun/nio/ch/Net.c
--- openjdk/jdk/src/windows/native/sun/nio/ch/Net.c
+++ openjdk/jdk/src/windows/native/sun/nio/ch/Net.c
@@ -72,9 +72,20 @@
     return (jint)s;
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
+    OSVERSIONINFO ver;
+    int version;
+    ver.dwOSVersionInfoSize = sizeof(ver);
+    GetVersionEx(&ver);
+    version = ver.dwMajorVersion * 10 + ver.dwMinorVersion;
+    //if os <= xp exclusive binding is off by default
+    return version >= 60 ? 1 : 0;
+}
+
 JNIEXPORT void JNICALL
-Java_sun_nio_ch_Net_bind(JNIEnv *env, jclass clazz,
-                         jobject fdo, jobject iao, jint port)
+Java_sun_nio_ch_Net_bind0(JNIEnv *env, jclass clazz,
+                         jobject fdo, jboolean exclBind, jobject iao, jint port)
 {
     SOCKETADDRESS sa;
     int rv;
@@ -84,7 +95,7 @@
       return;
     }
 
-    rv = NET_Bind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len);
+    rv = NET_WinBind(fdval(env, fdo), (struct sockaddr *)&sa, sa_len, isExclBind);
     if (rv == SOCKET_ERROR)
         NET_ThrowNew(env, WSAGetLastError(), "bind");
 }
@@ -152,7 +163,6 @@
     return iao;
 }
 
-
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz,
                                   jobject fdo, jint opt)