Merge "More APF debuggability." into nyc-dev

am: 6ad205b

* commit '6ad205b66d9b13479a84f113a43af4966b479d52':
  More APF debuggability.

Change-Id: If939093a15fbb3472e9672a668c4feecf55c948a
This commit is contained in:
Lorenzo Colitti
2016-04-09 10:18:23 +00:00
committed by android-build-merger

View File

@@ -252,15 +252,22 @@ public class ApfFilter {
long mLastSeen; long mLastSeen;
// For debugging only. Offsets into the packet where PIOs are. // For debugging only. Offsets into the packet where PIOs are.
private final ArrayList<Integer> mPrefixOptionOffsets; private final ArrayList<Integer> mPrefixOptionOffsets = new ArrayList<>();
// For debugging only. Offsets into the packet where RDNSS options are.
private final ArrayList<Integer> mRdnssOptionOffsets = new ArrayList<>();
// For debugging only. How many times this RA was seen. // For debugging only. How many times this RA was seen.
int seenCount = 0; int seenCount = 0;
// For debugging only. Returns the hex representation of the last matching packet. // For debugging only. Returns the hex representation of the last matching packet.
String getLastMatchingPacket() { String getLastMatchingPacket() {
return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(), false /* lowercase */); return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(),
false /* lowercase */);
} }
// For debugging only. Returns the string representation of the IPv6 address starting at
// position pos in the packet.
private String IPv6AddresstoString(int pos) { private String IPv6AddresstoString(int pos) {
try { try {
byte[] array = mPacket.array(); byte[] array = mPacket.array();
@@ -295,19 +302,37 @@ public class ApfFilter {
return s & 0xffffffff; return s & 0xffffffff;
} }
private void prefixOptionToString(StringBuffer sb, int offset) {
String prefix = IPv6AddresstoString(offset + 16);
int length = uint8(mPacket.get(offset + 2));
long valid = mPacket.getInt(offset + 4);
long preferred = mPacket.getInt(offset + 8);
sb.append(String.format("%s/%d %ds/%ds ", prefix, length, valid, preferred));
}
private void rdnssOptionToString(StringBuffer sb, int offset) {
int optLen = uint8(mPacket.get(offset + 1)) * 8;
if (optLen < 24) return; // Malformed or empty.
long lifetime = uint32(mPacket.getInt(offset + 4));
int numServers = (optLen - 8) / 16;
sb.append("DNS ").append(lifetime).append("s");
for (int server = 0; server < numServers; server++) {
sb.append(" ").append(IPv6AddresstoString(offset + 8 + 16 * server));
}
}
public String toString() { public String toString() {
try { try {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
sb.append(String.format("RA %s -> %s %d ", sb.append(String.format("RA %s -> %s %ds ",
IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET), IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET),
IPv6AddresstoString(IPV6_DEST_ADDR_OFFSET), IPv6AddresstoString(IPV6_DEST_ADDR_OFFSET),
uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET)))); uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET))));
for (int i: mPrefixOptionOffsets) { for (int i: mPrefixOptionOffsets) {
String prefix = IPv6AddresstoString(i + 16); prefixOptionToString(sb, i);
int length = uint8(mPacket.get(i + 2)); }
long valid = mPacket.getInt(i + 4); for (int i: mRdnssOptionOffsets) {
long preferred = mPacket.getInt(i + 8); rdnssOptionToString(sb, i);
sb.append(String.format("%s/%d %d/%d ", prefix, length, valid, preferred));
} }
return sb.toString(); return sb.toString();
} catch (BufferUnderflowException | IndexOutOfBoundsException e) { } catch (BufferUnderflowException | IndexOutOfBoundsException e) {
@@ -352,8 +377,7 @@ public class ApfFilter {
ICMP6_RA_ROUTER_LIFETIME_OFFSET, ICMP6_RA_ROUTER_LIFETIME_OFFSET,
ICMP6_RA_ROUTER_LIFETIME_LEN); ICMP6_RA_ROUTER_LIFETIME_LEN);
// Parse ICMPv6 options // Ensures that the RA is not truncated.
mPrefixOptionOffsets = new ArrayList<>();
mPacket.position(ICMP6_RA_OPTION_OFFSET); mPacket.position(ICMP6_RA_OPTION_OFFSET);
while (mPacket.hasRemaining()) { while (mPacket.hasRemaining()) {
int optionType = ((int)mPacket.get(mPacket.position())) & 0xff; int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
@@ -372,8 +396,10 @@ public class ApfFilter {
break; break;
// These three options have the same lifetime offset and size, so process // These three options have the same lifetime offset and size, so process
// together: // together:
case ICMP6_ROUTE_INFO_OPTION_TYPE:
case ICMP6_RDNSS_OPTION_TYPE: case ICMP6_RDNSS_OPTION_TYPE:
mRdnssOptionOffsets.add(mPacket.position());
// Fall through.
case ICMP6_ROUTE_INFO_OPTION_TYPE:
case ICMP6_DNSSL_OPTION_TYPE: case ICMP6_DNSSL_OPTION_TYPE:
// Parse lifetime // Parse lifetime
lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart, lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
@@ -520,6 +546,10 @@ public class ApfFilter {
@GuardedBy("this") @GuardedBy("this")
private byte[] mLastInstalledProgram; private byte[] mLastInstalledProgram;
// For debugging only. How many times the program was updated since we started.
@GuardedBy("this")
private int mNumProgramUpdates;
/** /**
* Generate filter code to process ARP packets. Execution of this code ends in either the * Generate filter code to process ARP packets. Execution of this code ends in either the
* DROP_LABEL or PASS_LABEL and does not fall off the end. * DROP_LABEL or PASS_LABEL and does not fall off the end.
@@ -724,6 +754,8 @@ public class ApfFilter {
mLastTimeInstalledProgram = curTime(); mLastTimeInstalledProgram = curTime();
mLastInstalledProgramMinLifetime = programMinLifetime; mLastInstalledProgramMinLifetime = programMinLifetime;
mLastInstalledProgram = program; mLastInstalledProgram = program;
mNumProgramUpdates++;
if (VDBG) { if (VDBG) {
hexDump("Installing filter: ", program, program.length); hexDump("Installing filter: ", program, program.length);
} }
@@ -865,19 +897,20 @@ public class ApfFilter {
} }
public synchronized void dump(IndentingPrintWriter pw) { public synchronized void dump(IndentingPrintWriter pw) {
pw.println("APF caps: " + mApfCapabilities); pw.println("Capabilities: " + mApfCapabilities);
pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED")); pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
pw.println("Multicast filtering: " + mMulticastFilter); pw.println("Multicast: " + (mMulticastFilter ? "DROP" : "ALLOW"));
try { try {
pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address)); pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address).getHostAddress());
} catch (UnknownHostException|NullPointerException e) {} } catch (UnknownHostException|NullPointerException e) {}
if (mLastTimeInstalledProgram == 0) { if (mLastTimeInstalledProgram == 0) {
pw.println("No program installed."); pw.println("No program installed.");
return; return;
} }
pw.println("Program updates: " + mNumProgramUpdates);
pw.println(String.format( pw.println(String.format(
"Last program length %d, installed %ds ago, lifetime %d", "Last program length %d, installed %ds ago, lifetime %ds",
mLastInstalledProgram.length, curTime() - mLastTimeInstalledProgram, mLastInstalledProgram.length, curTime() - mLastTimeInstalledProgram,
mLastInstalledProgramMinLifetime)); mLastInstalledProgramMinLifetime));
@@ -896,6 +929,7 @@ public class ApfFilter {
} }
pw.decreaseIndent(); pw.decreaseIndent();
} }
pw.decreaseIndent();
if (DBG) { if (DBG) {
pw.println("Last program:"); pw.println("Last program:");
@@ -903,7 +937,5 @@ public class ApfFilter {
pw.println(HexDump.toHexString(mLastInstalledProgram, false /* lowercase */)); pw.println(HexDump.toHexString(mLastInstalledProgram, false /* lowercase */));
pw.decreaseIndent(); pw.decreaseIndent();
} }
pw.decreaseIndent();
} }
} }