diff options
author | Paul Jensen <pauljensen@google.com> | 2014-05-12 23:40:42 -0400 |
---|---|---|
committer | Lorenzo Colitti <lorenzo@google.com> | 2014-05-13 19:46:56 -0700 |
commit | 3e58734d651080009c9190c7062837fca5c7cf4e (patch) | |
tree | d213742063128c6be8b785ae4fd7816b95a71879 /luni | |
parent | 8f3ae282cb56de80de35b90408c9d832c8e3c424 (diff) | |
download | libcore-3e58734d651080009c9190c7062837fca5c7cf4e.zip libcore-3e58734d651080009c9190c7062837fca5c7cf4e.tar.gz libcore-3e58734d651080009c9190c7062837fca5c7cf4e.tar.bz2 |
Add support for network-specific host name resolution.
For now all such support is hidden.
Change-Id: I932f73158a8f6e3ccc36c319d138180dff2aa070
Diffstat (limited to 'luni')
-rw-r--r-- | luni/src/main/java/android/system/Os.java | 4 | ||||
-rw-r--r-- | luni/src/main/java/java/net/AddressCache.java | 50 | ||||
-rw-r--r-- | luni/src/main/java/java/net/InetAddress.java | 61 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/ForwardingOs.java | 2 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Os.java | 2 | ||||
-rw-r--r-- | luni/src/main/java/libcore/io/Posix.java | 2 | ||||
-rw-r--r-- | luni/src/main/native/Portability.h | 9 | ||||
-rw-r--r-- | luni/src/main/native/libcore_io_Posix.cpp | 14 |
8 files changed, 109 insertions, 35 deletions
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java index beb785f..0b80b52 100644 --- a/luni/src/main/java/android/system/Os.java +++ b/luni/src/main/java/android/system/Os.java @@ -61,6 +61,8 @@ public final class Os { */ public static boolean access(String path, int mode) throws ErrnoException { return Libcore.os.access(path, mode); } + /** @hide */ public static InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException { return Libcore.os.android_getaddrinfo(node, hints, netId); } + /** * See <a href="http://man7.org/linux/man-pages/man2/bind.2.html">bind(2)</a>. */ @@ -155,8 +157,6 @@ public final class Os { */ public static String gai_strerror(int error) { return Libcore.os.gai_strerror(error); } - /** @hide */ public static InetAddress[] getaddrinfo(String node, StructAddrinfo hints) throws GaiException { return Libcore.os.getaddrinfo(node, hints); } - /** * See <a href="http://man7.org/linux/man-pages/man2/getegid.2.html">getegid(2)</a>. */ diff --git a/luni/src/main/java/java/net/AddressCache.java b/luni/src/main/java/java/net/AddressCache.java index 194761a..2aba78b 100644 --- a/luni/src/main/java/java/net/AddressCache.java +++ b/luni/src/main/java/java/net/AddressCache.java @@ -37,8 +37,36 @@ class AddressCache { private static final long TTL_NANOS = 2 * 1000000000L; // The actual cache. - private final BasicLruCache<String, AddressCacheEntry> cache - = new BasicLruCache<String, AddressCacheEntry>(MAX_ENTRIES); + private final BasicLruCache<AddressCacheKey, AddressCacheEntry> cache + = new BasicLruCache<AddressCacheKey, AddressCacheEntry>(MAX_ENTRIES); + + static class AddressCacheKey { + private final String mHostname; + private final int mNetId; + + AddressCacheKey(String hostname, int netId) { + mHostname = hostname; + mNetId = netId; + } + + @Override public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof AddressCacheKey)) { + return false; + } + AddressCacheKey lhs = (AddressCacheKey) o; + return mHostname.equals(lhs.mHostname) && mNetId == lhs.mNetId; + } + + @Override public int hashCode() { + int result = 17; + result = 31 * result + mNetId; + result = 31 * result + mHostname.hashCode(); + return result; + } + } static class AddressCacheEntry { // Either an InetAddress[] for a positive entry, @@ -67,12 +95,12 @@ class AddressCache { } /** - * Returns the cached InetAddress[] associated with 'hostname'. Returns null if nothing is known - * about 'hostname'. Returns a String suitable for use as an UnknownHostException detail - * message if 'hostname' is known not to exist. + * Returns the cached InetAddress[] for 'hostname' on network 'netId'. Returns null + * if nothing is known about 'hostname'. Returns a String suitable for use as an + * UnknownHostException detail message if 'hostname' is known not to exist. */ - public Object get(String hostname) { - AddressCacheEntry entry = cache.get(hostname); + public Object get(String hostname, int netId) { + AddressCacheEntry entry = cache.get(new AddressCacheKey(hostname, netId)); // Do we have a valid cache entry? if (entry != null && entry.expiryNanos >= System.nanoTime()) { return entry.value; @@ -86,15 +114,15 @@ class AddressCache { * Associates the given 'addresses' with 'hostname'. The association will expire after a * certain length of time. */ - public void put(String hostname, InetAddress[] addresses) { - cache.put(hostname, new AddressCacheEntry(addresses)); + public void put(String hostname, int netId, InetAddress[] addresses) { + cache.put(new AddressCacheKey(hostname, netId), new AddressCacheEntry(addresses)); } /** * Records that 'hostname' is known not to have any associated addresses. (I.e. insert a * negative cache entry.) */ - public void putUnknownHost(String hostname, String detailMessage) { - cache.put(hostname, new AddressCacheEntry(detailMessage)); + public void putUnknownHost(String hostname, int netId, String detailMessage) { + cache.put(new AddressCacheKey(hostname, netId), new AddressCacheEntry(detailMessage)); } } diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java index e31b4c3..5cfa15a 100644 --- a/luni/src/main/java/java/net/InetAddress.java +++ b/luni/src/main/java/java/net/InetAddress.java @@ -127,6 +127,9 @@ public class InetAddress implements Serializable { private static final long serialVersionUID = 3286316764910316507L; + /** Using NetID of NETID_UNSET indicates resolution should be done on default network. */ + private static final int NETID_UNSET = 0; + private int family; byte[] ipaddress; @@ -209,14 +212,29 @@ public class InetAddress implements Serializable { * @throws UnknownHostException if the address lookup fails. */ public static InetAddress[] getAllByName(String host) throws UnknownHostException { - return getAllByNameImpl(host).clone(); + return getAllByNameImpl(host, NETID_UNSET).clone(); } /** - * Returns the InetAddresses for {@code host}. The returned array is shared - * and must be cloned before it is returned to application code. + * Operates identically to {@code getAllByName} except host resolution is + * performed on the network designated by {@code netId}. + * + * @param host the hostname or literal IP string to be resolved. + * @param netId the network to use for host resolution. + * @return the array of addresses associated with the specified host. + * @throws UnknownHostException if the address lookup fails. + * @hide internal use only */ - private static InetAddress[] getAllByNameImpl(String host) throws UnknownHostException { + public static InetAddress[] getAllByNameOnNet(String host, int netId) throws UnknownHostException { + return getAllByNameImpl(host, netId).clone(); + } + + /** + * Returns the InetAddresses for {@code host} on network {@code netId}. The + * returned array is shared and must be cloned before it is returned to + * application code. + */ + private static InetAddress[] getAllByNameImpl(String host, int netId) throws UnknownHostException { if (host == null || host.isEmpty()) { return loopbackAddresses(); } @@ -231,7 +249,7 @@ public class InetAddress implements Serializable { return new InetAddress[] { result }; } - return lookupHostByName(host).clone(); + return lookupHostByName(host, netId).clone(); } private static InetAddress makeInetAddress(byte[] bytes, String hostName) throws UnknownHostException { @@ -264,7 +282,7 @@ public class InetAddress implements Serializable { hints.ai_flags = AI_NUMERICHOST; InetAddress[] addresses = null; try { - addresses = Libcore.os.getaddrinfo(address, hints); + addresses = Libcore.os.android_getaddrinfo(address, hints, NETID_UNSET); } catch (GaiException ignored) { } return (addresses != null) ? addresses[0] : null; @@ -284,7 +302,22 @@ public class InetAddress implements Serializable { * if the address lookup fails. */ public static InetAddress getByName(String host) throws UnknownHostException { - return getAllByNameImpl(host)[0]; + return getAllByNameImpl(host, NETID_UNSET)[0]; + } + + /** + * Operates identically to {@code getByName} except host resolution is + * performed on the network designated by {@code netId}. + * + * @param host + * the hostName to be resolved to an address or {@code null}. + * @param netId the network to use for host resolution. + * @return the {@code InetAddress} instance representing the host. + * @throws UnknownHostException if the address lookup fails. + * @hide internal use only + */ + public static InetAddress getByNameOnNet(String host, int netId) throws UnknownHostException { + return getAllByNameImpl(host, netId)[0]; } /** @@ -360,7 +393,7 @@ public class InetAddress implements Serializable { */ public static InetAddress getLocalHost() throws UnknownHostException { String host = Libcore.os.uname().nodename; - return lookupHostByName(host)[0]; + return lookupHostByName(host, NETID_UNSET)[0]; } /** @@ -377,12 +410,14 @@ public class InetAddress implements Serializable { * Resolves a hostname to its IP addresses using a cache. * * @param host the hostname to resolve. + * @param netId the network to perform resolution upon. * @return the IP addresses of the host. */ - private static InetAddress[] lookupHostByName(String host) throws UnknownHostException { + private static InetAddress[] lookupHostByName(String host, int netId) + throws UnknownHostException { BlockGuard.getThreadPolicy().onNetwork(); // Do we have a result cached? - Object cachedResult = addressCache.get(host); + Object cachedResult = addressCache.get(host, netId); if (cachedResult != null) { if (cachedResult instanceof InetAddress[]) { // A cached positive result. @@ -400,12 +435,12 @@ public class InetAddress implements Serializable { // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family // anyway, just pick one. hints.ai_socktype = SOCK_STREAM; - InetAddress[] addresses = Libcore.os.getaddrinfo(host, hints); + InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId); // TODO: should getaddrinfo set the hostname of the InetAddresses it returns? for (InetAddress address : addresses) { address.hostName = host; } - addressCache.put(host, addresses); + addressCache.put(host, netId, addresses); return addresses; } catch (GaiException gaiException) { // If the failure appears to have been a lack of INTERNET permission, throw a clear @@ -418,7 +453,7 @@ public class InetAddress implements Serializable { } // Otherwise, throw an UnknownHostException. String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error); - addressCache.putUnknownHost(host, detailMessage); + addressCache.putUnknownHost(host, netId, detailMessage); throw gaiException.rethrowAsUnknownHostException(detailMessage); } } diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index d09e442..bf4b448 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -52,6 +52,7 @@ public class ForwardingOs implements Os { public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException { return os.accept(fd, peerAddress); } public boolean access(String path, int mode) throws ErrnoException { return os.access(path, mode); } + public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException { return os.android_getaddrinfo(node, hints, netId); } public void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { os.bind(fd, address, port); } public void chmod(String path, int mode) throws ErrnoException { os.chmod(path, mode); } public void chown(String path, int uid, int gid) throws ErrnoException { os.chown(path, uid, gid); } @@ -73,7 +74,6 @@ public class ForwardingOs implements Os { public void fsync(FileDescriptor fd) throws ErrnoException { os.fsync(fd); } public void ftruncate(FileDescriptor fd, long length) throws ErrnoException { os.ftruncate(fd, length); } public String gai_strerror(int error) { return os.gai_strerror(error); } - public InetAddress[] getaddrinfo(String node, StructAddrinfo hints) throws GaiException { return os.getaddrinfo(node, hints); } public int getegid() { return os.getegid(); } public int geteuid() { return os.geteuid(); } public int getgid() { return os.getgid(); } diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index a537aeb..511bb27 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -43,6 +43,7 @@ import java.nio.ByteBuffer; public interface Os { public FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException; public boolean access(String path, int mode) throws ErrnoException; + public InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException; public void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException; public void chmod(String path, int mode) throws ErrnoException; public void chown(String path, int uid, int gid) throws ErrnoException; @@ -64,7 +65,6 @@ public interface Os { public void fsync(FileDescriptor fd) throws ErrnoException; public void ftruncate(FileDescriptor fd, long length) throws ErrnoException; public String gai_strerror(int error); - public InetAddress[] getaddrinfo(String node, StructAddrinfo hints) throws GaiException; public int getegid(); public int geteuid(); public int getgid(); diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index 7551190..f5eaaa3 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -46,6 +46,7 @@ public final class Posix implements Os { public native FileDescriptor accept(FileDescriptor fd, InetSocketAddress peerAddress) throws ErrnoException, SocketException; public native boolean access(String path, int mode) throws ErrnoException; + public native InetAddress[] android_getaddrinfo(String node, StructAddrinfo hints, int netId) throws GaiException; public native void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException; public native void chmod(String path, int mode) throws ErrnoException; public native void chown(String path, int uid, int gid) throws ErrnoException; @@ -67,7 +68,6 @@ public final class Posix implements Os { public native void fsync(FileDescriptor fd) throws ErrnoException; public native void ftruncate(FileDescriptor fd, long length) throws ErrnoException; public native String gai_strerror(int error); - public native InetAddress[] getaddrinfo(String node, StructAddrinfo hints) throws GaiException; public native int getegid(); public native int geteuid(); public native int getgid(); diff --git a/luni/src/main/native/Portability.h b/luni/src/main/native/Portability.h index 60b7062..3c8384d 100644 --- a/luni/src/main/native/Portability.h +++ b/luni/src/main/native/Portability.h @@ -74,6 +74,15 @@ static inline int mincore(void* addr, size_t length, unsigned char* vec) { #include <sys/sendfile.h> #include <sys/statvfs.h> +#if !defined(__BIONIC__) +#include <netdb.h> +#include "../../bionic/libc/dns/include/resolv_netid.h" +inline int android_getaddrinfofornet(const char *hostname, const char *servname, + const struct addrinfo *hints, unsigned /*netid*/, unsigned /*mark*/, struct addrinfo **res) { + return getaddrinfo(hostname, servname, hints, res); +} +#endif + #endif #endif // PORTABILITY_H_included diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index b1217c0..6eee7f0 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -25,6 +25,7 @@ #include "NetworkUtilities.h" #include "Portability.h" #include "readlink.h" +#include "../../bionic/libc/dns/include/resolv_netid.h" // For android_getaddrinfofornet. #include "ScopedBytes.h" #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" @@ -645,7 +646,8 @@ static jstring Posix_gai_strerror(JNIEnv* env, jobject, jint error) { return env->NewStringUTF(gai_strerror(error)); } -static jobjectArray Posix_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, jobject javaHints) { +static jobjectArray Posix_android_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, + jobject javaHints, jint netId) { ScopedUtfChars node(env, javaNode); if (node.c_str() == NULL) { return NULL; @@ -665,10 +667,10 @@ static jobjectArray Posix_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, jo addrinfo* addressList = NULL; errno = 0; - int rc = getaddrinfo(node.c_str(), NULL, &hints, &addressList); + int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList); UniquePtr<addrinfo, addrinfo_deleter> addressListDeleter(addressList); if (rc != 0) { - throwGaiException(env, "getaddrinfo", rc); + throwGaiException(env, "android_getaddrinfo", rc); return NULL; } @@ -678,7 +680,7 @@ static jobjectArray Posix_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, jo if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { ++addressCount; } else { - ALOGE("getaddrinfo unexpected ai_family %i", ai->ai_family); + ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); } } if (addressCount == 0) { @@ -696,7 +698,7 @@ static jobjectArray Posix_getaddrinfo(JNIEnv* env, jobject, jstring javaNode, jo for (addrinfo* ai = addressList; ai != NULL; ai = ai->ai_next) { if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { // Unknown address family. Skip this address. - ALOGE("getaddrinfo unexpected ai_family %i", ai->ai_family); + ALOGE("android_getaddrinfo unexpected ai_family %i", ai->ai_family); continue; } @@ -1499,6 +1501,7 @@ static jint Posix_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buff static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, accept, "(Ljava/io/FileDescriptor;Ljava/net/InetSocketAddress;)Ljava/io/FileDescriptor;"), NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"), + NATIVE_METHOD(Posix, android_getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;I)[Ljava/net/InetAddress;"), NATIVE_METHOD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"), NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"), NATIVE_METHOD(Posix, chown, "(Ljava/lang/String;II)V"), @@ -1520,7 +1523,6 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"), NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"), NATIVE_METHOD(Posix, gai_strerror, "(I)Ljava/lang/String;"), - NATIVE_METHOD(Posix, getaddrinfo, "(Ljava/lang/String;Landroid/system/StructAddrinfo;)[Ljava/net/InetAddress;"), NATIVE_METHOD(Posix, getegid, "()I"), NATIVE_METHOD(Posix, geteuid, "()I"), NATIVE_METHOD(Posix, getgid, "()I"), |