Merge "[TCPKeepalive] Fill correct TOS and TTL value"

This commit is contained in:
Mark Chien
2019-03-25 13:10:17 +00:00
committed by Gerrit Code Review
4 changed files with 59 additions and 14 deletions

View File

@@ -23,7 +23,10 @@ import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.system.OsConstants.ENOPROTOOPT; import static android.system.OsConstants.ENOPROTOOPT;
import static android.system.OsConstants.FIONREAD; import static android.system.OsConstants.FIONREAD;
import static android.system.OsConstants.IPPROTO_IP;
import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IP_TOS;
import static android.system.OsConstants.IP_TTL;
import static android.system.OsConstants.TIOCOUTQ; import static android.system.OsConstants.TIOCOUTQ;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -193,6 +196,12 @@ public class TcpKeepaliveController {
trw = NetworkUtils.getTcpRepairWindow(fd); trw = NetworkUtils.getTcpRepairWindow(fd);
tcpDetails.rcvWnd = trw.rcvWnd; tcpDetails.rcvWnd = trw.rcvWnd;
tcpDetails.rcvWndScale = trw.rcvWndScale; tcpDetails.rcvWndScale = trw.rcvWndScale;
if (tcpDetails.srcAddress.length == 4 /* V4 address length */) {
// Query TOS.
tcpDetails.tos = Os.getsockoptInt(fd, IPPROTO_IP, IP_TOS);
// Query TTL.
tcpDetails.ttl = Os.getsockoptInt(fd, IPPROTO_IP, IP_TTL);
}
} catch (ErrnoException e) { } catch (ErrnoException e) {
Log.e(TAG, "Exception reading TCP state from socket", e); Log.e(TAG, "Exception reading TCP state from socket", e);
if (e.errno == ENOPROTOOPT) { if (e.errno == ENOPROTOOPT) {

View File

@@ -50,6 +50,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
/** TCP RCV window scale. */ /** TCP RCV window scale. */
public final int tcpWndScale; public final int tcpWndScale;
/** IP TOS. */
public final int ipTos;
/** IP TTL. */
public final int ipTtl;
private static final int IPV4_HEADER_LENGTH = 20; private static final int IPV4_HEADER_LENGTH = 20;
private static final int IPV6_HEADER_LENGTH = 40; private static final int IPV6_HEADER_LENGTH = 40;
private static final int TCP_HEADER_LENGTH = 20; private static final int TCP_HEADER_LENGTH = 20;
@@ -65,6 +71,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
// In the packet, the window is shifted right by the window scale. // In the packet, the window is shifted right by the window scale.
tcpWnd = tcpDetails.rcvWnd; tcpWnd = tcpDetails.rcvWnd;
tcpWndScale = tcpDetails.rcvWndScale; tcpWndScale = tcpDetails.rcvWndScale;
ipTos = tcpDetails.tos;
ipTtl = tcpDetails.ttl;
} }
/** /**
@@ -98,12 +106,11 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH; final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
ByteBuffer buf = ByteBuffer.allocate(length); ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.BIG_ENDIAN); buf.order(ByteOrder.BIG_ENDIAN);
// IP version and TOS. TODO : fetch this from getsockopt(SOL_IP, IP_TOS) buf.put((byte) 0x45); // IP version and IHL
buf.putShort((short) 0x4500); buf.put((byte) tcpDetails.tos); // TOS
buf.putShort((short) length); buf.putShort((short) length);
buf.putInt(0x4000); // ID, flags=DF, offset buf.putInt(0x00004000); // ID, flags=DF, offset
// TODO : fetch TTL from getsockopt(SOL_IP, IP_TTL) buf.put((byte) tcpDetails.ttl); // TTL
buf.put((byte) 64);
buf.put((byte) OsConstants.IPPROTO_TCP); buf.put((byte) OsConstants.IPPROTO_TCP);
final int ipChecksumOffset = buf.position(); final int ipChecksumOffset = buf.position();
buf.putShort((short) 0); // IP checksum buf.putShort((short) 0); // IP checksum
@@ -117,7 +124,9 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size
final int tcpChecksumOffset = buf.position(); final int tcpChecksumOffset = buf.position();
buf.putShort((short) 0); // TCP checksum buf.putShort((short) 0); // TCP checksum
// URG is not set therefore the urgent pointer is not included // URG is not set therefore the urgent pointer is zero.
buf.putShort((short) 0); // Urgent pointer
buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum( buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH)); buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
@@ -138,13 +147,15 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
&& this.tcpAck == other.tcpAck && this.tcpAck == other.tcpAck
&& this.tcpSeq == other.tcpSeq && this.tcpSeq == other.tcpSeq
&& this.tcpWnd == other.tcpWnd && this.tcpWnd == other.tcpWnd
&& this.tcpWndScale == other.tcpWndScale; && this.tcpWndScale == other.tcpWndScale
&& this.ipTos == other.ipTos
&& this.ipTtl == other.ipTtl;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(srcAddress, dstAddress, srcPort, dstPort, tcpAck, tcpSeq, tcpWnd, return Objects.hash(srcAddress, dstAddress, srcPort, dstPort, tcpAck, tcpSeq, tcpWnd,
tcpWndScale); tcpWndScale, ipTos, ipTtl);
} }
/** /**
@@ -164,6 +175,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
out.writeInt(tcpAck); out.writeInt(tcpAck);
out.writeInt(tcpWnd); out.writeInt(tcpWnd);
out.writeInt(tcpWndScale); out.writeInt(tcpWndScale);
out.writeInt(ipTos);
out.writeInt(ipTtl);
} }
private TcpKeepalivePacketData(Parcel in) { private TcpKeepalivePacketData(Parcel in) {
@@ -172,6 +185,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
tcpAck = in.readInt(); tcpAck = in.readInt();
tcpWnd = in.readInt(); tcpWnd = in.readInt();
tcpWndScale = in.readInt(); tcpWndScale = in.readInt();
ipTos = in.readInt();
ipTtl = in.readInt();
} }
/** Parcelable Creator. */ /** Parcelable Creator. */
@@ -200,6 +215,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
parcel.ack = tcpAck; parcel.ack = tcpAck;
parcel.rcvWnd = tcpWnd; parcel.rcvWnd = tcpWnd;
parcel.rcvWndScale = tcpWndScale; parcel.rcvWndScale = tcpWndScale;
parcel.tos = ipTos;
parcel.ttl = ipTtl;
return parcel; return parcel;
} }
@@ -212,6 +229,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
+ " seq: " + tcpSeq + " seq: " + tcpSeq
+ " ack: " + tcpAck + " ack: " + tcpAck
+ " wnd: " + tcpWnd + " wnd: " + tcpWnd
+ " wndScale: " + tcpWndScale; + " wndScale: " + tcpWndScale
+ " tos: " + ipTos
+ " ttl: " + ipTtl;
} }
} }

View File

@@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable {
int ack; int ack;
int rcvWnd; int rcvWnd;
int rcvWndScale; int rcvWndScale;
int tos;
int ttl;
} }

View File

@@ -48,6 +48,8 @@ public final class TcpKeepalivePacketDataTest {
final int ack = 0x22222222; final int ack = 0x22222222;
final int wnd = 8000; final int wnd = 8000;
final int wndScale = 2; final int wndScale = 2;
final int tos = 4;
final int ttl = 64;
TcpKeepalivePacketData resultData = null; TcpKeepalivePacketData resultData = null;
final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
@@ -58,6 +60,8 @@ public final class TcpKeepalivePacketDataTest {
testInfo.ack = ack; testInfo.ack = ack;
testInfo.rcvWnd = wnd; testInfo.rcvWnd = wnd;
testInfo.rcvWndScale = wndScale; testInfo.rcvWndScale = wndScale;
testInfo.tos = tos;
testInfo.ttl = ttl;
try { try {
resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
} catch (InvalidPacketException e) { } catch (InvalidPacketException e) {
@@ -72,16 +76,21 @@ public final class TcpKeepalivePacketDataTest {
assertEquals(testInfo.ack, resultData.tcpAck); assertEquals(testInfo.ack, resultData.tcpAck);
assertEquals(testInfo.rcvWnd, resultData.tcpWnd); assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale); assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
assertEquals(testInfo.tos, resultData.ipTos);
assertEquals(testInfo.ttl, resultData.ipTtl);
TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR); TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR);
final byte[] packet = resultData.getPacket(); final byte[] packet = resultData.getPacket();
// IP version and TOS. // IP version and IHL
ByteBuffer buf = ByteBuffer.wrap(packet); assertEquals(packet[0], 0x45);
assertEquals(buf.getShort(), 0x4500); // TOS
assertEquals(packet[1], tos);
// TTL
assertEquals(packet[8], ttl);
// Source IP address. // Source IP address.
byte[] ip = new byte[4]; byte[] ip = new byte[4];
buf = ByteBuffer.wrap(packet, 12, 4); ByteBuffer buf = ByteBuffer.wrap(packet, 12, 4);
buf.get(ip); buf.get(ip);
assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR); assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR);
// Destination IP address. // Destination IP address.
@@ -113,6 +122,8 @@ public final class TcpKeepalivePacketDataTest {
final int ack = 0x22222222; final int ack = 0x22222222;
final int wnd = 48_000; final int wnd = 48_000;
final int wndScale = 2; final int wndScale = 2;
final int tos = 4;
final int ttl = 64;
final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable(); final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR; testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
testInfo.srcPort = srcPort; testInfo.srcPort = srcPort;
@@ -122,6 +133,8 @@ public final class TcpKeepalivePacketDataTest {
testInfo.ack = ack; testInfo.ack = ack;
testInfo.rcvWnd = wnd; testInfo.rcvWnd = wnd;
testInfo.rcvWndScale = wndScale; testInfo.rcvWndScale = wndScale;
testInfo.tos = tos;
testInfo.ttl = ttl;
TcpKeepalivePacketData testData = null; TcpKeepalivePacketData testData = null;
TcpKeepalivePacketDataParcelable resultData = null; TcpKeepalivePacketDataParcelable resultData = null;
testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo); testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
@@ -134,5 +147,7 @@ public final class TcpKeepalivePacketDataTest {
assertEquals(resultData.ack, ack); assertEquals(resultData.ack, ack);
assertEquals(resultData.rcvWnd, wnd); assertEquals(resultData.rcvWnd, wnd);
assertEquals(resultData.rcvWndScale, wndScale); assertEquals(resultData.rcvWndScale, wndScale);
assertEquals(resultData.tos, tos);
assertEquals(resultData.ttl, ttl);
} }
} }