diff options
3 files changed, 89 insertions, 33 deletions
diff --git a/core/java/android/net/KeepalivePacketData.aidl b/core/java/android/net/KeepalivePacketData.aidl new file mode 100644 index 000000000000..d456b53fd188 --- /dev/null +++ b/core/java/android/net/KeepalivePacketData.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +parcelable KeepalivePacketData; diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 84892c6a55a1..08d4ff5da966 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<KeepalivePacketData> CREATOR = + new Parcelable.Creator<KeepalivePacketData>() { + 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 f1af7042be3e..d24f9c985ac4 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() { |