Merge "apf: Remove IPv6 NAT-T keepalive related codes and ApfTest improvement" into qt-dev
This commit is contained in:
@@ -156,8 +156,7 @@ public class ApfFilter {
|
|||||||
DROPPED_ARP_REPLY_SPA_NO_HOST,
|
DROPPED_ARP_REPLY_SPA_NO_HOST,
|
||||||
DROPPED_IPV4_KEEPALIVE_ACK,
|
DROPPED_IPV4_KEEPALIVE_ACK,
|
||||||
DROPPED_IPV6_KEEPALIVE_ACK,
|
DROPPED_IPV6_KEEPALIVE_ACK,
|
||||||
DROPPED_IPV4_NATT_KEEPALIVE,
|
DROPPED_IPV4_NATT_KEEPALIVE;
|
||||||
DROPPED_IPV6_NATT_KEEPALIVE;
|
|
||||||
|
|
||||||
// Returns the negative byte offset from the end of the APF data segment for
|
// Returns the negative byte offset from the end of the APF data segment for
|
||||||
// a given counter.
|
// a given counter.
|
||||||
@@ -873,17 +872,17 @@ public class ApfFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A class to hold NAT-T keepalive ack information.
|
// A class to hold NAT-T keepalive ack information.
|
||||||
private abstract static class NattKeepaliveAck extends KeepalivePacket {
|
private class NattKeepaliveResponse extends KeepalivePacket {
|
||||||
static final int UDP_LENGTH_OFFSET = 4;
|
static final int UDP_LENGTH_OFFSET = 4;
|
||||||
static final int UDP_HEADER_LEN = 8;
|
static final int UDP_HEADER_LEN = 8;
|
||||||
|
|
||||||
protected static class NattKeepaliveAckData {
|
protected class NattKeepaliveResponseData {
|
||||||
public final byte[] srcAddress;
|
public final byte[] srcAddress;
|
||||||
public final int srcPort;
|
public final int srcPort;
|
||||||
public final byte[] dstAddress;
|
public final byte[] dstAddress;
|
||||||
public final int dstPort;
|
public final int dstPort;
|
||||||
|
|
||||||
NattKeepaliveAckData(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
NattKeepaliveResponseData(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
||||||
srcAddress = sentKeepalivePacket.dstAddress;
|
srcAddress = sentKeepalivePacket.dstAddress;
|
||||||
srcPort = sentKeepalivePacket.dstPort;
|
srcPort = sentKeepalivePacket.dstPort;
|
||||||
dstAddress = sentKeepalivePacket.srcAddress;
|
dstAddress = sentKeepalivePacket.srcAddress;
|
||||||
@@ -891,19 +890,19 @@ public class ApfFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final NattKeepaliveAckData mPacket;
|
protected final NattKeepaliveResponseData mPacket;
|
||||||
protected final byte[] mSrcDstAddr;
|
protected final byte[] mSrcDstAddr;
|
||||||
protected final byte[] mPortFingerprint;
|
protected final byte[] mPortFingerprint;
|
||||||
// NAT-T keepalive packet
|
// NAT-T keepalive packet
|
||||||
protected final byte[] mPayload = {(byte) 0xff};
|
protected final byte[] mPayload = {(byte) 0xff};
|
||||||
|
|
||||||
NattKeepaliveAck(final NattKeepaliveAckData packet, final byte[] srcDstAddr) {
|
NattKeepaliveResponse(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
||||||
mPacket = packet;
|
mPacket = new NattKeepaliveResponseData(sentKeepalivePacket);
|
||||||
mSrcDstAddr = srcDstAddr;
|
mSrcDstAddr = concatArrays(mPacket.srcAddress, mPacket.dstAddress);
|
||||||
mPortFingerprint = generatePortFingerprint(mPacket.srcPort, mPacket.dstPort);
|
mPortFingerprint = generatePortFingerprint(mPacket.srcPort, mPacket.dstPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
static byte[] generatePortFingerprint(int srcPort, int dstPort) {
|
byte[] generatePortFingerprint(int srcPort, int dstPort) {
|
||||||
final ByteBuffer fp = ByteBuffer.allocate(4);
|
final ByteBuffer fp = ByteBuffer.allocate(4);
|
||||||
fp.order(ByteOrder.BIG_ENDIAN);
|
fp.order(ByteOrder.BIG_ENDIAN);
|
||||||
fp.putShort((short) srcPort);
|
fp.putShort((short) srcPort);
|
||||||
@@ -911,27 +910,6 @@ public class ApfFilter {
|
|||||||
return fp.array();
|
return fp.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
try {
|
|
||||||
return String.format("%s -> %s",
|
|
||||||
NetworkStackUtils.addressAndPortToString(
|
|
||||||
InetAddress.getByAddress(mPacket.srcAddress), mPacket.srcPort),
|
|
||||||
NetworkStackUtils.addressAndPortToString(
|
|
||||||
InetAddress.getByAddress(mPacket.dstAddress), mPacket.dstPort));
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
return "Unknown host";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class NattKeepaliveAckV4 extends NattKeepaliveAck {
|
|
||||||
NattKeepaliveAckV4(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
|
||||||
this(new NattKeepaliveAckData(sentKeepalivePacket));
|
|
||||||
}
|
|
||||||
NattKeepaliveAckV4(final NattKeepaliveAckData packet) {
|
|
||||||
super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
|
void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
|
||||||
final String nextFilterLabel = "natt_keepalive_filter" + getUniqueNumberLocked();
|
final String nextFilterLabel = "natt_keepalive_filter" + getUniqueNumberLocked();
|
||||||
@@ -949,10 +927,9 @@ public class ApfFilter {
|
|||||||
gen.addAddR1();
|
gen.addAddR1();
|
||||||
gen.addJumpIfR0NotEquals(1, nextFilterLabel);
|
gen.addJumpIfR0NotEquals(1, nextFilterLabel);
|
||||||
|
|
||||||
// R0 = R0 + R1 -> R0 contains IP header
|
// Check that the ports match
|
||||||
gen.addLoadFromMemory(Register.R1, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
|
gen.addLoadFromMemory(Register.R0, gen.IPV4_HEADER_SIZE_MEMORY_SLOT);
|
||||||
gen.addLoadImmediate(Register.R0, ETH_HEADER_LEN);
|
gen.addAdd(ETH_HEADER_LEN);
|
||||||
gen.addAddR1();
|
|
||||||
gen.addJumpIfBytesNotEqual(Register.R0, mPortFingerprint, nextFilterLabel);
|
gen.addJumpIfBytesNotEqual(Register.R0, mPortFingerprint, nextFilterLabel);
|
||||||
|
|
||||||
// Payload offset = R0 + UDP header length
|
// Payload offset = R0 + UDP header length
|
||||||
@@ -963,20 +940,17 @@ public class ApfFilter {
|
|||||||
gen.addJump(mCountAndDropLabel);
|
gen.addJump(mCountAndDropLabel);
|
||||||
gen.defineLabel(nextFilterLabel);
|
gen.defineLabel(nextFilterLabel);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private class NattKeepaliveAckV6 extends NattKeepaliveAck {
|
public String toString() {
|
||||||
NattKeepaliveAckV6(final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
try {
|
||||||
this(new NattKeepaliveAckData(sentKeepalivePacket));
|
return String.format("%s -> %s",
|
||||||
|
NetworkStackUtils.addressAndPortToString(
|
||||||
|
InetAddress.getByAddress(mPacket.srcAddress), mPacket.srcPort),
|
||||||
|
NetworkStackUtils.addressAndPortToString(
|
||||||
|
InetAddress.getByAddress(mPacket.dstAddress), mPacket.dstPort));
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
return "Unknown host";
|
||||||
}
|
}
|
||||||
|
|
||||||
NattKeepaliveAckV6(final NattKeepaliveAckData packet) {
|
|
||||||
super(packet, concatArrays(packet.srcAddress, packet.dstAddress) /* srcDstAddr */);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void generateFilterLocked(ApfGenerator gen) throws IllegalInstructionException {
|
|
||||||
throw new UnsupportedOperationException("IPv6 NAT-T Keepalive is not supported yet");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1296,6 +1270,7 @@ public class ApfFilter {
|
|||||||
gen.addJump(mCountAndDropLabel);
|
gen.addJump(mCountAndDropLabel);
|
||||||
} else {
|
} else {
|
||||||
generateV4KeepaliveFilters(gen);
|
generateV4KeepaliveFilters(gen);
|
||||||
|
generateV4NattKeepaliveFilters(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, pass
|
// Otherwise, pass
|
||||||
@@ -1303,36 +1278,36 @@ public class ApfFilter {
|
|||||||
gen.addJump(mCountAndPassLabel);
|
gen.addJump(mCountAndPassLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateFilters(ApfGenerator gen, Class<?> filterType, int proto, int offset,
|
private void generateKeepaliveFilters(ApfGenerator gen, Class<?> filterType, int proto,
|
||||||
String label) throws IllegalInstructionException {
|
int offset, String label) throws IllegalInstructionException {
|
||||||
final boolean haveKeepaliveAcks = NetworkStackUtils.any(mKeepalivePackets,
|
final boolean haveKeepaliveResponses = NetworkStackUtils.any(mKeepalivePackets,
|
||||||
ack -> filterType.isInstance(ack));
|
ack -> filterType.isInstance(ack));
|
||||||
|
|
||||||
// If no keepalive packets of this type
|
// If no keepalive packets of this type
|
||||||
if (!haveKeepaliveAcks) return;
|
if (!haveKeepaliveResponses) return;
|
||||||
|
|
||||||
// If not the right proto, skip keepalive filters
|
// If not the right proto, skip keepalive filters
|
||||||
gen.addLoad8(Register.R0, offset);
|
gen.addLoad8(Register.R0, offset);
|
||||||
gen.addJumpIfR0NotEquals(proto, label);
|
gen.addJumpIfR0NotEquals(proto, label);
|
||||||
|
|
||||||
// Drop Keepalive packets
|
// Drop Keepalive responses
|
||||||
for (int i = 0; i < mKeepalivePackets.size(); ++i) {
|
for (int i = 0; i < mKeepalivePackets.size(); ++i) {
|
||||||
final KeepalivePacket ack = mKeepalivePackets.valueAt(i);
|
final KeepalivePacket response = mKeepalivePackets.valueAt(i);
|
||||||
if (filterType.isInstance(ack)) ack.generateFilterLocked(gen);
|
if (filterType.isInstance(response)) response.generateFilterLocked(gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
gen.defineLabel(label);
|
gen.defineLabel(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateV4KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
|
private void generateV4KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
|
||||||
generateFilters(gen, TcpKeepaliveAckV4.class, IPPROTO_TCP, IPV4_PROTOCOL_OFFSET,
|
generateKeepaliveFilters(gen, TcpKeepaliveAckV4.class, IPPROTO_TCP, IPV4_PROTOCOL_OFFSET,
|
||||||
"skip_v4_keepalive_filter");
|
"skip_v4_keepalive_filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateV4NattKeepaliveFilters(ApfGenerator gen)
|
private void generateV4NattKeepaliveFilters(ApfGenerator gen)
|
||||||
throws IllegalInstructionException {
|
throws IllegalInstructionException {
|
||||||
generateFilters(gen, NattKeepaliveAckV4.class, IPPROTO_UDP, IPV4_PROTOCOL_OFFSET,
|
generateKeepaliveFilters(gen, NattKeepaliveResponse.class,
|
||||||
"skip_v4_nattkeepalive_filter");
|
IPPROTO_UDP, IPV4_PROTOCOL_OFFSET, "skip_v4_nattkeepalive_filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1417,7 +1392,7 @@ public class ApfFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateV6KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
|
private void generateV6KeepaliveFilters(ApfGenerator gen) throws IllegalInstructionException {
|
||||||
generateFilters(gen, TcpKeepaliveAckV6.class, IPPROTO_TCP, IPV6_NEXT_HEADER_OFFSET,
|
generateKeepaliveFilters(gen, TcpKeepaliveAckV6.class, IPPROTO_TCP, IPV6_NEXT_HEADER_OFFSET,
|
||||||
"skip_v6_keepalive_filter");
|
"skip_v6_keepalive_filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1819,8 +1794,8 @@ public class ApfFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add NATT keepalive packet filter.
|
* Add NAT-T keepalive packet filter.
|
||||||
* This will add a filter to drop NATT keepalive packet which is passed as an argument.
|
* This will add a filter to drop NAT-T keepalive packet which is passed as an argument.
|
||||||
*
|
*
|
||||||
* @param slot The index used to access the filter.
|
* @param slot The index used to access the filter.
|
||||||
* @param sentKeepalivePacket The attributes of the sent keepalive packet.
|
* @param sentKeepalivePacket The attributes of the sent keepalive packet.
|
||||||
@@ -1829,12 +1804,12 @@ public class ApfFilter {
|
|||||||
final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
final NattKeepalivePacketDataParcelable sentKeepalivePacket) {
|
||||||
log("Adding NAT-T keepalive packet(" + slot + ")");
|
log("Adding NAT-T keepalive packet(" + slot + ")");
|
||||||
if (null != mKeepalivePackets.get(slot)) {
|
if (null != mKeepalivePackets.get(slot)) {
|
||||||
throw new IllegalArgumentException("Natt Keepalive slot " + slot + " is occupied");
|
throw new IllegalArgumentException("NAT-T Keepalive slot " + slot + " is occupied");
|
||||||
}
|
}
|
||||||
final int ipVersion = sentKeepalivePacket.srcAddress.length == 4 ? 4 : 6;
|
if (sentKeepalivePacket.srcAddress.length != 4) {
|
||||||
mKeepalivePackets.put(slot, (ipVersion == 4)
|
throw new IllegalArgumentException("NAT-T keepalive is only supported on IPv4");
|
||||||
? new NattKeepaliveAckV4(sentKeepalivePacket)
|
}
|
||||||
: new NattKeepaliveAckV6(sentKeepalivePacket));
|
mKeepalivePackets.put(slot, new NattKeepaliveResponse(sentKeepalivePacket));
|
||||||
installNewProgramLocked();
|
installNewProgramLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1918,7 +1893,7 @@ public class ApfFilter {
|
|||||||
pw.increaseIndent();
|
pw.increaseIndent();
|
||||||
for (int i = 0; i < mKeepalivePackets.size(); ++i) {
|
for (int i = 0; i < mKeepalivePackets.size(); ++i) {
|
||||||
final KeepalivePacket keepalivePacket = mKeepalivePackets.valueAt(i);
|
final KeepalivePacket keepalivePacket = mKeepalivePackets.valueAt(i);
|
||||||
if (keepalivePacket instanceof NattKeepaliveAck) {
|
if (keepalivePacket instanceof NattKeepaliveResponse) {
|
||||||
pw.print("Slot ");
|
pw.print("Slot ");
|
||||||
pw.print(mKeepalivePackets.keyAt(i));
|
pw.print(mKeepalivePackets.keyAt(i));
|
||||||
pw.print(": ");
|
pw.print(": ");
|
||||||
|
|||||||
@@ -1734,7 +1734,8 @@ public class ApfTest {
|
|||||||
final int dstPort = 4500;
|
final int dstPort = 4500;
|
||||||
final int slot1 = 1;
|
final int slot1 = 1;
|
||||||
// NAT-T keepalive
|
// NAT-T keepalive
|
||||||
final byte[] payload = {(byte) 0xff};
|
final byte[] kaPayload = {(byte) 0xff};
|
||||||
|
final byte[] nonKaPayload = {(byte) 0xfe};
|
||||||
|
|
||||||
// src: 10.0.0.5, port: 1024
|
// src: 10.0.0.5, port: 1024
|
||||||
// dst: 10.0.0.6, port: 4500
|
// dst: 10.0.0.6, port: 4500
|
||||||
@@ -1753,15 +1754,21 @@ public class ApfTest {
|
|||||||
// Verify IPv4 keepalive packet is dropped
|
// Verify IPv4 keepalive packet is dropped
|
||||||
// src: 10.0.0.6, port: 4500
|
// src: 10.0.0.6, port: 4500
|
||||||
// dst: 10.0.0.5, port: 1024
|
// dst: 10.0.0.5, port: 1024
|
||||||
final byte[] nattKaPkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR,
|
byte[] pkt = ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR,
|
||||||
IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */);
|
IPV4_KEEPALIVE_SRC_ADDR, dstPort, srcPort, 1 /* dataLength */);
|
||||||
System.arraycopy(payload, 0, nattKaPkt, IPV4_UDP_PAYLOAD_OFFSET, payload.length);
|
System.arraycopy(kaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, kaPayload.length);
|
||||||
assertDrop(program, nattKaPkt);
|
assertDrop(program, pkt);
|
||||||
// Verify IPv4 non-keepalive packet from the same source address is passed
|
|
||||||
|
// Verify a packet with payload length 1 byte but it is not 0xff will pass the filter.
|
||||||
|
System.arraycopy(nonKaPayload, 0, pkt, IPV4_UDP_PAYLOAD_OFFSET, nonKaPayload.length);
|
||||||
|
assertPass(program, pkt);
|
||||||
|
|
||||||
|
// Verify IPv4 non-keepalive response packet from the same source address is passed
|
||||||
assertPass(program,
|
assertPass(program,
|
||||||
ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
|
ipv4UdpPacket(IPV4_KEEPALIVE_DST_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
|
||||||
dstPort, srcPort, 10 /* dataLength */));
|
dstPort, srcPort, 10 /* dataLength */));
|
||||||
// Verify IPv4 non-keepalive packet from other source address is passed
|
|
||||||
|
// Verify IPv4 non-keepalive response packet from other source address is passed
|
||||||
assertPass(program,
|
assertPass(program,
|
||||||
ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
|
ipv4UdpPacket(IPV4_ANOTHER_ADDR, IPV4_KEEPALIVE_SRC_ADDR,
|
||||||
dstPort, srcPort, 10 /* dataLength */));
|
dstPort, srcPort, 10 /* dataLength */));
|
||||||
|
|||||||
Reference in New Issue
Block a user