From 583c95be3bca48d65e559160f5d204c5fba1cb87 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 2 Nov 2017 21:01:46 -0700 Subject: [PATCH 1/2] Relocate KeepalivePacketData to frameworks/base Due to an issue resolving the boot classpath, the KeepalivePacketData structure cannot be referenced by frameworks/opt/telephony while it is in services. -Move KeepalivePacketData to android.net -Also, relocate IpUtils without changing the package name. Bug: 38350389 Test: compilation Merged-In: If5fc63e9ad8b9b2d4c2fee47ff4bab2ab190a05a Change-Id: If5fc63e9ad8b9b2d4c2fee47ff4bab2ab190a05a (cherry picked from commit f8a2bc3eeecccd229e3fa2185b933fe26efdd34a) --- .../java/android/net}/KeepalivePacketData.java | 2 +- .../java/com/android/server/connectivity/KeepaliveTracker.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {services/core/java/com/android/server/connectivity => core/java/android/net}/KeepalivePacketData.java (99%) diff --git a/services/core/java/com/android/server/connectivity/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java similarity index 99% rename from services/core/java/com/android/server/connectivity/KeepalivePacketData.java rename to core/java/android/net/KeepalivePacketData.java index f6b73b7d69..84892c6a55 100644 --- a/services/core/java/com/android/server/connectivity/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.connectivity; +package android.net; import static android.net.util.NetworkConstants.IPV4_HEADER_MIN_LEN; import static android.net.util.NetworkConstants.UDP_HEADER_LEN; diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 9e1f6b85ce..f1af7042be 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -18,10 +18,10 @@ package com.android.server.connectivity; import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.connectivity.KeepalivePacketData; import com.android.server.connectivity.NetworkAgentInfo; import android.net.ConnectivityManager; import android.net.ConnectivityManager.PacketKeepalive; +import android.net.KeepalivePacketData; import android.net.LinkAddress; import android.net.NetworkAgent; import android.net.NetworkUtils; From 7f8d0be10db622618ea9b0568dc6d873b8d00756 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 6 Dec 2017 19:07:32 -0800 Subject: [PATCH 2/2] Rework KeepalivePacketData for Compatibility with Cell KeepalivePacketData currently mixes multiple concepts: the list of parameters that are used to generate a keepalive packet, the keepalive packet itself, and the parameters that are needed to send a keepalive packet over an ethernet link. The KeepalivePacketData is now a parcelable that can be used generically by any NetworkAgent, regardless of how that Agent fulfills its duty to initiate and maintain a keepalive session. Bug: 69063212 Test: verified with SL4A, additional tests pending Merged-In: I23dc4827ae729583356a8ff0f02e39a2ad2b81f5 Change-Id: I23dc4827ae729583356a8ff0f02e39a2ad2b81f5 (cherry picked from commit 5be3f5a2b1ecfbb3c9d8eb0dfa12cf6e88dbca9f) --- .../java/android/net/KeepalivePacketData.java | 99 +++++++++++++------ .../server/connectivity/KeepaliveTracker.java | 4 +- 2 files changed, 70 insertions(+), 33 deletions(-) diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 84892c6a55..08d4ff5da9 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -16,13 +16,13 @@ package android.net; -import static android.net.util.NetworkConstants.IPV4_HEADER_MIN_LEN; -import static android.net.util.NetworkConstants.UDP_HEADER_LEN; - import android.system.OsConstants; import android.net.ConnectivityManager; -import android.net.NetworkUtils; import android.net.util.IpUtils; +import android.os.Parcel; +import android.os.Parcelable; +import android.system.OsConstants; +import android.util.Log; import java.net.Inet4Address; import java.net.Inet6Address; @@ -38,9 +38,8 @@ import static android.net.ConnectivityManager.PacketKeepalive.*; * * @hide */ -public class KeepalivePacketData { - /** Protocol of the packet to send; one of the OsConstants.ETH_P_* values. */ - public final int protocol; +public class KeepalivePacketData implements Parcelable { + private static final String TAG = "KeepalivePacketData"; /** Source IP address */ public final InetAddress srcAddress; @@ -54,54 +53,57 @@ public class KeepalivePacketData { /** Destination port */ public final int dstPort; - /** Destination MAC address. Can change if routing changes. */ - public byte[] dstMac; - /** Packet data. A raw byte string of packet data, not including the link-layer header. */ - public final byte[] data; + private final byte[] mPacket; + private static final int IPV4_HEADER_LENGTH = 20; + private static final int UDP_HEADER_LENGTH = 8; + + // This should only be constructed via static factory methods, such as + // nattKeepalivePacket protected KeepalivePacketData(InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException { this.srcAddress = srcAddress; this.dstAddress = dstAddress; this.srcPort = srcPort; this.dstPort = dstPort; - this.data = data; + this.mPacket = data; // Check we have two IP addresses of the same family. - if (srcAddress == null || dstAddress == null || - !srcAddress.getClass().getName().equals(dstAddress.getClass().getName())) { - throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); - } - - // Set the protocol. - if (this.dstAddress instanceof Inet4Address) { - this.protocol = OsConstants.ETH_P_IP; - } else if (this.dstAddress instanceof Inet6Address) { - this.protocol = OsConstants.ETH_P_IPV6; - } else { + if (srcAddress == null || dstAddress == null || !srcAddress.getClass().getName() + .equals(dstAddress.getClass().getName())) { + Log.e(TAG, "Invalid or mismatched InetAddresses in KeepalivePacketData"); throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); } // Check the ports. if (!IpUtils.isValidUdpOrTcpPort(srcPort) || !IpUtils.isValidUdpOrTcpPort(dstPort)) { + Log.e(TAG, "Invalid ports in KeepalivePacketData"); throw new InvalidPacketException(ERROR_INVALID_PORT); } } public static class InvalidPacketException extends Exception { - final public int error; + public final int error; public InvalidPacketException(int error) { this.error = error; } } - /** - * Creates an IPsec NAT-T keepalive packet with the specified parameters. - */ + public byte[] getPacket() { + return mPacket.clone(); + } + public static KeepalivePacketData nattKeepalivePacket( - InetAddress srcAddress, int srcPort, - InetAddress dstAddress, int dstPort) throws InvalidPacketException { + InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort) + throws InvalidPacketException { + + // FIXME: remove this and actually support IPv6 keepalives + if (srcAddress instanceof Inet6Address && dstAddress instanceof Inet6Address) { + // Optimistically returning an IPv6 Keepalive Packet with no data, + // which currently only works on cellular + return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, new byte[0]); + } if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) { throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); @@ -111,7 +113,7 @@ public class KeepalivePacketData { throw new InvalidPacketException(ERROR_INVALID_PORT); } - int length = IPV4_HEADER_MIN_LEN + UDP_HEADER_LEN + 1; + int length = IPV4_HEADER_LENGTH + UDP_HEADER_LENGTH + 1; ByteBuffer buf = ByteBuffer.allocate(length); buf.order(ByteOrder.BIG_ENDIAN); buf.putShort((short) 0x4500); // IP version and TOS @@ -130,8 +132,43 @@ public class KeepalivePacketData { buf.putShort((short) 0); // UDP checksum buf.put((byte) 0xff); // NAT-T keepalive buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); - buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_MIN_LEN)); + buf.putShort(udpChecksumOffset, IpUtils.udpChecksum(buf, 0, IPV4_HEADER_LENGTH)); return new KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, buf.array()); } + + /* Parcelable Implementation */ + public int describeContents() { + return 0; + } + + /** Write to parcel */ + public void writeToParcel(Parcel out, int flags) { + out.writeString(srcAddress.getHostAddress()); + out.writeString(dstAddress.getHostAddress()); + out.writeInt(srcPort); + out.writeInt(dstPort); + out.writeByteArray(mPacket); + } + + private KeepalivePacketData(Parcel in) { + srcAddress = NetworkUtils.numericToInetAddress(in.readString()); + dstAddress = NetworkUtils.numericToInetAddress(in.readString()); + srcPort = in.readInt(); + dstPort = in.readInt(); + mPacket = in.createByteArray(); + } + + /** Parcelable Creator */ + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public KeepalivePacketData createFromParcel(Parcel in) { + return new KeepalivePacketData(in); + } + + public KeepalivePacketData[] newArray(int size) { + return new KeepalivePacketData[size]; + } + }; + } diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index f1af7042be..d24f9c985a 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -129,7 +129,7 @@ public class KeepaliveTracker { .append("->") .append(IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort)) .append(" interval=" + mInterval) - .append(" data=" + HexDump.toHexString(mPacket.data)) + .append(" packetData=" + HexDump.toHexString(mPacket.getPacket())) .append(" uid=").append(mUid).append(" pid=").append(mPid) .append(" ]") .toString(); @@ -172,7 +172,7 @@ public class KeepaliveTracker { } private int checkInterval() { - return mInterval >= 20 ? SUCCESS : ERROR_INVALID_INTERVAL; + return mInterval >= 10 ? SUCCESS : ERROR_INVALID_INTERVAL; } private int isValid() {