summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2015-03-16 11:06:48 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-03-16 11:06:48 +0000
commit1dacfbb464d8d21c312cca681a1a297e0f632f08 (patch)
tree2729e3e1c0f6e09f1d923c19aacfc297d1781913
parent1ab902acc995d6ef7a297959d57b6d8715a0bd2a (diff)
parent7d6411b79ecf1a6e2ed0e9a5af2113826e32030f (diff)
downloadlibcore-1dacfbb464d8d21c312cca681a1a297e0f632f08.zip
libcore-1dacfbb464d8d21c312cca681a1a297e0f632f08.tar.gz
libcore-1dacfbb464d8d21c312cca681a1a297e0f632f08.tar.bz2
am 7d6411b7: Merge "Support packet sockets in libcore."
* commit '7d6411b79ecf1a6e2ed0e9a5af2113826e32030f': Support packet sockets in libcore.
-rw-r--r--luni/src/main/java/android/system/OsConstants.java6
-rw-r--r--luni/src/main/native/android_system_OsConstants.cpp9
-rw-r--r--luni/src/main/native/libcore_io_Posix.cpp63
-rw-r--r--luni/src/test/java/libcore/io/OsTest.java22
4 files changed, 98 insertions, 2 deletions
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index acc4435..c0d31e5 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -96,6 +96,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();
+ /** @hide */ public static final int AF_PACKET = placeholder();
public static final int AF_UNIX = placeholder();
public static final int AF_UNSPEC = placeholder();
public static final int AI_ADDRCONFIG = placeholder();
@@ -105,6 +106,8 @@ public final class OsConstants {
public static final int AI_NUMERICSERV = placeholder();
public static final int AI_PASSIVE = placeholder();
public static final int AI_V4MAPPED = placeholder();
+ /** @hide */ public static final int ARPHRD_ETHER = placeholder();
+ /** @hide */ public static final int ARPHRD_LOOPBACK = placeholder();
public static final int CAP_AUDIT_CONTROL = placeholder();
public static final int CAP_AUDIT_WRITE = placeholder();
public static final int CAP_BLOCK_SUSPEND = placeholder();
@@ -228,6 +231,9 @@ public final class OsConstants {
public static final int ESPIPE = placeholder();
public static final int ESRCH = placeholder();
public static final int ESTALE = placeholder();
+ /** @hide */ public static final int ETH_P_ARP = placeholder();
+ /** @hide */ public static final int ETH_P_IP = placeholder();
+ /** @hide */ public static final int ETH_P_IPV6 = placeholder();
public static final int ETIME = placeholder();
public static final int ETIMEDOUT = placeholder();
public static final int ETXTBSY = placeholder();
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index 0c55305..a9031f4 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -38,6 +38,9 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <net/if_arp.h>
+#include <linux/if_ether.h>
+
// After the others because these are not necessarily self-contained in glibc.
#ifndef __APPLE__
#include <linux/if_addr.h>
@@ -58,6 +61,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_PACKET", AF_PACKET);
initConstant(env, c, "AF_NETLINK", AF_NETLINK);
initConstant(env, c, "AF_UNIX", AF_UNIX);
initConstant(env, c, "AF_UNSPEC", AF_UNSPEC);
@@ -70,6 +74,8 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) {
#endif
initConstant(env, c, "AI_PASSIVE", AI_PASSIVE);
initConstant(env, c, "AI_V4MAPPED", AI_V4MAPPED);
+ initConstant(env, c, "ARPHRD_ETHER", ARPHRD_ETHER);
+ initConstant(env, c, "ARPHRD_LOOPBACK", ARPHRD_LOOPBACK);
#if defined(CAP_LAST_CAP)
initConstant(env, c, "CAP_AUDIT_CONTROL", CAP_AUDIT_CONTROL);
initConstant(env, c, "CAP_AUDIT_WRITE", CAP_AUDIT_WRITE);
@@ -197,6 +203,9 @@ static void OsConstants_initConstants(JNIEnv* env, jclass c) {
initConstant(env, c, "ESPIPE", ESPIPE);
initConstant(env, c, "ESRCH", ESRCH);
initConstant(env, c, "ESTALE", ESTALE);
+ initConstant(env, c, "ETH_P_ARP", ETH_P_ARP);
+ initConstant(env, c, "ETH_P_IP", ETH_P_IP);
+ initConstant(env, c, "ETH_P_IPV6", ETH_P_IPV6);
initConstant(env, c, "ETIME", ETIME);
initConstant(env, c, "ETIMEDOUT", ETIMEDOUT);
initConstant(env, c, "ETXTBSY", ETXTBSY);
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index f41ffe6..12ac3f0 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -333,8 +333,26 @@ static jobject makeSocketAddress(JNIEnv* env, const sockaddr_storage& ss) {
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");
+ } else if (ss.ss_family == AF_PACKET) {
+ const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss);
+ static jmethodID ctor = env->GetMethodID(JniConstants::packetSocketAddressClass,
+ "<init>", "(SISB[B)V");
+ ScopedLocalRef<jbyteArray> byteArray(env, env->NewByteArray(sll->sll_halen));
+ if (byteArray.get() == NULL) {
+ return NULL;
+ }
+ env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen,
+ reinterpret_cast<const jbyte*>(sll->sll_addr));
+ jobject packetSocketAddress = env->NewObject(JniConstants::packetSocketAddressClass, ctor,
+ static_cast<jshort>(ntohs(sll->sll_protocol)),
+ static_cast<jint>(sll->sll_ifindex),
+ static_cast<jshort>(sll->sll_hatype),
+ static_cast<jbyte>(sll->sll_pkttype),
+ byteArray.get());
+ return packetSocketAddress;
+ }
+ jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", "unsupported ss_family: %d",
+ ss.ss_family);
return NULL;
}
@@ -472,6 +490,42 @@ static bool javaNetlinkSocketAddressToSockaddr(
return true;
}
+static bool javaPacketSocketAddressToSockaddr(
+ JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
+ static jfieldID protocolFid = env->GetFieldID(
+ JniConstants::packetSocketAddressClass, "sll_protocol", "S");
+ static jfieldID ifindexFid = env->GetFieldID(
+ JniConstants::packetSocketAddressClass, "sll_ifindex", "I");
+ static jfieldID hatypeFid = env->GetFieldID(
+ JniConstants::packetSocketAddressClass, "sll_hatype", "S");
+ static jfieldID pkttypeFid = env->GetFieldID(
+ JniConstants::packetSocketAddressClass, "sll_pkttype", "B");
+ static jfieldID addrFid = env->GetFieldID(
+ JniConstants::packetSocketAddressClass, "sll_addr", "[B");
+
+ sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss);
+ sll->sll_family = AF_PACKET;
+ sll->sll_protocol = ntohs(env->GetShortField(javaSocketAddress, protocolFid));
+ sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid);
+ sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid);
+ sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid);
+
+ jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid);
+ if (sllAddr == NULL) {
+ sll->sll_halen = 0;
+ memset(&sll->sll_addr, 0, sizeof(sll->sll_addr));
+ } else {
+ jsize len = env->GetArrayLength(sllAddr);
+ if ((size_t) len > sizeof(sll->sll_addr)) {
+ len = sizeof(sll->sll_addr);
+ }
+ sll->sll_halen = len;
+ env->GetByteArrayRegion(sllAddr, 0, len, (jbyte*) sll->sll_addr);
+ }
+ sa_len = sizeof(sockaddr_ll);
+ return true;
+}
+
static bool javaSocketAddressToSockaddr(
JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
if (javaSocketAddress == NULL) {
@@ -483,6 +537,8 @@ static bool javaSocketAddressToSockaddr(
return javaNetlinkSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
} else if (env->IsInstanceOf(javaSocketAddress, JniConstants::inetSocketAddressClass)) {
return javaInetSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
+ } else if (env->IsInstanceOf(javaSocketAddress, JniConstants::packetSocketAddressClass)) {
+ return javaPacketSocketAddressToSockaddr(env, javaSocketAddress, ss, sa_len);
}
jniThrowException(env, "java/lang/UnsupportedOperationException",
"unsupported SocketAddress subclass");
@@ -1599,6 +1655,9 @@ static void Posix_shutdown(JNIEnv* env, jobject, jobject javaFd, jint how) {
}
static jobject Posix_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) {
+ if (domain == AF_PACKET) {
+ protocol = htons(protocol); // Packet sockets specify the protocol in host byte order.
+ }
int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol)));
return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 5a9d436..3ebbfcd 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -18,6 +18,7 @@ package libcore.io;
import android.system.ErrnoException;
import android.system.NetlinkSocketAddress;
+import android.system.PacketSocketAddress;
import android.system.StructTimeval;
import android.system.StructUcred;
import java.io.File;
@@ -29,6 +30,7 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.InetUnixAddress;
+import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
@@ -291,6 +293,26 @@ public class OsTest extends TestCase {
Libcore.os.close(nlSocket);
}
+ public void test_PacketSocketAddress() throws Exception {
+ NetworkInterface lo = NetworkInterface.getByName("lo");
+ FileDescriptor fd = Libcore.os.socket(AF_PACKET, SOCK_DGRAM, (short) ETH_P_IPV6);
+ PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex());
+ Libcore.os.bind(fd, addr);
+
+ PacketSocketAddress bound = (PacketSocketAddress) Libcore.os.getsockname(fd);
+ assertEquals((short) ETH_P_IPV6, bound.sll_protocol);
+ assertEquals(lo.getIndex(), bound.sll_ifindex);
+ assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype);
+ assertEquals(0, bound.sll_pkttype);
+
+ // The loopback address is ETH_ALEN bytes long and is all zeros.
+ // http://lxr.free-electrons.com/source/drivers/net/loopback.c?v=3.10#L167
+ assertEquals(6, bound.sll_addr.length);
+ for (int i = 0; i < 6; i++) {
+ assertEquals(0, bound.sll_addr[i]);
+ }
+ }
+
public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception {
checkByteBufferPositions_sendto_recvfrom(AF_INET, InetAddress.getByName("127.0.0.1"));
}