Merge "[TCPKeepalive] Fill correct TOS and TTL value"
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.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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable {
|
|||||||
int ack;
|
int ack;
|
||||||
int rcvWnd;
|
int rcvWnd;
|
||||||
int rcvWndScale;
|
int rcvWndScale;
|
||||||
|
int tos;
|
||||||
|
int ttl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user