use of android.net.apf.ApfGenerator in project android_frameworks_base by DirtyUnicorns.
the class Bpf2Apf method main.
/**
* Convert the output of "tcpdump -d" (human readable BPF program dump) piped in stdin into an
* APF program and output it via stdout.
*/
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
StringBuilder responseData = new StringBuilder();
ApfGenerator gen = new ApfGenerator();
while ((line = in.readLine()) != null) convertLine(line, gen);
System.out.write(gen.generate());
}
use of android.net.apf.ApfGenerator in project android_frameworks_base by crdroidandroid.
the class ApfFilter method beginProgramLocked.
/**
* Begin generating an APF program to:
* <ul>
* <li>Drop ARP requests not for us, if mIPv4Address is set,
* <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
* <li>Drop IPv4 multicast packets, if mMulticastFilter,
* <li>Pass all other IPv4 packets,
* <li>Drop all broadcast non-IP non-ARP packets.
* <li>Pass all non-ICMPv6 IPv6 packets,
* <li>Pass all non-IPv4 and non-IPv6 packets,
* <li>Drop IPv6 ICMPv6 NAs to ff02::1.
* <li>Drop IPv6 ICMPv6 RSs.
* <li>Let execution continue off the end of the program for IPv6 ICMPv6 packets. This allows
* insertion of RA filters here, or if there aren't any, just passes the packets.
* </ul>
*/
@GuardedBy("this")
private ApfGenerator beginProgramLocked() throws IllegalInstructionException {
ApfGenerator gen = new ApfGenerator();
// This is guaranteed to return true because of the check in maybeCreate.
gen.setApfVersion(mApfCapabilities.apfVersionSupported);
// Here's a basic summary of what the initial program does:
//
// if it's ARP:
// insert ARP filter to drop or pass these appropriately
// if it's IPv4:
// insert IPv4 filter to drop or pass these appropriately
// if it's not IPv6:
// if it's broadcast:
// drop
// pass
// insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets
// Add ARP filters:
String skipArpFiltersLabel = "skipArpFilters";
gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
generateArpFilterLocked(gen);
gen.defineLabel(skipArpFiltersLabel);
// Add IPv4 filters:
String skipIPv4FiltersLabel = "skipIPv4Filters";
// NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
// execute the ARP filter, since that filter does not fall through, but either drops or
// passes.
gen.addJumpIfR0NotEquals(ETH_P_IP, skipIPv4FiltersLabel);
generateIPv4FilterLocked(gen);
gen.defineLabel(skipIPv4FiltersLabel);
// Check for IPv6:
// NOTE: Relies on R0 containing ethertype. This is safe because if we got here, we did not
// execute the ARP or IPv4 filters, since those filters do not fall through, but either
// drop or pass.
String ipv6FilterLabel = "IPv6Filters";
gen.addJumpIfR0Equals(ETH_P_IPV6, ipv6FilterLabel);
// Drop non-IP non-ARP broadcasts, pass the rest
gen.addLoadImmediate(Register.R0, ETH_DEST_ADDR_OFFSET);
gen.addJumpIfBytesNotEqual(Register.R0, ETH_BROADCAST_MAC_ADDRESS, gen.PASS_LABEL);
gen.addJump(gen.DROP_LABEL);
// Add IPv6 filters:
gen.defineLabel(ipv6FilterLabel);
generateIPv6FilterLocked(gen);
return gen;
}
use of android.net.apf.ApfGenerator in project android_frameworks_base by crdroidandroid.
the class ApfFilter method installNewProgramLocked.
/**
* Generate and install a new filter program.
*/
@GuardedBy("this")
@VisibleForTesting
void installNewProgramLocked() {
purgeExpiredRasLocked();
ArrayList<Ra> rasToFilter = new ArrayList<>();
final byte[] program;
long programMinLifetime = Long.MAX_VALUE;
try {
// Step 1: Determine how many RA filters we can fit in the program.
ApfGenerator gen = beginProgramLocked();
for (Ra ra : mRas) {
ra.generateFilterLocked(gen);
// Stop if we get too big.
if (gen.programLengthOverEstimate() > mApfCapabilities.maximumApfProgramSize)
break;
rasToFilter.add(ra);
}
// Step 2: Actually generate the program
gen = beginProgramLocked();
for (Ra ra : rasToFilter) {
programMinLifetime = Math.min(programMinLifetime, ra.generateFilterLocked(gen));
}
// Execution will reach the end of the program if no filters match, which will pass the
// packet to the AP.
program = gen.generate();
} catch (IllegalInstructionException e) {
Log.e(TAG, "Program failed to generate: ", e);
return;
}
mLastTimeInstalledProgram = curTime();
mLastInstalledProgramMinLifetime = programMinLifetime;
mLastInstalledProgram = program;
mNumProgramUpdates++;
if (VDBG) {
hexDump("Installing filter: ", program, program.length);
}
mIpManagerCallback.installPacketFilter(program);
int flags = ApfProgramEvent.flagsFor(mIPv4Address != null, mMulticastFilter);
mMetricsLog.log(new ApfProgramEvent(programMinLifetime, rasToFilter.size(), mRas.size(), program.length, flags));
}
use of android.net.apf.ApfGenerator in project android_frameworks_base by crdroidandroid.
the class ApfTest method testApfInstructions.
/**
* Test each instruction by generating a program containing the instruction,
* generating bytecode for that program and running it through the
* interpreter to verify it functions correctly.
*/
@LargeTest
public void testApfInstructions() throws IllegalInstructionException {
// Empty program should pass because having the program counter reach the
// location immediately after the program indicates the packet should be
// passed to the AP.
ApfGenerator gen = new ApfGenerator();
assertPass(gen);
// Test jumping to pass label.
gen = new ApfGenerator();
gen.addJump(gen.PASS_LABEL);
byte[] program = gen.generate();
assertEquals(1, program.length);
assertEquals((14 << 3) | (0 << 1) | 0, program[0]);
assertPass(program, new byte[MIN_PKT_SIZE], 0);
// Test jumping to drop label.
gen = new ApfGenerator();
gen.addJump(gen.DROP_LABEL);
program = gen.generate();
assertEquals(2, program.length);
assertEquals((14 << 3) | (1 << 1) | 0, program[0]);
assertEquals(1, program[1]);
assertDrop(program, new byte[15], 15);
// Test jumping if equal to 0.
gen = new ApfGenerator();
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if not equal to 0.
gen = new ApfGenerator();
gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0NotEquals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if registers equal.
gen = new ApfGenerator();
gen.addJumpIfR0EqualsR1(gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if registers not equal.
gen = new ApfGenerator();
gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0NotEqualsR1(gen.DROP_LABEL);
assertDrop(gen);
// Test load immediate.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test add.
gen = new ApfGenerator();
gen.addAdd(1234567890);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test subtract.
gen = new ApfGenerator();
gen.addAdd(-1234567890);
gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test or.
gen = new ApfGenerator();
gen.addOr(1234567890);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test and.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addAnd(123456789);
gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
assertDrop(gen);
// Test left shift.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLeftShift(1);
gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
assertDrop(gen);
// Test right shift.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addRightShift(1);
gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
assertDrop(gen);
// Test multiply.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addMul(2);
gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
assertDrop(gen);
// Test divide.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addDiv(2);
gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
assertDrop(gen);
// Test divide by zero.
gen = new ApfGenerator();
gen.addDiv(0);
gen.addJump(gen.DROP_LABEL);
assertPass(gen);
// Test add.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addAddR1();
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test subtract.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, -1234567890);
gen.addAddR1();
gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test or.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addOrR1();
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test and.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 123456789);
gen.addAndR1();
gen.addJumpIfR0Equals(1234567890 & 123456789, gen.DROP_LABEL);
assertDrop(gen);
// Test left shift.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 1);
gen.addLeftShiftR1();
gen.addJumpIfR0Equals(1234567890 << 1, gen.DROP_LABEL);
assertDrop(gen);
// Test right shift.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, -1);
gen.addLeftShiftR1();
gen.addJumpIfR0Equals(1234567890 >> 1, gen.DROP_LABEL);
assertDrop(gen);
// Test multiply.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 2);
gen.addMulR1();
gen.addJumpIfR0Equals(1234567890 * 2, gen.DROP_LABEL);
assertDrop(gen);
// Test divide.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addLoadImmediate(Register.R1, 2);
gen.addDivR1();
gen.addJumpIfR0Equals(1234567890 / 2, gen.DROP_LABEL);
assertDrop(gen);
// Test divide by zero.
gen = new ApfGenerator();
gen.addDivR1();
gen.addJump(gen.DROP_LABEL);
assertPass(gen);
// Test byte load.
gen = new ApfGenerator();
gen.addLoad8(Register.R0, 1);
gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 123, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test out of bounds load.
gen = new ApfGenerator();
gen.addLoad8(Register.R0, 16);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertPass(gen, new byte[] { 123, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test half-word load.
gen = new ApfGenerator();
gen.addLoad16(Register.R0, 1);
gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 123, 45, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test word load.
gen = new ApfGenerator();
gen.addLoad32(Register.R0, 1);
gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 123, 45, 67, 89, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test byte indexed load.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1);
gen.addLoad8Indexed(Register.R0, 0);
gen.addJumpIfR0Equals(45, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 123, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test out of bounds indexed load.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 8);
gen.addLoad8Indexed(Register.R0, 8);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertPass(gen, new byte[] { 123, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test half-word indexed load.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1);
gen.addLoad16Indexed(Register.R0, 0);
gen.addJumpIfR0Equals((45 << 8) | 67, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 123, 45, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test word indexed load.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1);
gen.addLoad32Indexed(Register.R0, 0);
gen.addJumpIfR0Equals((45 << 24) | (67 << 16) | (89 << 8) | 12, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 123, 45, 67, 89, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
// Test jumping if greater than.
gen = new ApfGenerator();
gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0GreaterThan(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if less than.
gen = new ApfGenerator();
gen.addJumpIfR0LessThan(0, gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addJumpIfR0LessThan(1, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if any bits set.
gen = new ApfGenerator();
gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
assertDrop(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 3);
gen.addJumpIfR0AnyBitsSet(3, gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if register greater than.
gen = new ApfGenerator();
gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 2);
gen.addLoadImmediate(Register.R1, 1);
gen.addJumpIfR0GreaterThanR1(gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if register less than.
gen = new ApfGenerator();
gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1);
gen.addJumpIfR0LessThanR1(gen.DROP_LABEL);
assertDrop(gen);
// Test jumping if any bits set in register.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 3);
gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
assertPass(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 3);
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
assertDrop(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 3);
gen.addLoadImmediate(Register.R0, 3);
gen.addJumpIfR0AnyBitsSetR1(gen.DROP_LABEL);
assertDrop(gen);
// Test load from memory.
gen = new ApfGenerator();
gen.addLoadFromMemory(Register.R0, 0);
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test store to memory.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addStoreToMemory(Register.R1, 12);
gen.addLoadFromMemory(Register.R0, 12);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test filter age pre-filled memory.
gen = new ApfGenerator();
gen.addLoadFromMemory(Register.R0, gen.FILTER_AGE_MEMORY_SLOT);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen, new byte[MIN_PKT_SIZE], 1234567890);
// Test packet size pre-filled memory.
gen = new ApfGenerator();
gen.addLoadFromMemory(Register.R0, gen.PACKET_SIZE_MEMORY_SLOT);
gen.addJumpIfR0Equals(MIN_PKT_SIZE, gen.DROP_LABEL);
assertDrop(gen);
// Test IPv4 header size pre-filled memory.
gen = new ApfGenerator();
gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
gen.addJumpIfR0Equals(20, gen.DROP_LABEL);
assertDrop(gen, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x45 }, 0);
// Test not.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addNot(Register.R0);
gen.addJumpIfR0Equals(~1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test negate.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addNeg(Register.R0);
gen.addJumpIfR0Equals(-1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test move.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addMove(Register.R0);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addMove(Register.R1);
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
// Test swap.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R1, 1234567890);
gen.addSwap();
gen.addJumpIfR0Equals(1234567890, gen.DROP_LABEL);
assertDrop(gen);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1234567890);
gen.addSwap();
gen.addJumpIfR0Equals(0, gen.DROP_LABEL);
assertDrop(gen);
// Test jump if bytes not equal.
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[] { 123 }, gen.DROP_LABEL);
program = gen.generate();
assertEquals(6, program.length);
assertEquals((13 << 3) | (1 << 1) | 0, program[0]);
assertEquals(1, program[1]);
assertEquals(((20 << 3) | (1 << 1) | 0) - 256, program[2]);
assertEquals(1, program[3]);
assertEquals(1, program[4]);
assertEquals(123, program[5]);
assertDrop(program, new byte[MIN_PKT_SIZE], 0);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[] { 123 }, gen.DROP_LABEL);
byte[] packet123 = { 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
assertPass(gen, packet123, 0);
gen = new ApfGenerator();
gen.addJumpIfBytesNotEqual(Register.R0, new byte[] { 123 }, gen.DROP_LABEL);
assertDrop(gen, packet123, 0);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[] { 1, 2, 30, 4, 5 }, gen.DROP_LABEL);
byte[] packet12345 = { 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
assertDrop(gen, packet12345, 0);
gen = new ApfGenerator();
gen.addLoadImmediate(Register.R0, 1);
gen.addJumpIfBytesNotEqual(Register.R0, new byte[] { 1, 2, 3, 4, 5 }, gen.DROP_LABEL);
assertPass(gen, packet12345, 0);
}
use of android.net.apf.ApfGenerator in project android_frameworks_base by crdroidandroid.
the class Bpf2Apf method main.
/**
* Convert the output of "tcpdump -d" (human readable BPF program dump) piped in stdin into an
* APF program and output it via stdout.
*/
public static void main(String[] args) throws Exception {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line = null;
StringBuilder responseData = new StringBuilder();
ApfGenerator gen = new ApfGenerator();
while ((line = in.readLine()) != null) convertLine(line, gen);
System.out.write(gen.generate());
}
Aggregations