diff options
author | Erik Kline <ek@google.com> | 2015-03-10 22:04:27 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-03-10 22:04:27 +0000 |
commit | b186e3c9195112f7acf938be388889dd773c2b18 (patch) | |
tree | 117e14d5da80d8e3cd6f2afcba5b8eacee303eed /luni/src/main | |
parent | 2e1d4fcc089f4d3451e9c982e7b192143df37674 (diff) | |
parent | 24c68680f1c187fa9d2a9cc4c4ddb5ae09fa7dfb (diff) | |
download | libcore-b186e3c9195112f7acf938be388889dd773c2b18.zip libcore-b186e3c9195112f7acf938be388889dd773c2b18.tar.gz libcore-b186e3c9195112f7acf938be388889dd773c2b18.tar.bz2 |
am 24c68680: am 649f614e: am 2882e512: Merge "Add support for netlink sockets and addresses."
* commit '24c68680f1c187fa9d2a9cc4c4ddb5ae09fa7dfb':
Add support for netlink sockets and addresses.
Diffstat (limited to 'luni/src/main')
-rw-r--r-- | luni/src/main/java/android/system/NetlinkSocketAddress.java | 61 | ||||
-rw-r--r-- | luni/src/main/java/android/system/Os.java | 4 | ||||
-rw-r--r-- | luni/src/main/java/android/system/OsConstants.java | 15 | ||||
-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/android_system_OsConstants.cpp | 15 | ||||
-rw-r--r-- | luni/src/main/native/libcore_io_Posix.cpp | 102 |
8 files changed, 195 insertions, 8 deletions
diff --git a/luni/src/main/java/android/system/NetlinkSocketAddress.java b/luni/src/main/java/android/system/NetlinkSocketAddress.java new file mode 100644 index 0000000..af78cd0 --- /dev/null +++ b/luni/src/main/java/android/system/NetlinkSocketAddress.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.system; + +import libcore.util.Objects; +import java.net.SocketAddress; + +/** + * Netlink socket address. + * + * Corresponds to Linux's {@code struct sockaddr_nl} from + * <a href="https://github.com/torvalds/linux/blob/master/include/uapi/linux/netlink.h"><linux/netlink.h></a>. + * + * @hide + */ +public final class NetlinkSocketAddress extends SocketAddress { + /** port ID */ + private final int nlPortId; + + /** multicast groups mask */ + private final int nlGroupsMask; + + public NetlinkSocketAddress() { + this(0, 0); + } + + public NetlinkSocketAddress(int nlPortId) { + this(nlPortId, 0); + } + + public NetlinkSocketAddress(int nlPortId, int nlGroupsMask) { + this.nlPortId = nlPortId; + this.nlGroupsMask = nlGroupsMask; + } + + public int getPortId() { + return nlPortId; + } + + public int getGroupsMask() { + return nlGroupsMask; + } + + @Override public String toString() { + return Objects.toString(this); + } +} diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java index 8028f23..ee683d2 100644 --- a/luni/src/main/java/android/system/Os.java +++ b/luni/src/main/java/android/system/Os.java @@ -54,6 +54,8 @@ public final class Os { */ public static void bind(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { Libcore.os.bind(fd, address, port); } + /** @hide */ public static void bind(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException { Libcore.os.bind(fd, address); } + /** * See <a href="http://man7.org/linux/man-pages/man2/chmod.2.html">chmod(2)</a>. */ @@ -74,6 +76,8 @@ public final class Os { */ public static void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { Libcore.os.connect(fd, address, port); } + /** @hide */ public static void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException { Libcore.os.connect(fd, address); } + /** * See <a href="http://man7.org/linux/man-pages/man2/dup.2.html">dup(2)</a>. */ diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java index 1f9205c..a52004b 100644 --- a/luni/src/main/java/android/system/OsConstants.java +++ b/luni/src/main/java/android/system/OsConstants.java @@ -95,6 +95,7 @@ public final class OsConstants { public static final int AF_INET = placeholder(); public static final int AF_INET6 = placeholder(); + /** @hide */ public static final int AF_NETLINK = placeholder(); public static final int AF_UNIX = placeholder(); public static final int AF_UNSPEC = placeholder(); public static final int AI_ADDRCONFIG = placeholder(); @@ -324,6 +325,7 @@ public final class OsConstants { public static final int MS_ASYNC = placeholder(); public static final int MS_INVALIDATE = placeholder(); public static final int MS_SYNC = placeholder(); + /** @hide */ public static final int NETLINK_ROUTE = placeholder(); public static final int NI_DGRAM = placeholder(); public static final int NI_NAMEREQD = placeholder(); public static final int NI_NOFQDN = placeholder(); @@ -365,6 +367,19 @@ public final class OsConstants { public static final int RT_SCOPE_NOWHERE = placeholder(); public static final int RT_SCOPE_SITE = placeholder(); public static final int RT_SCOPE_UNIVERSE = placeholder(); + /** @hide */ public static final int RTMGRP_IPV4_IFADDR = placeholder(); + /** @hide */ public static final int RTMGRP_IPV4_MROUTE = placeholder(); + /** @hide */ public static final int RTMGRP_IPV4_ROUTE = placeholder(); + /** @hide */ public static final int RTMGRP_IPV4_RULE = placeholder(); + /** @hide */ public static final int RTMGRP_IPV6_IFADDR = placeholder(); + /** @hide */ public static final int RTMGRP_IPV6_IFINFO = placeholder(); + /** @hide */ public static final int RTMGRP_IPV6_MROUTE = placeholder(); + /** @hide */ public static final int RTMGRP_IPV6_PREFIX = placeholder(); + /** @hide */ public static final int RTMGRP_IPV6_ROUTE = placeholder(); + /** @hide */ public static final int RTMGRP_LINK = placeholder(); + /** @hide */ public static final int RTMGRP_NEIGH = placeholder(); + /** @hide */ public static final int RTMGRP_NOTIFY = placeholder(); + /** @hide */ public static final int RTMGRP_TC = placeholder(); public static final int SEEK_CUR = placeholder(); public static final int SEEK_END = placeholder(); public static final int SEEK_SET = placeholder(); diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java index 5c90757..d07b99a 100644 --- a/luni/src/main/java/libcore/io/ForwardingOs.java +++ b/luni/src/main/java/libcore/io/ForwardingOs.java @@ -54,10 +54,12 @@ public class ForwardingOs implements Os { 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 bind(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException { os.bind(fd, address); } 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); } public void close(FileDescriptor fd) throws ErrnoException { os.close(fd); } public void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException { os.connect(fd, address, port); } + public void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException { os.connect(fd, address); } public FileDescriptor dup(FileDescriptor oldFd) throws ErrnoException { return os.dup(oldFd); } public FileDescriptor dup2(FileDescriptor oldFd, int newFd) throws ErrnoException { return os.dup2(oldFd, newFd); } public String[] environ() { return os.environ(); } diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java index 620af19..3fc031c 100644 --- a/luni/src/main/java/libcore/io/Os.java +++ b/luni/src/main/java/libcore/io/Os.java @@ -45,10 +45,12 @@ public interface Os { 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 bind(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException; public void chmod(String path, int mode) throws ErrnoException; public void chown(String path, int uid, int gid) throws ErrnoException; public void close(FileDescriptor fd) throws ErrnoException; public void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException; + public void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException; public FileDescriptor dup(FileDescriptor oldFd) throws ErrnoException; public FileDescriptor dup2(FileDescriptor oldFd, int newFd) throws ErrnoException; public String[] environ(); diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java index 2629553..251d06f 100644 --- a/luni/src/main/java/libcore/io/Posix.java +++ b/luni/src/main/java/libcore/io/Posix.java @@ -48,10 +48,12 @@ public final class Posix implements Os { 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 bind(FileDescriptor fd, SocketAddress address) 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; public native void close(FileDescriptor fd) throws ErrnoException; public native void connect(FileDescriptor fd, InetAddress address, int port) throws ErrnoException, SocketException; + public native void connect(FileDescriptor fd, SocketAddress address) throws ErrnoException, SocketException; public native FileDescriptor dup(FileDescriptor oldFd) throws ErrnoException; public native FileDescriptor dup2(FileDescriptor oldFd, int newFd) throws ErrnoException; public native String[] environ(); diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp index 46dabb3..0c55305 100644 --- a/luni/src/main/native/android_system_OsConstants.cpp +++ b/luni/src/main/native/android_system_OsConstants.cpp @@ -58,6 +58,7 @@ static void initConstant(JNIEnv* env, jclass c, const char* fieldName, int value static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "AF_INET", AF_INET); initConstant(env, c, "AF_INET6", AF_INET6); + initConstant(env, c, "AF_NETLINK", AF_NETLINK); initConstant(env, c, "AF_UNIX", AF_UNIX); initConstant(env, c, "AF_UNSPEC", AF_UNSPEC); initConstant(env, c, "AI_ADDRCONFIG", AI_ADDRCONFIG); @@ -355,6 +356,7 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "MS_ASYNC", MS_ASYNC); initConstant(env, c, "MS_INVALIDATE", MS_INVALIDATE); initConstant(env, c, "MS_SYNC", MS_SYNC); + initConstant(env, c, "NETLINK_ROUTE", NETLINK_ROUTE); initConstant(env, c, "NI_DGRAM", NI_DGRAM); initConstant(env, c, "NI_NAMEREQD", NI_NAMEREQD); initConstant(env, c, "NI_NOFQDN", NI_NOFQDN); @@ -407,6 +409,19 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) { initConstant(env, c, "RT_SCOPE_NOWHERE", RT_SCOPE_NOWHERE); initConstant(env, c, "RT_SCOPE_SITE", RT_SCOPE_SITE); initConstant(env, c, "RT_SCOPE_UNIVERSE", RT_SCOPE_UNIVERSE); + initConstant(env, c, "RTMGRP_IPV4_IFADDR", RTMGRP_IPV4_IFADDR); + initConstant(env, c, "RTMGRP_IPV4_MROUTE", RTMGRP_IPV4_MROUTE); + initConstant(env, c, "RTMGRP_IPV4_ROUTE", RTMGRP_IPV4_ROUTE); + initConstant(env, c, "RTMGRP_IPV4_RULE", RTMGRP_IPV4_RULE); + initConstant(env, c, "RTMGRP_IPV6_IFADDR", RTMGRP_IPV6_IFADDR); + initConstant(env, c, "RTMGRP_IPV6_IFINFO", RTMGRP_IPV6_IFINFO); + initConstant(env, c, "RTMGRP_IPV6_MROUTE", RTMGRP_IPV6_MROUTE); + initConstant(env, c, "RTMGRP_IPV6_PREFIX", RTMGRP_IPV6_PREFIX); + initConstant(env, c, "RTMGRP_IPV6_ROUTE", RTMGRP_IPV6_ROUTE); + initConstant(env, c, "RTMGRP_LINK", RTMGRP_LINK); + initConstant(env, c, "RTMGRP_NEIGH", RTMGRP_NEIGH); + initConstant(env, c, "RTMGRP_NOTIFY", RTMGRP_NOTIFY); + initConstant(env, c, "RTMGRP_TC", RTMGRP_TC); #endif initConstant(env, c, "SEEK_CUR", SEEK_CUR); initConstant(env, c, "SEEK_END", SEEK_END); diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp index 4c7e372..a1113ab 100644 --- a/luni/src/main/native/libcore_io_Posix.cpp +++ b/luni/src/main/native/libcore_io_Posix.cpp @@ -34,6 +34,7 @@ #include <arpa/inet.h> #include <errno.h> #include <fcntl.h> +#include <linux/rtnetlink.h> #include <net/if.h> #include <netdb.h> #include <netinet/in.h> @@ -266,14 +267,25 @@ private: }; static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss) { - jint port; - jobject inetAddress = sockaddrToInetAddress(env, ss, &port); - if (inetAddress == NULL) { - return NULL; - } - static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass, "<init>", - "(Ljava/net/InetAddress;I)V"); - return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port); + if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6 || ss.ss_family == AF_UNIX) { + jint port; + jobject inetAddress = sockaddrToInetAddress(env, ss, &port); + if (inetAddress == NULL) { + return NULL; // Exception already thrown. + } + static jmethodID ctor = env->GetMethodID(JniConstants::inetSocketAddressClass, + "<init>", "(Ljava/net/InetAddress;I)V"); + return env->NewObject(JniConstants::inetSocketAddressClass, ctor, inetAddress, port); + } else if (ss.ss_family == AF_NETLINK) { + const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss); + static jmethodID ctor = env->GetMethodID(JniConstants::netlinkSocketAddressClass, + "<init>", "(II)V"); + return env->NewObject(JniConstants::netlinkSocketAddressClass, ctor, + static_cast<jint>(nl_addr->nl_pid), + static_cast<jint>(nl_addr->nl_groups)); + } + jniThrowException(env, "java/lang/IllegalArgumentException", "unsupported ss_family"); + return NULL; } static jobject makeStructPasswd(JNIEnv* env, const struct passwd& pw) { @@ -384,6 +396,49 @@ static bool fillInetSocketAddress(JNIEnv* env, jint rc, jobject javaInetSocketAd return true; } +static bool javaInetSocketAddressToSockaddr( + JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { + static jfieldID addressFid = env->GetFieldID( + JniConstants::inetSocketAddressClass, "addr", "Ljava/net/InetAddress;"); + static jfieldID portFid = env->GetFieldID(JniConstants::inetSocketAddressClass, "port", "I"); + return inetAddressToSockaddr(env, + env->GetObjectField(javaSocketAddress, addressFid), + env->GetIntField(javaSocketAddress, portFid), + ss, sa_len); +} + +static bool javaNetlinkSocketAddressToSockaddr( + JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { + static jfieldID nlPidFid = env->GetFieldID( + JniConstants::netlinkSocketAddressClass, "nlPortId", "I"); + static jfieldID nlGroupsFid = env->GetFieldID( + JniConstants::netlinkSocketAddressClass, "nlGroupsMask", "I"); + + sockaddr_nl *nlAddr = reinterpret_cast<sockaddr_nl *>(&ss); + nlAddr->nl_family = AF_NETLINK; + nlAddr->nl_pid = env->GetIntField(javaSocketAddress, nlPidFid); + nlAddr->nl_groups = env->GetIntField(javaSocketAddress, nlGroupsFid); + sa_len = sizeof(sockaddr_nl); + return true; +} + +static bool javaSocketAddressToSockaddr( + JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) { + if (javaSocketAddress == NULL) { + jniThrowNullPointerException(env, NULL); + return false; + } + + if (env->IsInstanceOf(javaSocketAddress, JniConstants::netlinkSocketAddressClass)) { + return javaNetlinkSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len); + } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) { + return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len); + } + jniThrowException(env, "java/lang/UnsupportedOperationException", + "unsupported SocketAddress subclass"); + return false; +} + static jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) { ScopedUtfChars path(env, javaPath); if (path.c_str() == NULL) { @@ -487,6 +542,19 @@ static void Posix_bind(JNIEnv* env, jobject, jobject javaFd, jobject javaAddress (void) NET_FAILURE_RETRY(env, int, bind, javaFd, sa, sa_len); } +static void Posix_bindSocketAddress( + JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) { + sockaddr_storage ss; + socklen_t sa_len; + if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) { + return; // Exception already thrown. + } + + const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss); + // We don't need the return value because we'll already have thrown. + (void) NET_FAILURE_RETRY(env, int, bind, javaFd, sa, sa_len); +} + static void Posix_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) { ScopedUtfChars path(env, javaPath); if (path.c_str() == NULL) { @@ -526,6 +594,19 @@ static void Posix_connect(JNIEnv* env, jobject, jobject javaFd, jobject javaAddr (void) NET_FAILURE_RETRY(env, int, connect, javaFd, sa, sa_len); } +static void Posix_connectSocketAddress( + JNIEnv* env, jobject, jobject javaFd, jobject javaSocketAddress) { + sockaddr_storage ss; + socklen_t sa_len; + if (!javaSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len)) { + return; // Exception already thrown. + } + + const sockaddr* sa = reinterpret_cast<const sockaddr*>(&ss); + // We don't need the return value because we'll already have thrown. + (void) NET_FAILURE_RETRY(env, int, connect, javaFd, sa, sa_len); +} + static jobject Posix_dup(JNIEnv* env, jobject, jobject javaOldFd) { int oldFd = jniGetFDFromFileDescriptor(env, javaOldFd); int newFd = throwIfMinusOne(env, "dup", TEMP_FAILURE_RETRY(dup(oldFd))); @@ -1587,15 +1668,20 @@ static jint Posix_writev(JNIEnv* env, jobject, jobject javaFd, jobjectArray buff return IO_FAILURE_RETRY(env, ssize_t, writev, javaFd, ioVec.get(), ioVec.size()); } +#define NATIVE_METHOD_OVERLOAD(className, functionName, signature, variant) \ + { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName ## variant) } + 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_OVERLOAD(Posix, bind, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress), NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"), NATIVE_METHOD(Posix, chown, "(Ljava/lang/String;II)V"), NATIVE_METHOD(Posix, close, "(Ljava/io/FileDescriptor;)V"), NATIVE_METHOD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/InetAddress;I)V"), + NATIVE_METHOD_OVERLOAD(Posix, connect, "(Ljava/io/FileDescriptor;Ljava/net/SocketAddress;)V", SocketAddress), NATIVE_METHOD(Posix, dup, "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;"), NATIVE_METHOD(Posix, dup2, "(Ljava/io/FileDescriptor;I)Ljava/io/FileDescriptor;"), NATIVE_METHOD(Posix, environ, "()[Ljava/lang/String;"), |