diff options
-rw-r--r-- | api/current.txt | 16 | ||||
-rw-r--r-- | core/java/android/net/IpPrefix.aidl | 20 | ||||
-rw-r--r-- | core/java/android/net/IpPrefix.java | 170 | ||||
-rw-r--r-- | core/java/android/net/LinkProperties.java | 15 | ||||
-rw-r--r-- | core/java/android/net/RouteInfo.java | 82 | ||||
-rw-r--r-- | core/tests/coretests/src/android/net/RouteInfoTest.java | 6 | ||||
-rw-r--r-- | services/core/java/com/android/server/ConnectivityService.java | 4 | ||||
-rw-r--r-- | services/core/java/com/android/server/NetworkManagementService.java | 8 | ||||
-rw-r--r-- | services/core/java/com/android/server/net/IpConfigStore.java | 2 |
9 files changed, 286 insertions, 37 deletions
diff --git a/api/current.txt b/api/current.txt index 8b230b6..56c9c92 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16017,6 +16017,14 @@ package android.net { field public int serverAddress; } + public class IpPrefix implements android.os.Parcelable { + method public int describeContents(); + method public java.net.InetAddress getAddress(); + method public int getPrefixLength(); + method public byte[] getRawAddress(); + method public void writeToParcel(android.os.Parcel, int); + } + public class LinkAddress implements android.os.Parcelable { method public int describeContents(); method public java.net.InetAddress getAddress(); @@ -16028,8 +16036,6 @@ package android.net { } public class LinkProperties implements android.os.Parcelable { - ctor public LinkProperties(); - ctor public LinkProperties(android.net.LinkProperties); method public int describeContents(); method public java.util.List<java.net.InetAddress> getDnsServers(); method public java.lang.String getDomains(); @@ -16237,12 +16243,8 @@ package android.net { } public class RouteInfo implements android.os.Parcelable { - ctor public RouteInfo(android.net.LinkAddress, java.net.InetAddress, java.lang.String); - ctor public RouteInfo(android.net.LinkAddress, java.net.InetAddress); - ctor public RouteInfo(java.net.InetAddress); - ctor public RouteInfo(android.net.LinkAddress); method public int describeContents(); - method public android.net.LinkAddress getDestination(); + method public android.net.IpPrefix getDestination(); method public java.net.InetAddress getGateway(); method public java.lang.String getInterface(); method public boolean isDefaultRoute(); diff --git a/core/java/android/net/IpPrefix.aidl b/core/java/android/net/IpPrefix.aidl new file mode 100644 index 0000000..9e552c7 --- /dev/null +++ b/core/java/android/net/IpPrefix.aidl @@ -0,0 +1,20 @@ +/** + * + * Copyright (C) 2014 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 IpPrefix; diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java new file mode 100644 index 0000000..a14d13f --- /dev/null +++ b/core/java/android/net/IpPrefix.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2014 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; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; + +/** + * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a + * power of two boundary (also known as an "IP subnet"). A prefix is specified by two pieces of + * information: + * + * <ul> + * <li>A starting IP address (IPv4 or IPv6). This is the first IP address of the prefix. + * <li>A prefix length. This specifies the length of the prefix by specifing the number of bits + * in the IP address, starting from the most significant bit in network byte order, that + * are constant for all addresses in the prefix. + * </ul> + * + * For example, the prefix <code>192.0.2.0/24</code> covers the 256 IPv4 addresses from + * <code>192.0.2.0</code> to <code>192.0.2.255</code>, inclusive, and the prefix + * <code>2001:db8:1:2</code> covers the 2^64 IPv6 addresses from <code>2001:db8:1:2::</code> to + * <code>2001:db8:1:2:ffff:ffff:ffff:ffff</code>, inclusive. + * + * Objects of this class are immutable. + */ +public final class IpPrefix implements Parcelable { + private final byte[] address; // network byte order + private final int prefixLength; + + /** + * Constructs a new {@code IpPrefix} from a byte array containing an IPv4 or IPv6 address in + * network byte order and a prefix length. + * + * @param address the IP address. Must be non-null and exactly 4 or 16 bytes long. + * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * + * @hide + */ + public IpPrefix(byte[] address, int prefixLength) { + if (address.length != 4 && address.length != 16) { + throw new IllegalArgumentException( + "IpPrefix has " + address.length + " bytes which is neither 4 nor 16"); + } + if (prefixLength < 0 || prefixLength > (address.length * 8)) { + throw new IllegalArgumentException("IpPrefix with " + address.length + + " bytes has invalid prefix length " + prefixLength); + } + this.address = address.clone(); + this.prefixLength = prefixLength; + // TODO: Validate that the non-prefix bits are zero + } + + /** + * @hide + */ + public IpPrefix(InetAddress address, int prefixLength) { + this(address.getAddress(), prefixLength); + } + + /** + * Compares this {@code IpPrefix} object against the specified object in {@code obj}. Two + * objects are equal if they have the same startAddress and prefixLength. + * + * @param obj the object to be tested for equality. + * @return {@code true} if both objects are equal, {@code false} otherwise. + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof IpPrefix)) { + return false; + } + IpPrefix that = (IpPrefix) obj; + return Arrays.equals(this.address, that.address) && this.prefixLength == that.prefixLength; + } + + /** + * Gets the hashcode of the represented IP prefix. + * + * @return the appropriate hashcode value. + */ + @Override + public int hashCode() { + return Arrays.hashCode(address) + 11 * prefixLength; + } + + /** + * Returns a copy of the first IP address in the prefix. Modifying the returned object does not + * change this object's contents. + * + * @return the address in the form of a byte array. + */ + public InetAddress getAddress() { + try { + return InetAddress.getByAddress(address); + } catch (UnknownHostException e) { + // Cannot happen. InetAddress.getByAddress can only throw an exception if the byte + // array is the wrong length, but we check that in the constructor. + return null; + } + } + + /** + * Returns a copy of the IP address bytes in network order (the highest order byte is the zeroth + * element). Modifying the returned array does not change this object's contents. + * + * @return the address in the form of a byte array. + */ + public byte[] getRawAddress() { + return address.clone(); + } + + /** + * Returns the prefix length of this {@code IpAddress}. + * + * @return the prefix length. + */ + public int getPrefixLength() { + return prefixLength; + } + + /** + * Implement the Parcelable interface. + */ + public int describeContents() { + return 0; + } + + /** + * Implement the Parcelable interface. + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(address); + dest.writeInt(prefixLength); + } + + /** + * Implement the Parcelable interface. + */ + public static final Creator<IpPrefix> CREATOR = + new Creator<IpPrefix>() { + public IpPrefix createFromParcel(Parcel in) { + byte[] address = in.createByteArray(); + int prefixLength = in.readInt(); + return new IpPrefix(address, prefixLength); + } + + public IpPrefix[] newArray(int size) { + return new IpPrefix[size]; + } + }; +} diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index cff9025..8eefa0f 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -44,7 +44,7 @@ import java.util.List; * does not affect live networks. * */ -public class LinkProperties implements Parcelable { +public final class LinkProperties implements Parcelable { // The interface described by the network link. private String mIfaceName; private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>(); @@ -77,9 +77,15 @@ public class LinkProperties implements Parcelable { } } + /** + * @hide + */ public LinkProperties() { } + /** + * @hide + */ public LinkProperties(LinkProperties source) { if (source != null) { mIfaceName = source.getInterfaceName(); @@ -267,7 +273,7 @@ public class LinkProperties implements Parcelable { } /** - * Returns all the {@link LinkAddress} for DNS servers on this link. + * Returns all the {@link InetAddress} for DNS servers on this link. * * @return An umodifiable {@link List} of {@link InetAddress} for DNS servers on * this link. @@ -457,7 +463,6 @@ public class LinkProperties implements Parcelable { /** * Implement the Parcelable interface - * @hide */ public int describeContents() { return 0; @@ -477,12 +482,12 @@ public class LinkProperties implements Parcelable { String domainName = "Domains: " + mDomains; - String mtu = "MTU: " + mMtu; + String mtu = " MTU: " + mMtu; String routes = " Routes: ["; for (RouteInfo route : mRoutes) routes += route.toString() + ","; routes += "] "; - String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " "); + String proxy = (mHttpProxy == null ? "" : " HttpProxy: " + mHttpProxy.toString() + " "); String stacked = ""; if (mStackedLinks.values().size() > 0) { diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index ad8e4f7..6d65d8f 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -35,10 +35,10 @@ import java.util.Objects; * * A route contains three pieces of information: * <ul> - * <li>a destination {@link LinkAddress} for directly-connected subnets. If this is - * {@code null} it indicates a default route of the address family (IPv4 or IPv6) + * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route. + * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6) * implied by the gateway IP address. - * <li>a gateway {@link InetAddress} for default routes. If this is {@code null} it + * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it * indicates a directly-connected route. * <li>an interface (which may be unspecified). * </ul> @@ -46,9 +46,10 @@ import java.util.Objects; * destination and gateway are both specified, they must be of the same address family * (IPv4 or IPv6). */ -public class RouteInfo implements Parcelable { +public final class RouteInfo implements Parcelable { /** * The IP destination address for this route. + * TODO: Make this an IpPrefix. */ private final LinkAddress mDestination; @@ -80,6 +81,19 @@ public class RouteInfo implements Parcelable { * @param destination the destination prefix * @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) { @@ -128,8 +142,17 @@ public class RouteInfo implements Parcelable { * <p> * Destination and gateway may not both be null. * - * @param destination the destination address and prefix in a {@link LinkAddress} + * @param destination the destination address and prefix in an {@link IpPrefix} * @param gateway the {@link InetAddress} to route packets through + * + * @hide + */ + public RouteInfo(IpPrefix destination, InetAddress gateway) { + this(destination, gateway, null); + } + + /** + * @hide */ public RouteInfo(LinkAddress destination, InetAddress gateway) { this(destination, gateway, null); @@ -139,16 +162,27 @@ public class RouteInfo implements Parcelable { * Constructs a default {@code RouteInfo} object. * * @param gateway the {@link InetAddress} to route packets through + * + * @hide */ public RouteInfo(InetAddress gateway) { - this(null, gateway, null); + this((LinkAddress) null, gateway, null); } /** * Constructs a {@code RouteInfo} object representing a direct connected subnet. * - * @param destination the {@link LinkAddress} describing the address and prefix + * @param destination the {@link IpPrefix} describing the address and prefix * length of the subnet. + * + * @hide + */ + public RouteInfo(IpPrefix destination) { + this(destination, null, null); + } + + /** + * @hide */ public RouteInfo(LinkAddress destination) { this(destination, null, null); @@ -194,11 +228,19 @@ public class RouteInfo implements Parcelable { } /** - * Retrieves the destination address and prefix length in the form of a {@link LinkAddress}. + * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}. * - * @return {@link LinkAddress} specifying the destination. This is never {@code null}. + * @return {@link IpPrefix} specifying the destination. This is never {@code null}. + */ + public IpPrefix getDestination() { + return new IpPrefix(mDestination.getAddress(), mDestination.getPrefixLength()); + } + + /** + * TODO: Convert callers to use IpPrefix and then remove. + * @hide */ - public LinkAddress getDestination() { + public LinkAddress getDestinationLinkAddress() { return mDestination; } @@ -233,7 +275,8 @@ public class RouteInfo implements Parcelable { /** * Indicates if this route is a host route (ie, matches only a single host address). * - * @return {@code true} if the destination has a prefix length of 32/128 for v4/v6. + * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6, + * respectively. * @hide */ public boolean isHostRoute() { @@ -295,13 +338,22 @@ public class RouteInfo implements Parcelable { return bestRoute; } + /** + * Returns a human-readable description of this object. + */ public String toString() { String val = ""; if (mDestination != null) val = mDestination.toString(); - if (mGateway != null) val += " -> " + mGateway.getHostAddress(); + val += " ->"; + if (mGateway != null) val += " " + mGateway.getHostAddress(); + if (mInterface != null) val += " " + mInterface; return val; } + /** + * Compares this RouteInfo object against the specified object and indicates if they are equal. + * @return {@code true} if the objects are equal, {@code false} otherwise. + */ public boolean equals(Object obj) { if (this == obj) return true; @@ -314,6 +366,9 @@ public class RouteInfo implements Parcelable { Objects.equals(mInterface, target.getInterface()); } + /** + * Returns a hashcode for this <code>RouteInfo</code> object. + */ public int hashCode() { return (mDestination == null ? 0 : mDestination.hashCode() * 41) + (mGateway == null ? 0 :mGateway.hashCode() * 47) @@ -323,7 +378,6 @@ public class RouteInfo implements Parcelable { /** * Implement the Parcelable interface - * @hide */ public int describeContents() { return 0; @@ -331,7 +385,6 @@ public class RouteInfo implements Parcelable { /** * Implement the Parcelable interface - * @hide */ public void writeToParcel(Parcel dest, int flags) { if (mDestination == null) { @@ -354,7 +407,6 @@ public class RouteInfo implements Parcelable { /** * Implement the Parcelable interface. - * @hide */ public static final Creator<RouteInfo> CREATOR = new Creator<RouteInfo>() { diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/core/tests/coretests/src/android/net/RouteInfoTest.java index 55d6592..01283a6 100644 --- a/core/tests/coretests/src/android/net/RouteInfoTest.java +++ b/core/tests/coretests/src/android/net/RouteInfoTest.java @@ -43,17 +43,17 @@ public class RouteInfoTest extends TestCase { // Invalid input. try { - r = new RouteInfo(null, null, "rmnet0"); + r = new RouteInfo((LinkAddress) null, null, "rmnet0"); fail("Expected RuntimeException: destination and gateway null"); } catch(RuntimeException e) {} // Null destination is default route. - r = new RouteInfo(null, Address("2001:db8::1"), null); + r = new RouteInfo((LinkAddress) null, Address("2001:db8::1"), null); assertEquals(Prefix("::/0"), r.getDestination()); assertEquals(Address("2001:db8::1"), r.getGateway()); assertNull(r.getInterface()); - r = new RouteInfo(null, Address("192.0.2.1"), "wlan0"); + r = new RouteInfo((LinkAddress) null, Address("192.0.2.1"), "wlan0"); assertEquals(Prefix("0.0.0.0/0"), r.getDestination()); assertEquals(Address("192.0.2.1"), r.getGateway()); assertEquals("wlan0", r.getInterface()); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 70b9d44..5b36ec6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1871,7 +1871,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetd.addRoute(netId, r); } if (exempt) { - LinkAddress dest = r.getDestination(); + LinkAddress dest = r.getDestinationLinkAddress(); if (!mExemptAddresses.contains(dest)) { mNetd.setHostExemption(dest); mExemptAddresses.add(dest); @@ -1904,7 +1904,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { mNetd.removeRoute(netId, r); } - LinkAddress dest = r.getDestination(); + LinkAddress dest = r.getDestinationLinkAddress(); if (mExemptAddresses.contains(dest)) { mNetd.clearHostExemption(dest); mExemptAddresses.remove(dest); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index eefe8da..3b748bd 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -882,7 +882,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub final Command cmd = new Command("network", "route", action, netId); // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr - final LinkAddress la = route.getDestination(); + final LinkAddress la = route.getDestinationLinkAddress(); cmd.appendArg(route.getInterface()); cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength()); if (route.hasGateway()) { @@ -1697,7 +1697,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void setMarkedForwardingRoute(String iface, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - LinkAddress dest = route.getDestination(); + LinkAddress dest = route.getDestinationLinkAddress(); mConnector.execute("interface", "fwmark", "route", "add", iface, dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); } catch (NativeDaemonConnectorException e) { @@ -1709,7 +1709,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void clearMarkedForwardingRoute(String iface, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { - LinkAddress dest = route.getDestination(); + LinkAddress dest = route.getDestinationLinkAddress(); mConnector.execute("interface", "fwmark", "route", "remove", iface, dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); } catch (NativeDaemonConnectorException e) { @@ -1998,7 +1998,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub final Command cmd = new Command("network", "route", "legacy", uid, action, netId); // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr - final LinkAddress la = routeInfo.getDestination(); + final LinkAddress la = routeInfo.getDestinationLinkAddress(); cmd.appendArg(routeInfo.getInterface()); cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength()); if (routeInfo.hasGateway()) { diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index bb0d5fe..35bc6ec 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -85,7 +85,7 @@ public class IpConfigStore { } for (RouteInfo route : linkProperties.getRoutes()) { out.writeUTF(GATEWAY_KEY); - LinkAddress dest = route.getDestination(); + LinkAddress dest = route.getDestinationLinkAddress(); if (dest != null) { out.writeInt(1); out.writeUTF(dest.getAddress().getHostAddress()); |