Merge "More APF debuggability." into nyc-dev
am: 6ad205b
* commit '6ad205b66d9b13479a84f113a43af4966b479d52':
More APF debuggability.
Change-Id: If939093a15fbb3472e9672a668c4feecf55c948a
This commit is contained in:
@@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user