changeset 4893:5dd926007336

8001318: Socket.getLocalAddress not consistent with InetAddress.getLocalHost Reviewed-by: alanb, chegar, hawtin
author khazra
date Thu, 28 Mar 2013 14:59:22 -0700
parents c87f9d33fde6
children a68d49b9b053
files src/share/classes/java/net/NetUtil.java src/share/classes/java/net/ServerSocket.java src/share/classes/java/net/Socket.java src/share/classes/java/net/SocksSocketImpl.java src/share/classes/sun/net/NetworkClient.java src/share/classes/sun/net/ftp/impl/FtpClient.java src/share/classes/sun/net/httpserver/ServerImpl.java src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java src/share/classes/sun/nio/ch/DatagramChannelImpl.java src/share/classes/sun/nio/ch/Net.java src/share/classes/sun/nio/ch/ServerSocketAdaptor.java src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java src/share/classes/sun/nio/ch/SocketAdaptor.java src/share/classes/sun/nio/ch/SocketChannelImpl.java src/share/classes/sun/rmi/server/Activation.java src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java src/solaris/classes/sun/nio/ch/SctpNet.java src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java
diffstat 20 files changed, 328 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/net/NetUtil.java	Thu Mar 28 14:59:22 2013 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2013, 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.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+
+class NetUtil {
+
+    // Value of jdk.net.revealLocalAddress
+    private static boolean revealLocalAddress;
+
+    // True if jdk.net.revealLocalAddress had been read
+    private static volatile boolean propRevealLocalAddr;
+
+    /*
+     * Returns true if security check on localAddress is disabled
+     */
+    static boolean doRevealLocalAddress() {
+        return propRevealLocalAddr ? revealLocalAddress
+                                     : readRevealLocalAddr();
+
+    }
+
+    private static boolean readRevealLocalAddr() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                revealLocalAddress = Boolean.parseBoolean(
+                      AccessController.doPrivileged(
+                          new PrivilegedExceptionAction<String>() {
+                              @Override
+                              public String run() {
+                                  return System.getProperty(
+                                      "jdk.net.revealLocalAddress");
+                              }
+                          }));
+
+            } catch (Exception e) {
+                //revealLocalAddress is false
+            }
+            propRevealLocalAddr = true;
+        }
+        /*
+         * No security manager, or security check passed or
+         * jdk.net.revealLocalAddress set to true
+         */
+        return revealLocalAddress;
+    }
+
+}
--- a/src/share/classes/java/net/ServerSocket.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/java/net/ServerSocket.java	Thu Mar 28 14:59:22 2013 -0700
@@ -399,7 +399,15 @@
         if (!isBound())
             return null;
         try {
-            return getImpl().getInetAddress();
+            InetAddress in = getImpl().getInetAddress();
+            if (!NetUtil.doRevealLocalAddress()) {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkConnect(in.getHostAddress(), -1);
+            }
+            return in;
+        } catch (SecurityException e) {
+            return InetAddress.getLoopbackAddress();
         } catch (SocketException e) {
             // nothing
             // If we're bound, the impl has been created
@@ -712,13 +720,20 @@
      *
      * @return  a string representation of this socket.
      */
-    public String toString() {
+   public String toString() {
         if (!isBound())
             return "ServerSocket[unbound]";
-        return "ServerSocket[addr=" + impl.getInetAddress() +
-                ",port=" + impl.getPort() +
+        InetAddress in;
+        if (!NetUtil.doRevealLocalAddress() &&
+                System.getSecurityManager() != null)
+        {
+            in = InetAddress.getLoopbackAddress();
+        } else {
+            in = impl.getInetAddress();
+        }
+        return "ServerSocket[addr=" + in +
                 ",localport=" + impl.getLocalPort()  + "]";
-    }
+   }
 
     void setBound() {
         bound = true;
--- a/src/share/classes/java/net/Socket.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/java/net/Socket.java	Thu Mar 28 14:59:22 2013 -0700
@@ -693,9 +693,17 @@
         InetAddress in = null;
         try {
             in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR);
+
+            if (!NetUtil.doRevealLocalAddress()) {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkConnect(in.getHostAddress(), -1);
+            }
             if (in.isAnyLocalAddress()) {
                 in = InetAddress.anyLocalAddress();
             }
+        } catch (SecurityException e) {
+            in = InetAddress.getLoopbackAddress();
         } catch (Exception e) {
             in = InetAddress.anyLocalAddress(); // "0.0.0.0"
         }
--- a/src/share/classes/java/net/SocksSocketImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/java/net/SocksSocketImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -28,6 +28,7 @@
 import java.io.OutputStream;
 import java.io.BufferedOutputStream;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.security.PrivilegedExceptionAction;
 import sun.net.SocksProxy;
 import sun.net.www.ParseUtil;
@@ -590,7 +591,13 @@
         /* Test for AnyLocal */
         InetAddress naddr = baddr;
         if (naddr.isAnyLocalAddress()) {
-            naddr = cmdsock.getLocalAddress();
+            naddr = AccessController.doPrivileged(
+                        new PrivilegedAction<InetAddress>() {
+                            public InetAddress run() {
+                                return cmdsock.getLocalAddress();
+
+                            }
+                        });
             addr1 = naddr.getAddress();
         }
         out.write(PROTO_VERS4);
--- a/src/share/classes/sun/net/NetworkClient.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/net/NetworkClient.java	Thu Mar 28 14:59:22 2013 -0700
@@ -200,7 +200,13 @@
     protected InetAddress getLocalAddress() throws IOException {
         if (serverSocket == null)
             throw new IOException("not connected");
-        return serverSocket.getLocalAddress();
+        return  AccessController.doPrivileged(
+                        new PrivilegedAction<InetAddress>() {
+                            public InetAddress run() {
+                                return serverSocket.getLocalAddress();
+
+                            }
+                        });
     }
 
     /** Close an open connection to the server. */
--- a/src/share/classes/sun/net/ftp/impl/FtpClient.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/net/ftp/impl/FtpClient.java	Thu Mar 28 14:59:22 2013 -0700
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
@@ -76,7 +77,10 @@
     private FtpReplyCode lastReplyCode = null;
     /** Welcome message from the server, if any. */
     private String welcomeMsg;
-    private boolean passiveMode = true;
+    /**
+     * Only passive mode used in JDK. See Bug 8010784.
+     */
+    private final boolean passiveMode = true;
     private TransferType type = TransferType.BINARY;
     private long restartOffset = 0;
     private long lastTransSize = -1; // -1 means 'unknown size'
@@ -645,9 +649,19 @@
         } else {
             s = new Socket();
         }
+
+        InetAddress serverAddress = AccessController.doPrivileged(
+                new PrivilegedAction<InetAddress>() {
+                    @Override
+                    public InetAddress run() {
+                        return server.getLocalAddress();
+                    }
+                });
+
         // Bind the socket to the same address as the control channel. This
         // is needed in case of multi-homed systems.
-        s.bind(new InetSocketAddress(server.getLocalAddress(), 0));
+        s.bind(new InetSocketAddress(serverAddress, 0));
+
         if (connectTimeout >= 0) {
             s.connect(dest, connectTimeout);
         } else {
@@ -816,7 +830,8 @@
      * @see #setActiveMode()
      */
     public sun.net.ftp.FtpClient enablePassiveMode(boolean passive) {
-        passiveMode = passive;
+        // Only passive mode used in JDK. See Bug 8010784.
+        // passiveMode = passive;
         return this;
     }
 
--- a/src/share/classes/sun/net/httpserver/ServerImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/net/httpserver/ServerImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -34,6 +34,8 @@
 import java.util.logging.Level;
 import javax.net.ssl.*;
 import com.sun.net.httpserver.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import sun.net.httpserver.HttpConnection.State;
 
 /**
@@ -244,7 +246,14 @@
     }
 
     public InetSocketAddress getAddress() {
-        return (InetSocketAddress)schan.socket().getLocalSocketAddress();
+        return AccessController.doPrivileged(
+                new PrivilegedAction<InetSocketAddress>() {
+                    public InetSocketAddress run() {
+                        return
+                            (InetSocketAddress)schan.socket()
+                                .getLocalSocketAddress();
+                    }
+                });
     }
 
     Selector getSelector () {
--- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -51,7 +51,7 @@
     protected final FileDescriptor fd;
 
     // the local address to which the channel's socket is bound
-    protected volatile SocketAddress localAddress = null;
+    protected volatile InetSocketAddress localAddress = null;
 
     // need this lock to set local address
     private final Object stateLock = new Object();
@@ -173,7 +173,7 @@
     public final SocketAddress getLocalAddress() throws IOException {
         if (!isOpen())
             throw new ClosedChannelException();
-        return localAddress;
+        return Net.getRevealedLocalAddress(localAddress);
     }
 
     @Override
@@ -251,7 +251,7 @@
             if (localAddress == null) {
                 sb.append("unbound");
             } else {
-                sb.append(localAddress.toString());
+                sb.append(Net.getRevealedLocalAddressAsString(localAddress));
             }
         }
         sb.append(']');
--- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -53,8 +53,8 @@
     // protects state, localAddress, and remoteAddress
     protected final Object stateLock = new Object();
 
-    protected volatile SocketAddress localAddress = null;
-    protected volatile SocketAddress remoteAddress = null;
+    protected volatile InetSocketAddress localAddress = null;
+    protected volatile InetSocketAddress remoteAddress = null;
 
     // State, increases monotonically
     static final int ST_UNINITIALIZED = -1;
@@ -442,7 +442,7 @@
     public final SocketAddress getLocalAddress() throws IOException {
         if (!isOpen())
             throw new ClosedChannelException();
-        return localAddress;
+         return Net.getRevealedLocalAddress(localAddress);
     }
 
     @Override
@@ -582,7 +582,8 @@
                 }
                 if (localAddress != null) {
                     sb.append(" local=");
-                    sb.append(localAddress.toString());
+                    sb.append(
+                            Net.getRevealedLocalAddressAsString(localAddress));
                 }
                 if (remoteAddress != null) {
                     sb.append(" remote=");
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -86,8 +86,8 @@
     private int state = ST_UNINITIALIZED;
 
     // Binding
-    private SocketAddress localAddress;
-    private SocketAddress remoteAddress;
+    private InetSocketAddress localAddress;
+    private InetSocketAddress remoteAddress;
 
     // Our socket adaptor, if any
     private DatagramSocket socket;
@@ -169,7 +169,7 @@
         synchronized (stateLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            return localAddress;
+            return Net.getRevealedLocalAddress(localAddress);
         }
     }
 
@@ -710,6 +710,7 @@
         }
     }
 
+    @Override
     public DatagramChannel connect(SocketAddress sa) throws IOException {
         int localPort = 0;
 
@@ -731,7 +732,7 @@
 
                     // Connection succeeded; disallow further invocation
                     state = ST_CONNECTED;
-                    remoteAddress = sa;
+                    remoteAddress = isa;
                     sender = isa;
                     cachedSenderInetAddress = isa.getAddress();
                     cachedSenderPort = isa.getPort();
@@ -750,7 +751,7 @@
                 synchronized (stateLock) {
                     if (!isConnected() || !isOpen())
                         return this;
-                    InetSocketAddress isa = (InetSocketAddress)remoteAddress;
+                    InetSocketAddress isa = remoteAddress;
                     SecurityManager sm = System.getSecurityManager();
                     if (sm != null)
                         sm.checkConnect(isa.getAddress().getHostAddress(),
--- a/src/share/classes/sun/nio/ch/Net.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/Net.java	Thu Mar 28 14:59:22 2013 -0700
@@ -31,6 +31,7 @@
 import java.util.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
 
 
 class Net {                                             // package-private
@@ -44,6 +45,12 @@
         }
     };
 
+    // Value of jdk.net.revealLocalAddress
+    private static boolean revealLocalAddress;
+
+    // True if jdk.net.revealLocalAddress had been read
+    private static volatile boolean propRevealLocalAddress;
+
     // set to true if exclusive binding is on for Windows
     private static final boolean exclusiveBind;
 
@@ -52,8 +59,8 @@
         if (availLevel >= 0) {
             String exclBindProp =
                 java.security.AccessController.doPrivileged(
-                    new PrivilegedAction<String>() {
-                        @Override
+                      new PrivilegedAction<String>() {
+                          @Override
                         public String run() {
                             return System.getProperty(
                                     "sun.net.useExclusiveBind");
@@ -183,6 +190,58 @@
     }
 
     /**
+     * Returns the local address after performing a SecurityManager#checkConnect.
+     */
+    static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) {
+        SecurityManager sm = System.getSecurityManager();
+        if (addr == null || sm == null)
+            return addr;
+
+        if (!getRevealLocalAddress()) {
+            // Return loopback address only if security check fails
+            try{
+                sm.checkConnect(addr.getAddress().getHostAddress(), -1);
+                //Security check passed
+            } catch (SecurityException e) {
+                //Return loopback address
+                addr = getLoopbackAddress(addr.getPort());
+            }
+        }
+        return addr;
+    }
+
+    static String getRevealedLocalAddressAsString(InetSocketAddress addr) {
+        if (!getRevealLocalAddress() && System.getSecurityManager() != null)
+            addr = getLoopbackAddress(addr.getPort());
+        return addr.toString();
+    }
+
+    private static boolean getRevealLocalAddress() {
+        if (!propRevealLocalAddress) {
+            try {
+                revealLocalAddress = Boolean.parseBoolean(
+                      AccessController.doPrivileged(
+                          new PrivilegedExceptionAction<String>() {
+                              public String run() {
+                                  return System.getProperty(
+                                      "jdk.net.revealLocalAddress");
+                              }
+                          }));
+
+            } catch (Exception e) {
+                // revealLocalAddress is false
+            }
+            propRevealLocalAddress = true;
+        }
+        return revealLocalAddress;
+    }
+
+    private static InetSocketAddress getLoopbackAddress(int port) {
+        return new InetSocketAddress(InetAddress.getLoopbackAddress(),
+                                     port);
+    }
+
+    /**
      * Returns any IPv4 address of the given network interface, or
      * null if the interface does not have any IPv4 addresses.
      */
--- a/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Thu Mar 28 14:59:22 2013 -0700
@@ -80,7 +80,8 @@
     public InetAddress getInetAddress() {
         if (!ssc.isBound())
             return null;
-        return Net.asInetSocketAddress(ssc.localAddress()).getAddress();
+        return Net.getRevealedLocalAddress(ssc.localAddress()).getAddress();
+
     }
 
     public int getLocalPort() {
--- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -72,7 +72,7 @@
     private int state = ST_UNINITIALIZED;
 
     // Binding
-    private SocketAddress localAddress; // null => unbound
+    private InetSocketAddress localAddress; // null => unbound
 
     // set true when exclusive binding is on and SO_REUSEADDR is emulated
     private boolean isReuseAddress;
@@ -116,7 +116,9 @@
         synchronized (stateLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            return localAddress;
+            return localAddress == null? localAddress
+                    : Net.getRevealedLocalAddress(
+                          Net.asInetSocketAddress(localAddress));
         }
     }
 
@@ -190,7 +192,7 @@
         }
     }
 
-    public SocketAddress localAddress() {
+    public InetSocketAddress localAddress() {
         synchronized (stateLock) {
             return localAddress;
         }
@@ -361,14 +363,15 @@
         StringBuffer sb = new StringBuffer();
         sb.append(this.getClass().getName());
         sb.append('[');
-        if (!isOpen())
+        if (!isOpen()) {
             sb.append("closed");
-        else {
+        } else {
             synchronized (stateLock) {
-                if (localAddress() == null) {
+                InetSocketAddress addr = localAddress();
+                if (addr == null) {
                     sb.append("unbound");
                 } else {
-                    sb.append(localAddress().toString());
+                    sb.append(Net.getRevealedLocalAddressAsString(addr));
                 }
             }
         }
--- a/src/share/classes/sun/nio/ch/SocketAdaptor.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/SocketAdaptor.java	Thu Mar 28 14:59:22 2013 -0700
@@ -155,9 +155,9 @@
 
     public InetAddress getLocalAddress() {
         if (sc.isOpen()) {
-            SocketAddress local = sc.localAddress();
+            InetSocketAddress local = sc.localAddress();
             if (local != null)
-                return ((InetSocketAddress)local).getAddress();
+                return Net.getRevealedLocalAddress(local).getAddress();
         }
         return new InetSocketAddress(0).getAddress();
     }
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -83,8 +83,8 @@
     private int state = ST_UNINITIALIZED;
 
     // Binding
-    private SocketAddress localAddress;
-    private SocketAddress remoteAddress;
+    private InetSocketAddress localAddress;
+    private InetSocketAddress remoteAddress;
 
     // Input/Output open
     private boolean isInputOpen = true;
@@ -146,7 +146,7 @@
         synchronized (stateLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            return localAddress;
+            return  Net.getRevealedLocalAddress(localAddress);
         }
     }
 
@@ -547,7 +547,7 @@
         IOUtil.configureBlocking(fd, block);
     }
 
-    public SocketAddress localAddress() {
+    public InetSocketAddress localAddress() {
         synchronized (stateLock) {
             return localAddress;
         }
@@ -958,6 +958,7 @@
         return fdVal;
     }
 
+    @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
         sb.append(this.getClass().getSuperclass().getName());
@@ -981,9 +982,10 @@
                         sb.append(" oshut");
                     break;
                 }
-                if (localAddress() != null) {
+                InetSocketAddress addr = localAddress();
+                if (addr != null) {
                     sb.append(" local=");
-                    sb.append(localAddress().toString());
+                    sb.append(Net.getRevealedLocalAddressAsString(addr));
                 }
                 if (remoteAddress() != null) {
                     sb.append(" remote=");
--- a/src/share/classes/sun/rmi/server/Activation.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/rmi/server/Activation.java	Thu Mar 28 14:59:22 2013 -0700
@@ -2224,7 +2224,13 @@
         }
 
         public InetAddress getInetAddress() {
-            return serverSocket.getInetAddress();
+            return AccessController.doPrivileged(
+                new PrivilegedAction<InetAddress>() {
+                    @Override
+                    public InetAddress run() {
+                        return serverSocket.getInetAddress();
+                    }
+                });
         }
 
         public int getLocalPort() {
@@ -2232,7 +2238,13 @@
         }
 
         public SocketAddress getLocalSocketAddress() {
-            return serverSocket.getLocalSocketAddress();
+            return AccessController.doPrivileged(
+                new PrivilegedAction<SocketAddress>() {
+                    @Override
+                    public SocketAddress run() {
+                        return serverSocket.getLocalSocketAddress();
+                    }
+                });
         }
 
         /**
--- a/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java	Thu Mar 28 14:59:22 2013 -0700
@@ -28,6 +28,8 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.SocketException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 /**
  * The WrappedSocket class provides a general wrapper for providing an
@@ -78,7 +80,14 @@
      * Get the local address to which the socket is bound.
      */
     public InetAddress getLocalAddress() {
-        return socket.getLocalAddress();
+        return  AccessController.doPrivileged(
+                        new PrivilegedAction<InetAddress>() {
+                            @Override
+                            public InetAddress run() {
+                                return socket.getLocalAddress();
+
+                            }
+                        });
     }
 
     /**
--- a/src/solaris/classes/sun/nio/ch/SctpNet.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/solaris/classes/sun/nio/ch/SctpNet.java	Thu Mar 28 14:59:22 2013 -0700
@@ -36,11 +36,18 @@
 import sun.security.action.GetPropertyAction;
 import com.sun.nio.sctp.SctpSocketOption;
 import static com.sun.nio.sctp.SctpStandardSocketOptions.*;
+import java.security.PrivilegedExceptionAction;
 
 public class SctpNet {
     static final String osName = AccessController.doPrivileged(
                     new GetPropertyAction("os.name"));
 
+    // Value of jdk.net.revealLocalAddress
+    private static boolean revealLocalAddress;
+
+    // True if jdk.net.revealLocalAddress had been read
+    private static volatile boolean propRevealLocalAddr;
+
     /* -- Miscellaneous SCTP utilities -- */
 
     private static boolean IPv4MappedAddresses() {
@@ -92,18 +99,65 @@
 
     static Set<SocketAddress> getLocalAddresses(int fd)
             throws IOException {
-        HashSet<SocketAddress> set = null;
+        Set<SocketAddress> set = null;
         SocketAddress[] saa = getLocalAddresses0(fd);
 
         if (saa != null) {
-            set = new HashSet<SocketAddress>(saa.length);
-            for (SocketAddress sa : saa)
-                set.add(sa);
+            set = getRevealedLocalAddressSet(saa);
         }
 
         return set;
     }
 
+    private static Set<SocketAddress> getRevealedLocalAddressSet(
+            SocketAddress[] saa)
+    {
+         SecurityManager sm = System.getSecurityManager();
+         Set<SocketAddress> set = new HashSet<>(saa.length);
+         for (SocketAddress sa : saa) {
+             set.add(getRevealedLocalAddress(sa, sm));
+         }
+         return set;
+    }
+
+    private static SocketAddress getRevealedLocalAddress(SocketAddress sa,
+                                                         SecurityManager sm)
+    {
+        if (sm == null || sa == null)
+            return sa;
+        InetSocketAddress ia = (InetSocketAddress)sa;
+        if (!propRevealLocalAddr) {
+            try {
+                revealLocalAddress = Boolean.parseBoolean(
+                      AccessController.doPrivileged(
+                          new PrivilegedExceptionAction<String>() {
+                              public String run() {
+                                  return System.getProperty(
+                                      "jdk.net.revealLocalAddress");
+                              }
+                          }));
+
+            } catch (Exception e) {
+                // revealLocalAddress is false
+            }
+            propRevealLocalAddr = true;
+        }
+        if (!revealLocalAddress) {
+           try{
+               sm.checkConnect(ia.getAddress().getHostAddress(), -1);
+               //Security check passed
+           } catch (SecurityException e) {
+                //Return loopback address
+                return new InetSocketAddress(
+                        InetAddress.getLoopbackAddress(), ia.getPort());
+           }
+        }
+
+        // Security check passed or jdk.net.revealLocalAddress set to true
+        return sa;
+
+    }
+
     static Set<SocketAddress> getRemoteAddresses(int fd, int assocId)
             throws IOException {
         HashSet<SocketAddress> set = null;
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -241,7 +241,7 @@
         synchronized (stateLock) {
             state = ST_CONNECTED;
             localAddress = Net.localAddress(fd);
-            remoteAddress = pendingRemote;
+            remoteAddress = (InetSocketAddress)pendingRemote;
         }
     }
 
--- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Mon Mar 25 12:41:55 2013 +0400
+++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java	Thu Mar 28 14:59:22 2013 -0700
@@ -137,7 +137,9 @@
 
     // invoked by WindowsAsynchronousServerSocketChannelImpl when new connection
     // accept
-    void setConnected(SocketAddress localAddress, SocketAddress remoteAddress) {
+    void setConnected(InetSocketAddress localAddress,
+                      InetSocketAddress remoteAddress)
+    {
         synchronized (stateLock) {
             state = ST_CONNECTED;
             this.localAddress = localAddress;