Merge "[TCPKeepalive] Fill correct TOS and TTL value" am: 6aef2afd4e
am: 37dd29a169
Change-Id: I0de6ff4a97f64b0ba72856c9d9d6fe57d677e5fa
This commit is contained in:
@@ -23,7 +23,10 @@ import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
|
||||
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
|
||||
import static android.system.OsConstants.ENOPROTOOPT;
|
||||
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.IP_TOS;
|
||||
import static android.system.OsConstants.IP_TTL;
|
||||
import static android.system.OsConstants.TIOCOUTQ;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
@@ -193,6 +196,12 @@ public class TcpKeepaliveController {
|
||||
trw = NetworkUtils.getTcpRepairWindow(fd);
|
||||
tcpDetails.rcvWnd = trw.rcvWnd;
|
||||
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) {
|
||||
Log.e(TAG, "Exception reading TCP state from socket", e);
|
||||
if (e.errno == ENOPROTOOPT) {
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.util.Objects;
|
||||
public class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
|
||||
private static final String TAG = "TcpKeepalivePacketData";
|
||||
|
||||
/** TCP sequence number. */
|
||||
/** TCP sequence number. */
|
||||
public final int tcpSeq;
|
||||
|
||||
/** TCP ACK number. */
|
||||
@@ -50,6 +50,12 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
|
||||
/** TCP RCV window scale. */
|
||||
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 IPV6_HEADER_LENGTH = 40;
|
||||
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.
|
||||
tcpWnd = tcpDetails.rcvWnd;
|
||||
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;
|
||||
ByteBuffer buf = ByteBuffer.allocate(length);
|
||||
buf.order(ByteOrder.BIG_ENDIAN);
|
||||
// IP version and TOS. TODO : fetch this from getsockopt(SOL_IP, IP_TOS)
|
||||
buf.putShort((short) 0x4500);
|
||||
buf.put((byte) 0x45); // IP version and IHL
|
||||
buf.put((byte) tcpDetails.tos); // TOS
|
||||
buf.putShort((short) length);
|
||||
buf.putInt(0x4000); // ID, flags=DF, offset
|
||||
// TODO : fetch TTL from getsockopt(SOL_IP, IP_TTL)
|
||||
buf.put((byte) 64);
|
||||
buf.putInt(0x00004000); // ID, flags=DF, offset
|
||||
buf.put((byte) tcpDetails.ttl); // TTL
|
||||
buf.put((byte) OsConstants.IPPROTO_TCP);
|
||||
final int ipChecksumOffset = buf.position();
|
||||
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
|
||||
final int tcpChecksumOffset = buf.position();
|
||||
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(tcpChecksumOffset, IpUtils.tcpChecksum(
|
||||
buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
|
||||
@@ -138,13 +147,15 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
|
||||
&& this.tcpAck == other.tcpAck
|
||||
&& this.tcpSeq == other.tcpSeq
|
||||
&& this.tcpWnd == other.tcpWnd
|
||||
&& this.tcpWndScale == other.tcpWndScale;
|
||||
&& this.tcpWndScale == other.tcpWndScale
|
||||
&& this.ipTos == other.ipTos
|
||||
&& this.ipTtl == other.ipTtl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
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(tcpWnd);
|
||||
out.writeInt(tcpWndScale);
|
||||
out.writeInt(ipTos);
|
||||
out.writeInt(ipTtl);
|
||||
}
|
||||
|
||||
private TcpKeepalivePacketData(Parcel in) {
|
||||
@@ -172,6 +185,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
|
||||
tcpAck = in.readInt();
|
||||
tcpWnd = in.readInt();
|
||||
tcpWndScale = in.readInt();
|
||||
ipTos = in.readInt();
|
||||
ipTtl = in.readInt();
|
||||
}
|
||||
|
||||
/** Parcelable Creator. */
|
||||
@@ -200,6 +215,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
|
||||
parcel.ack = tcpAck;
|
||||
parcel.rcvWnd = tcpWnd;
|
||||
parcel.rcvWndScale = tcpWndScale;
|
||||
parcel.tos = ipTos;
|
||||
parcel.ttl = ipTtl;
|
||||
return parcel;
|
||||
}
|
||||
|
||||
@@ -212,6 +229,8 @@ public class TcpKeepalivePacketData extends KeepalivePacketData implements Parce
|
||||
+ " seq: " + tcpSeq
|
||||
+ " ack: " + tcpAck
|
||||
+ " wnd: " + tcpWnd
|
||||
+ " wndScale: " + tcpWndScale;
|
||||
+ " wndScale: " + tcpWndScale
|
||||
+ " tos: " + ipTos
|
||||
+ " ttl: " + ipTtl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable {
|
||||
int ack;
|
||||
int rcvWnd;
|
||||
int rcvWndScale;
|
||||
int tos;
|
||||
int ttl;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,8 @@ public final class TcpKeepalivePacketDataTest {
|
||||
final int ack = 0x22222222;
|
||||
final int wnd = 8000;
|
||||
final int wndScale = 2;
|
||||
final int tos = 4;
|
||||
final int ttl = 64;
|
||||
TcpKeepalivePacketData resultData = null;
|
||||
final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
|
||||
testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
|
||||
@@ -58,6 +60,8 @@ public final class TcpKeepalivePacketDataTest {
|
||||
testInfo.ack = ack;
|
||||
testInfo.rcvWnd = wnd;
|
||||
testInfo.rcvWndScale = wndScale;
|
||||
testInfo.tos = tos;
|
||||
testInfo.ttl = ttl;
|
||||
try {
|
||||
resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
|
||||
} catch (InvalidPacketException e) {
|
||||
@@ -72,16 +76,21 @@ public final class TcpKeepalivePacketDataTest {
|
||||
assertEquals(testInfo.ack, resultData.tcpAck);
|
||||
assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
|
||||
assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
|
||||
assertEquals(testInfo.tos, resultData.ipTos);
|
||||
assertEquals(testInfo.ttl, resultData.ipTtl);
|
||||
|
||||
TestUtils.assertParcelingIsLossless(resultData, TcpKeepalivePacketData.CREATOR);
|
||||
|
||||
final byte[] packet = resultData.getPacket();
|
||||
// IP version and TOS.
|
||||
ByteBuffer buf = ByteBuffer.wrap(packet);
|
||||
assertEquals(buf.getShort(), 0x4500);
|
||||
// IP version and IHL
|
||||
assertEquals(packet[0], 0x45);
|
||||
// TOS
|
||||
assertEquals(packet[1], tos);
|
||||
// TTL
|
||||
assertEquals(packet[8], ttl);
|
||||
// Source IP address.
|
||||
byte[] ip = new byte[4];
|
||||
buf = ByteBuffer.wrap(packet, 12, 4);
|
||||
ByteBuffer buf = ByteBuffer.wrap(packet, 12, 4);
|
||||
buf.get(ip);
|
||||
assertArrayEquals(ip, IPV4_KEEPALIVE_SRC_ADDR);
|
||||
// Destination IP address.
|
||||
@@ -113,6 +122,8 @@ public final class TcpKeepalivePacketDataTest {
|
||||
final int ack = 0x22222222;
|
||||
final int wnd = 48_000;
|
||||
final int wndScale = 2;
|
||||
final int tos = 4;
|
||||
final int ttl = 64;
|
||||
final TcpKeepalivePacketDataParcelable testInfo = new TcpKeepalivePacketDataParcelable();
|
||||
testInfo.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
|
||||
testInfo.srcPort = srcPort;
|
||||
@@ -122,6 +133,8 @@ public final class TcpKeepalivePacketDataTest {
|
||||
testInfo.ack = ack;
|
||||
testInfo.rcvWnd = wnd;
|
||||
testInfo.rcvWndScale = wndScale;
|
||||
testInfo.tos = tos;
|
||||
testInfo.ttl = ttl;
|
||||
TcpKeepalivePacketData testData = null;
|
||||
TcpKeepalivePacketDataParcelable resultData = null;
|
||||
testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
|
||||
@@ -134,5 +147,7 @@ public final class TcpKeepalivePacketDataTest {
|
||||
assertEquals(resultData.ack, ack);
|
||||
assertEquals(resultData.rcvWnd, wnd);
|
||||
assertEquals(resultData.rcvWndScale, wndScale);
|
||||
assertEquals(resultData.tos, tos);
|
||||
assertEquals(resultData.ttl, ttl);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user