Switch RouteInfo to use IpPrefix instead of LinkAddress.
This addresses a TODO and also makes it possible to create
routes to destinations that are not valid LinkAddresses, such as
multicast addresses.
Bug: 16875580
Change-Id: Id4c77b00dc3064bf27d78cdcbbe035e645748cfe
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 129248c..a4ec80c 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -49,9 +49,8 @@
public final class RouteInfo implements Parcelable {
/**
* The IP destination address for this route.
- * TODO: Make this an IpPrefix.
*/
- private final LinkAddress mDestination;
+ private final IpPrefix mDestination;
/**
* The gateway address for this route.
@@ -81,26 +80,15 @@
* @param gateway the IP address to route packets through
* @param iface the interface name to send packets on
*
- * TODO: Convert to use IpPrefix.
- *
* @hide
*/
public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
- this(destination == null ? null :
- new LinkAddress(destination.getAddress(), destination.getPrefixLength()),
- gateway, iface);
- }
-
- /**
- * @hide
- */
- public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
if (destination == null) {
if (gateway != null) {
if (gateway instanceof Inet4Address) {
- destination = new LinkAddress(Inet4Address.ANY, 0);
+ destination = new IpPrefix(Inet4Address.ANY, 0);
} else {
- destination = new LinkAddress(Inet6Address.ANY, 0);
+ destination = new IpPrefix(Inet6Address.ANY, 0);
}
} else {
// no destination, no gateway. invalid.
@@ -108,6 +96,9 @@
destination);
}
}
+ // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
+ // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
+ // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
if (gateway == null) {
if (destination.getAddress() instanceof Inet4Address) {
gateway = Inet4Address.ANY;
@@ -117,20 +108,28 @@
}
mHasGateway = (!gateway.isAnyLocalAddress());
- mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
- destination.getPrefixLength()), destination.getPrefixLength());
if ((destination.getAddress() instanceof Inet4Address &&
(gateway instanceof Inet4Address == false)) ||
(destination.getAddress() instanceof Inet6Address &&
(gateway instanceof Inet6Address == false))) {
throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
}
- mGateway = gateway;
- mInterface = iface;
+ mDestination = destination; // IpPrefix objects are immutable.
+ mGateway = gateway; // InetAddress objects are immutable.
+ mInterface = iface; // Strings are immutable.
mIsHost = isHost();
}
/**
+ * @hide
+ */
+ public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
+ this(destination == null ? null :
+ new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
+ gateway, iface);
+ }
+
+ /**
* Constructs a {@code RouteInfo} object.
*
* If destination is null, then gateway must be specified and the
@@ -164,7 +163,7 @@
* @hide
*/
public RouteInfo(InetAddress gateway) {
- this((LinkAddress) null, gateway, null);
+ this((IpPrefix) null, gateway, null);
}
/**
@@ -200,9 +199,9 @@
if (host == null) return null;
if (host instanceof Inet4Address) {
- return new RouteInfo(new LinkAddress(host, 32), gateway, iface);
+ return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
} else {
- return new RouteInfo(new LinkAddress(host, 128), gateway, iface);
+ return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
}
}
@@ -219,7 +218,7 @@
* @return {@link IpPrefix} specifying the destination. This is never {@code null}.
*/
public IpPrefix getDestination() {
- return new IpPrefix(mDestination.getAddress(), mDestination.getPrefixLength());
+ return mDestination;
}
/**
@@ -227,7 +226,7 @@
* @hide
*/
public LinkAddress getDestinationLinkAddress() {
- return mDestination;
+ return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
}
/**
@@ -363,7 +362,7 @@
RouteInfo target = (RouteInfo) obj;
- return Objects.equals(mDestination, target.getDestinationLinkAddress()) &&
+ return Objects.equals(mDestination, target.getDestination()) &&
Objects.equals(mGateway, target.getGateway()) &&
Objects.equals(mInterface, target.getInterface());
}
@@ -388,16 +387,9 @@
* Implement the Parcelable interface
*/
public void writeToParcel(Parcel dest, int flags) {
- dest.writeByteArray(mDestination.getAddress().getAddress());
- dest.writeInt(mDestination.getPrefixLength());
-
- if (mGateway == null) {
- dest.writeByte((byte) 0);
- } else {
- dest.writeByte((byte) 1);
- dest.writeByteArray(mGateway.getAddress());
- }
-
+ dest.writeParcelable(mDestination, flags);
+ byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
+ dest.writeByteArray(gatewayBytes);
dest.writeString(mInterface);
}
@@ -407,33 +399,16 @@
public static final Creator<RouteInfo> CREATOR =
new Creator<RouteInfo>() {
public RouteInfo createFromParcel(Parcel in) {
- InetAddress destAddr = null;
- int prefix = 0;
+ IpPrefix dest = in.readParcelable(null);
+
InetAddress gateway = null;
-
byte[] addr = in.createByteArray();
- prefix = in.readInt();
-
try {
- destAddr = InetAddress.getByAddress(addr);
+ gateway = InetAddress.getByAddress(addr);
} catch (UnknownHostException e) {}
- if (in.readByte() == 1) {
- addr = in.createByteArray();
-
- try {
- gateway = InetAddress.getByAddress(addr);
- } catch (UnknownHostException e) {}
- }
-
String iface = in.readString();
- LinkAddress dest = null;
-
- if (destAddr != null) {
- dest = new LinkAddress(destAddr, prefix);
- }
-
return new RouteInfo(dest, gateway, iface);
}
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/core/tests/coretests/src/android/net/RouteInfoTest.java
index dcacd11..0b88bc7 100644
--- a/core/tests/coretests/src/android/net/RouteInfoTest.java
+++ b/core/tests/coretests/src/android/net/RouteInfoTest.java
@@ -214,6 +214,29 @@
assertFalse(r.isIPv6Default());
}
+ public void testTruncation() {
+ LinkAddress l;
+ RouteInfo r;
+
+ l = new LinkAddress("192.0.2.5/30");
+ r = new RouteInfo(l, Address("192.0.2.1"), "wlan0");
+ assertEquals("192.0.2.4", r.getDestination().getAddress().getHostAddress());
+
+ l = new LinkAddress("2001:db8:1:f::5/63");
+ r = new RouteInfo(l, Address("2001:db8:5::1"), "wlan0");
+ assertEquals("2001:db8:1:e::", r.getDestination().getAddress().getHostAddress());
+ }
+
+ // Make sure that creating routes to multicast addresses doesn't throw an exception. Even though
+ // there's nothing we can do with them, we don't want to crash if, e.g., someone calls
+ // requestRouteToHostAddress("230.0.0.0", MOBILE_HIPRI);
+ public void testMulticastRoute() {
+ RouteInfo r;
+ r = new RouteInfo(Prefix("230.0.0.0/32"), Address("192.0.2.1"), "wlan0");
+ r = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::1"), "wlan0");
+ // No exceptions? Good.
+ }
+
public RouteInfo passThroughParcel(RouteInfo r) {
Parcel p = Parcel.obtain();
RouteInfo r2 = null;