Loading services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading services/net/java/android/net/TcpKeepalivePacketData.java +29 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } /** Loading Loading @@ -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 Loading @@ -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)); Loading @@ -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); } /** Loading @@ -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) { Loading @@ -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. */ Loading Loading @@ -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; } Loading @@ -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; } } services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable { int ack; int rcvWnd; int rcvWndScale; int tos; int ttl; } tests/net/java/android/net/TcpKeepalivePacketDataTest.java +19 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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. Loading Loading @@ -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; Loading @@ -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); Loading @@ -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); } } Loading
services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +9 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading
services/net/java/android/net/TcpKeepalivePacketData.java +29 −10 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } /** Loading Loading @@ -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 Loading @@ -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)); Loading @@ -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); } /** Loading @@ -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) { Loading @@ -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. */ Loading Loading @@ -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; } Loading @@ -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; } }
services/net/java/android/net/TcpKeepalivePacketDataParcelable.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -25,4 +25,6 @@ parcelable TcpKeepalivePacketDataParcelable { int ack; int rcvWnd; int rcvWndScale; int tos; int ttl; }
tests/net/java/android/net/TcpKeepalivePacketDataTest.java +19 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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. Loading Loading @@ -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; Loading @@ -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); Loading @@ -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); } }