diff options
4 files changed, 59 insertions, 14 deletions
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java index 09badec5c197..e570ef1e9bf2 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java @@ -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) { diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java index d79ad1fe41a9..7f2f499ab21f 100644 --- a/services/net/java/android/net/TcpKeepalivePacketData.java +++ b/services/net/java/android/net/TcpKeepalivePacketData.java @@ -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; } } diff --git a/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl index d66b6ae3ab54..e25168d588e7 100644 --- a/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl +++ b/services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl @@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable { int ack; int rcvWnd; int rcvWndScale; + int tos; + int ttl; } diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index 372ffcd057b4..e0b722761c34 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -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); } } |