Merge changes from topic "cherry-pick-cell-keepalive"

am: 7e8374e9fc

Change-Id: I3001cd2693b2c57643672fd7f370b5cca2890585
This commit is contained in:
nharold
2018-01-30 19:41:53 +00:00
committed by android-build-merger
2 changed files with 72 additions and 35 deletions

View File

@@ -14,15 +14,15 @@
* limitations under the License. * 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;
import android.system.OsConstants; import android.system.OsConstants;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkUtils;
import android.net.util.IpUtils; 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.Inet4Address;
import java.net.Inet6Address; import java.net.Inet6Address;
@@ -38,9 +38,8 @@ import static android.net.ConnectivityManager.PacketKeepalive.*;
* *
* @hide * @hide
*/ */
public class KeepalivePacketData { public class KeepalivePacketData implements Parcelable {
/** Protocol of the packet to send; one of the OsConstants.ETH_P_* values. */ private static final String TAG = "KeepalivePacketData";
public final int protocol;
/** Source IP address */ /** Source IP address */
public final InetAddress srcAddress; public final InetAddress srcAddress;
@@ -54,54 +53,57 @@ public class KeepalivePacketData {
/** Destination port */ /** Destination port */
public final int dstPort; 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. */ /** 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, protected KeepalivePacketData(InetAddress srcAddress, int srcPort,
InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException { InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException {
this.srcAddress = srcAddress; this.srcAddress = srcAddress;
this.dstAddress = dstAddress; this.dstAddress = dstAddress;
this.srcPort = srcPort; this.srcPort = srcPort;
this.dstPort = dstPort; this.dstPort = dstPort;
this.data = data; this.mPacket = data;
// Check we have two IP addresses of the same family. // Check we have two IP addresses of the same family.
if (srcAddress == null || dstAddress == null || if (srcAddress == null || dstAddress == null || !srcAddress.getClass().getName()
!srcAddress.getClass().getName().equals(dstAddress.getClass().getName())) { .equals(dstAddress.getClass().getName())) {
throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); Log.e(TAG, "Invalid or mismatched InetAddresses in KeepalivePacketData");
}
// 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 {
throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
} }
// Check the ports. // Check the ports.
if (!IpUtils.isValidUdpOrTcpPort(srcPort) || !IpUtils.isValidUdpOrTcpPort(dstPort)) { if (!IpUtils.isValidUdpOrTcpPort(srcPort) || !IpUtils.isValidUdpOrTcpPort(dstPort)) {
Log.e(TAG, "Invalid ports in KeepalivePacketData");
throw new InvalidPacketException(ERROR_INVALID_PORT); throw new InvalidPacketException(ERROR_INVALID_PORT);
} }
} }
public static class InvalidPacketException extends Exception { public static class InvalidPacketException extends Exception {
final public int error; public final int error;
public InvalidPacketException(int error) { public InvalidPacketException(int error) {
this.error = error; this.error = error;
} }
} }
/** public byte[] getPacket() {
* Creates an IPsec NAT-T keepalive packet with the specified parameters. return mPacket.clone();
*/ }
public static KeepalivePacketData nattKeepalivePacket( public static KeepalivePacketData nattKeepalivePacket(
InetAddress srcAddress, int srcPort, InetAddress srcAddress, int srcPort, InetAddress dstAddress, int dstPort)
InetAddress dstAddress, int dstPort) throws InvalidPacketException { 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)) { if (!(srcAddress instanceof Inet4Address) || !(dstAddress instanceof Inet4Address)) {
throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS); throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
@@ -111,7 +113,7 @@ public class KeepalivePacketData {
throw new InvalidPacketException(ERROR_INVALID_PORT); 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); ByteBuffer buf = ByteBuffer.allocate(length);
buf.order(ByteOrder.BIG_ENDIAN); buf.order(ByteOrder.BIG_ENDIAN);
buf.putShort((short) 0x4500); // IP version and TOS buf.putShort((short) 0x4500); // IP version and TOS
@@ -130,8 +132,43 @@ public class KeepalivePacketData {
buf.putShort((short) 0); // UDP checksum buf.putShort((short) 0); // UDP checksum
buf.put((byte) 0xff); // NAT-T keepalive buf.put((byte) 0xff); // NAT-T keepalive
buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0)); 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()); 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];
}
};
} }

View File

@@ -18,10 +18,10 @@ package com.android.server.connectivity;
import com.android.internal.util.HexDump; import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.IndentingPrintWriter;
import com.android.server.connectivity.KeepalivePacketData;
import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkAgentInfo;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.ConnectivityManager.PacketKeepalive; import android.net.ConnectivityManager.PacketKeepalive;
import android.net.KeepalivePacketData;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.NetworkAgent; import android.net.NetworkAgent;
import android.net.NetworkUtils; import android.net.NetworkUtils;
@@ -129,7 +129,7 @@ public class KeepaliveTracker {
.append("->") .append("->")
.append(IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort)) .append(IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort))
.append(" interval=" + mInterval) .append(" interval=" + mInterval)
.append(" data=" + HexDump.toHexString(mPacket.data)) .append(" packetData=" + HexDump.toHexString(mPacket.getPacket()))
.append(" uid=").append(mUid).append(" pid=").append(mPid) .append(" uid=").append(mUid).append(" pid=").append(mPid)
.append(" ]") .append(" ]")
.toString(); .toString();
@@ -172,7 +172,7 @@ public class KeepaliveTracker {
} }
private int checkInterval() { private int checkInterval() {
return mInterval >= 20 ? SUCCESS : ERROR_INVALID_INTERVAL; return mInterval >= 10 ? SUCCESS : ERROR_INVALID_INTERVAL;
} }
private int isValid() { private int isValid() {