Loading services/net/java/android/net/apf/ApfFilter.java +1 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ public class ApfFilter { * the last writable 32bit word. */ @VisibleForTesting private static enum Counter { public static enum Counter { RESERVED_OOB, // Points to offset 0 from the end of the buffer (out-of-bounds) TOTAL_PACKETS, PASSED_ARP, Loading tests/net/java/android/net/apf/ApfTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.support.test.runner.AndroidJUnit4; import android.system.ErrnoException; import android.system.Os; import android.text.format.DateUtils; import android.util.Log; import com.android.frameworks.tests.net.R; import com.android.internal.util.HexDump; import java.io.File; Loading Loading @@ -89,6 +90,7 @@ public class ApfTest { System.loadLibrary("frameworksnettestsjni"); } private static final String TAG = "ApfTest"; // Expected return codes from APF interpreter. private static final int PASS = 1; private static final int DROP = 0; Loading Loading @@ -869,6 +871,37 @@ public class ApfTest { } } /** * Generate APF program, run pcap file though APF filter, then check all the packets in the file * should be dropped. */ @Test public void testApfFilterPcapFile() throws Exception { final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151}; String pcapFilename = stageFile(R.raw.apfPcap); MockIpClientCallback ipClientCallback = new MockIpClientCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); ApfConfiguration config = getDefaultConfig(); ApfCapabilities MOCK_APF_PCAP_CAPABILITIES = new ApfCapabilities(4, 1700, ARPHRD_ETHER); config.apfCapabilities = MOCK_APF_PCAP_CAPABILITIES; config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipClientCallback.getApfProgram(); byte[] data = new byte[ApfFilter.Counter.totalSize()]; final boolean result; result = dropsAllPackets(program, data, pcapFilename); Log.i(TAG, "testApfFilterPcapFile(): Data counters: " + HexDump.toHexString(data, false)); assertTrue("Failed to drop all packets by filter. \nAPF counters:" + HexDump.toHexString(data, false), result); } private class MockIpClientCallback extends IpClient.Callback { private final ConditionVariable mGotApfProgram = new ConditionVariable(); private byte[] mLastApfProgram; Loading Loading @@ -1706,6 +1739,14 @@ public class ApfTest { private native static boolean compareBpfApf(String filter, String pcap_filename, byte[] apf_program); /** * Open packet capture file {@code pcapFilename} and run it through APF filter. Then * checks whether all the packets are dropped and populates data[] {@code data} with * the APF counters. */ private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename); @Test public void testBroadcastAddress() throws Exception { assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); Loading tests/net/jni/apf_jni.cpp +74 −27 Original line number Diff line number Diff line Loading @@ -21,37 +21,40 @@ #include <stdlib.h> #include <string> #include <utils/Log.h> #include <vector> #include "apf_interpreter.h" #include "nativehelper/scoped_primitive_array.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) // JNI function acting as simply call-through to native APF interpreter. static jint com_android_server_ApfTest_apfSimulate( JNIEnv* env, jclass, jbyteArray program, jbyteArray packet, jbyteArray data, jint filter_age) { uint8_t* program_raw = (uint8_t*)env->GetByteArrayElements(program, nullptr); uint8_t* packet_raw = (uint8_t*)env->GetByteArrayElements(packet, nullptr); uint8_t* data_raw = (uint8_t*)(data ? env->GetByteArrayElements(data, nullptr) : nullptr); uint32_t program_len = env->GetArrayLength(program); uint32_t packet_len = env->GetArrayLength(packet); uint32_t data_len = data ? env->GetArrayLength(data) : 0; JNIEnv* env, jclass, jbyteArray jprogram, jbyteArray jpacket, jbyteArray jdata, jint filter_age) { ScopedByteArrayRO packet(env, jpacket); uint32_t packet_len = (uint32_t)packet.size(); uint32_t program_len = env->GetArrayLength(jprogram); uint32_t data_len = jdata ? env->GetArrayLength(jdata) : 0; std::vector<uint8_t> buf(program_len + data_len, 0); env->GetByteArrayRegion(jprogram, 0, program_len, reinterpret_cast<jbyte*>(buf.data())); if (jdata) { // Merge program and data into a single buffer. uint8_t* program_and_data = (uint8_t*)malloc(program_len + data_len); memcpy(program_and_data, program_raw, program_len); memcpy(program_and_data + program_len, data_raw, data_len); env->GetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + program_len)); } jint result = accept_packet(program_and_data, program_len, program_len + data_len, packet_raw, packet_len, filter_age); if (data) { memcpy(data_raw, program_and_data + program_len, data_len); env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */); } free(program_and_data); env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT); env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT); accept_packet(buf.data(), program_len, program_len + data_len, reinterpret_cast<const uint8_t*>(packet.get()), packet_len, filter_age); if (jdata) { env->SetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + program_len)); } return result; } Loading Loading @@ -118,8 +121,7 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js jstring jpcap_filename, jbyteArray japf_program) { ScopedUtfChars filter(env, jfilter); ScopedUtfChars pcap_filename(env, jpcap_filename); uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL); uint32_t apf_program_len = env->GetArrayLength(japf_program); ScopedByteArrayRO apf_program(env, japf_program); // Open pcap file for BPF filtering ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb")); Loading Loading @@ -161,7 +163,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js do { apf_packet = pcap_next(apf_pcap.get(), &apf_header); } while (apf_packet != NULL && !accept_packet( apf_program, apf_program_len, 0 /* data_len */, reinterpret_cast<uint8_t*>(const_cast<int8_t*>(apf_program.get())), apf_program.size(), 0 /* data_len */, apf_packet, apf_header.len, 0 /* filter_age */)); // Make sure both filters matched the same packet. Loading @@ -178,6 +181,48 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js return true; } static jboolean com_android_server_ApfTest_dropsAllPackets(JNIEnv* env, jclass, jbyteArray jprogram, jbyteArray jdata, jstring jpcap_filename) { ScopedUtfChars pcap_filename(env, jpcap_filename); ScopedByteArrayRO apf_program(env, jprogram); uint32_t apf_program_len = (uint32_t)apf_program.size(); uint32_t data_len = env->GetArrayLength(jdata); pcap_pkthdr apf_header; const uint8_t* apf_packet; char pcap_error[PCAP_ERRBUF_SIZE]; std::vector<uint8_t> buf(apf_program_len + data_len, 0); // Merge program and data into a single buffer. env->GetByteArrayRegion(jprogram, 0, apf_program_len, reinterpret_cast<jbyte*>(buf.data())); env->GetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + apf_program_len)); // Open pcap file ScopedFILE apf_fp(fopen(pcap_filename.c_str(), "rb")); ScopedPcap apf_pcap(pcap_fopen_offline(apf_fp.get(), pcap_error)); if (apf_pcap.get() == NULL) { throwException(env, "pcap_fopen_offline failed: " + std::string(pcap_error)); return false; } while ((apf_packet = pcap_next(apf_pcap.get(), &apf_header)) != NULL) { int result = accept_packet(buf.data(), apf_program_len, apf_program_len + data_len, apf_packet, apf_header.len, 0); // Return false once packet passes the filter if (result) { env->SetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + apf_program_len)); return false; } } env->SetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + apf_program_len)); return true; } extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { Loading @@ -192,6 +237,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { (void*)com_android_server_ApfTest_compileToBpf }, { "compareBpfApf", "(Ljava/lang/String;Ljava/lang/String;[B)Z", (void*)com_android_server_ApfTest_compareBpfApf }, { "dropsAllPackets", "([B[BLjava/lang/String;)Z", (void*)com_android_server_ApfTest_dropsAllPackets }, }; jniRegisterNativeMethods(env, "android/net/apf/ApfTest", Loading tests/net/res/raw/apfPcap.pcap 0 → 100644 +99.2 KiB File added.No diff preview for this file type. View file Loading
services/net/java/android/net/apf/ApfFilter.java +1 −1 Original line number Diff line number Diff line Loading @@ -111,7 +111,7 @@ public class ApfFilter { * the last writable 32bit word. */ @VisibleForTesting private static enum Counter { public static enum Counter { RESERVED_OOB, // Points to offset 0 from the end of the buffer (out-of-bounds) TOTAL_PACKETS, PASSED_ARP, Loading
tests/net/java/android/net/apf/ApfTest.java +41 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.support.test.runner.AndroidJUnit4; import android.system.ErrnoException; import android.system.Os; import android.text.format.DateUtils; import android.util.Log; import com.android.frameworks.tests.net.R; import com.android.internal.util.HexDump; import java.io.File; Loading Loading @@ -89,6 +90,7 @@ public class ApfTest { System.loadLibrary("frameworksnettestsjni"); } private static final String TAG = "ApfTest"; // Expected return codes from APF interpreter. private static final int PASS = 1; private static final int DROP = 0; Loading Loading @@ -869,6 +871,37 @@ public class ApfTest { } } /** * Generate APF program, run pcap file though APF filter, then check all the packets in the file * should be dropped. */ @Test public void testApfFilterPcapFile() throws Exception { final byte[] MOCK_PCAP_IPV4_ADDR = {(byte) 172, 16, 7, (byte) 151}; String pcapFilename = stageFile(R.raw.apfPcap); MockIpClientCallback ipClientCallback = new MockIpClientCallback(); LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_PCAP_IPV4_ADDR), 16); LinkProperties lp = new LinkProperties(); lp.addLinkAddress(link); ApfConfiguration config = getDefaultConfig(); ApfCapabilities MOCK_APF_PCAP_CAPABILITIES = new ApfCapabilities(4, 1700, ARPHRD_ETHER); config.apfCapabilities = MOCK_APF_PCAP_CAPABILITIES; config.multicastFilter = DROP_MULTICAST; config.ieee802_3Filter = DROP_802_3_FRAMES; TestApfFilter apfFilter = new TestApfFilter(mContext, config, ipClientCallback, mLog); apfFilter.setLinkProperties(lp); byte[] program = ipClientCallback.getApfProgram(); byte[] data = new byte[ApfFilter.Counter.totalSize()]; final boolean result; result = dropsAllPackets(program, data, pcapFilename); Log.i(TAG, "testApfFilterPcapFile(): Data counters: " + HexDump.toHexString(data, false)); assertTrue("Failed to drop all packets by filter. \nAPF counters:" + HexDump.toHexString(data, false), result); } private class MockIpClientCallback extends IpClient.Callback { private final ConditionVariable mGotApfProgram = new ConditionVariable(); private byte[] mLastApfProgram; Loading Loading @@ -1706,6 +1739,14 @@ public class ApfTest { private native static boolean compareBpfApf(String filter, String pcap_filename, byte[] apf_program); /** * Open packet capture file {@code pcapFilename} and run it through APF filter. Then * checks whether all the packets are dropped and populates data[] {@code data} with * the APF counters. */ private native static boolean dropsAllPackets(byte[] program, byte[] data, String pcapFilename); @Test public void testBroadcastAddress() throws Exception { assertEqualsIp("255.255.255.255", ApfFilter.ipv4BroadcastAddress(IPV4_ANY_HOST_ADDR, 0)); Loading
tests/net/jni/apf_jni.cpp +74 −27 Original line number Diff line number Diff line Loading @@ -21,37 +21,40 @@ #include <stdlib.h> #include <string> #include <utils/Log.h> #include <vector> #include "apf_interpreter.h" #include "nativehelper/scoped_primitive_array.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) // JNI function acting as simply call-through to native APF interpreter. static jint com_android_server_ApfTest_apfSimulate( JNIEnv* env, jclass, jbyteArray program, jbyteArray packet, jbyteArray data, jint filter_age) { uint8_t* program_raw = (uint8_t*)env->GetByteArrayElements(program, nullptr); uint8_t* packet_raw = (uint8_t*)env->GetByteArrayElements(packet, nullptr); uint8_t* data_raw = (uint8_t*)(data ? env->GetByteArrayElements(data, nullptr) : nullptr); uint32_t program_len = env->GetArrayLength(program); uint32_t packet_len = env->GetArrayLength(packet); uint32_t data_len = data ? env->GetArrayLength(data) : 0; JNIEnv* env, jclass, jbyteArray jprogram, jbyteArray jpacket, jbyteArray jdata, jint filter_age) { ScopedByteArrayRO packet(env, jpacket); uint32_t packet_len = (uint32_t)packet.size(); uint32_t program_len = env->GetArrayLength(jprogram); uint32_t data_len = jdata ? env->GetArrayLength(jdata) : 0; std::vector<uint8_t> buf(program_len + data_len, 0); env->GetByteArrayRegion(jprogram, 0, program_len, reinterpret_cast<jbyte*>(buf.data())); if (jdata) { // Merge program and data into a single buffer. uint8_t* program_and_data = (uint8_t*)malloc(program_len + data_len); memcpy(program_and_data, program_raw, program_len); memcpy(program_and_data + program_len, data_raw, data_len); env->GetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + program_len)); } jint result = accept_packet(program_and_data, program_len, program_len + data_len, packet_raw, packet_len, filter_age); if (data) { memcpy(data_raw, program_and_data + program_len, data_len); env->ReleaseByteArrayElements(data, (jbyte*)data_raw, 0 /* copy back */); } free(program_and_data); env->ReleaseByteArrayElements(packet, (jbyte*)packet_raw, JNI_ABORT); env->ReleaseByteArrayElements(program, (jbyte*)program_raw, JNI_ABORT); accept_packet(buf.data(), program_len, program_len + data_len, reinterpret_cast<const uint8_t*>(packet.get()), packet_len, filter_age); if (jdata) { env->SetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + program_len)); } return result; } Loading Loading @@ -118,8 +121,7 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js jstring jpcap_filename, jbyteArray japf_program) { ScopedUtfChars filter(env, jfilter); ScopedUtfChars pcap_filename(env, jpcap_filename); uint8_t* apf_program = (uint8_t*)env->GetByteArrayElements(japf_program, NULL); uint32_t apf_program_len = env->GetArrayLength(japf_program); ScopedByteArrayRO apf_program(env, japf_program); // Open pcap file for BPF filtering ScopedFILE bpf_fp(fopen(pcap_filename.c_str(), "rb")); Loading Loading @@ -161,7 +163,8 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js do { apf_packet = pcap_next(apf_pcap.get(), &apf_header); } while (apf_packet != NULL && !accept_packet( apf_program, apf_program_len, 0 /* data_len */, reinterpret_cast<uint8_t*>(const_cast<int8_t*>(apf_program.get())), apf_program.size(), 0 /* data_len */, apf_packet, apf_header.len, 0 /* filter_age */)); // Make sure both filters matched the same packet. Loading @@ -178,6 +181,48 @@ static jboolean com_android_server_ApfTest_compareBpfApf(JNIEnv* env, jclass, js return true; } static jboolean com_android_server_ApfTest_dropsAllPackets(JNIEnv* env, jclass, jbyteArray jprogram, jbyteArray jdata, jstring jpcap_filename) { ScopedUtfChars pcap_filename(env, jpcap_filename); ScopedByteArrayRO apf_program(env, jprogram); uint32_t apf_program_len = (uint32_t)apf_program.size(); uint32_t data_len = env->GetArrayLength(jdata); pcap_pkthdr apf_header; const uint8_t* apf_packet; char pcap_error[PCAP_ERRBUF_SIZE]; std::vector<uint8_t> buf(apf_program_len + data_len, 0); // Merge program and data into a single buffer. env->GetByteArrayRegion(jprogram, 0, apf_program_len, reinterpret_cast<jbyte*>(buf.data())); env->GetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + apf_program_len)); // Open pcap file ScopedFILE apf_fp(fopen(pcap_filename.c_str(), "rb")); ScopedPcap apf_pcap(pcap_fopen_offline(apf_fp.get(), pcap_error)); if (apf_pcap.get() == NULL) { throwException(env, "pcap_fopen_offline failed: " + std::string(pcap_error)); return false; } while ((apf_packet = pcap_next(apf_pcap.get(), &apf_header)) != NULL) { int result = accept_packet(buf.data(), apf_program_len, apf_program_len + data_len, apf_packet, apf_header.len, 0); // Return false once packet passes the filter if (result) { env->SetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + apf_program_len)); return false; } } env->SetByteArrayRegion(jdata, 0, data_len, reinterpret_cast<jbyte*>(buf.data() + apf_program_len)); return true; } extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { JNIEnv *env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { Loading @@ -192,6 +237,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { (void*)com_android_server_ApfTest_compileToBpf }, { "compareBpfApf", "(Ljava/lang/String;Ljava/lang/String;[B)Z", (void*)com_android_server_ApfTest_compareBpfApf }, { "dropsAllPackets", "([B[BLjava/lang/String;)Z", (void*)com_android_server_ApfTest_dropsAllPackets }, }; jniRegisterNativeMethods(env, "android/net/apf/ApfTest", Loading
tests/net/res/raw/apfPcap.pcap 0 → 100644 +99.2 KiB File added.No diff preview for this file type. View file