667 lines
22 KiB
Java
667 lines
22 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2011 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.annotation.IntDef;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.annotation.SystemApi;
|
||
|
import android.compat.annotation.UnsupportedAppUsage;
|
||
|
import android.os.Build;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
|
||
|
import com.android.net.module.util.NetUtils;
|
||
|
import com.android.net.module.util.NetworkStackConstants;
|
||
|
|
||
|
import java.lang.annotation.Retention;
|
||
|
import java.lang.annotation.RetentionPolicy;
|
||
|
import java.net.Inet4Address;
|
||
|
import java.net.Inet6Address;
|
||
|
import java.net.InetAddress;
|
||
|
import java.net.UnknownHostException;
|
||
|
import java.util.Collection;
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/**
|
||
|
* Represents a network route.
|
||
|
* <p>
|
||
|
* This is used both to describe static network configuration and live network
|
||
|
* configuration information.
|
||
|
*
|
||
|
* A route contains three pieces of information:
|
||
|
* <ul>
|
||
|
* <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} 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>
|
||
|
* Either the destination or the gateway may be {@code null}, but not both. If the
|
||
|
* destination and gateway are both specified, they must be of the same address family
|
||
|
* (IPv4 or IPv6).
|
||
|
*/
|
||
|
public final class RouteInfo implements Parcelable {
|
||
|
/** @hide */
|
||
|
@IntDef(value = {
|
||
|
RTN_UNICAST,
|
||
|
RTN_UNREACHABLE,
|
||
|
RTN_THROW,
|
||
|
})
|
||
|
@Retention(RetentionPolicy.SOURCE)
|
||
|
public @interface RouteType {}
|
||
|
|
||
|
/**
|
||
|
* The IP destination address for this route.
|
||
|
*/
|
||
|
@NonNull
|
||
|
private final IpPrefix mDestination;
|
||
|
|
||
|
/**
|
||
|
* The gateway address for this route.
|
||
|
*/
|
||
|
@UnsupportedAppUsage
|
||
|
@Nullable
|
||
|
private final InetAddress mGateway;
|
||
|
|
||
|
/**
|
||
|
* The interface for this route.
|
||
|
*/
|
||
|
@Nullable
|
||
|
private final String mInterface;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Unicast route.
|
||
|
*
|
||
|
* Indicates that destination is reachable directly or via gateway.
|
||
|
**/
|
||
|
public static final int RTN_UNICAST = 1;
|
||
|
|
||
|
/**
|
||
|
* Unreachable route.
|
||
|
*
|
||
|
* Indicates that destination is unreachable.
|
||
|
**/
|
||
|
public static final int RTN_UNREACHABLE = 7;
|
||
|
|
||
|
/**
|
||
|
* Throw route.
|
||
|
*
|
||
|
* Indicates that routing information about this destination is not in this table.
|
||
|
* Routing lookup should continue in another table.
|
||
|
**/
|
||
|
public static final int RTN_THROW = 9;
|
||
|
|
||
|
/**
|
||
|
* The type of this route; one of the RTN_xxx constants above.
|
||
|
*/
|
||
|
private final int mType;
|
||
|
|
||
|
/**
|
||
|
* The maximum transmission unit size for this route.
|
||
|
*/
|
||
|
private final int mMtu;
|
||
|
|
||
|
// Derived data members.
|
||
|
// TODO: remove these.
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||
|
private final boolean mIsHost;
|
||
|
private final boolean mHasGateway;
|
||
|
|
||
|
/**
|
||
|
* Constructs a RouteInfo object.
|
||
|
*
|
||
|
* If destination is null, then gateway must be specified and the
|
||
|
* constructed route is either the IPv4 default route <code>0.0.0.0</code>
|
||
|
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
|
||
|
* route <code>::/0</code> if gateway is an instance of
|
||
|
* {@link Inet6Address}.
|
||
|
* <p>
|
||
|
* destination and gateway may not both be null.
|
||
|
*
|
||
|
* @param destination the destination prefix
|
||
|
* @param gateway the IP address to route packets through
|
||
|
* @param iface the interface name to send packets on
|
||
|
* @param type the type of this route
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
|
||
|
@Nullable String iface, @RouteType int type) {
|
||
|
this(destination, gateway, iface, type, 0);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructs a RouteInfo object.
|
||
|
*
|
||
|
* If destination is null, then gateway must be specified and the
|
||
|
* constructed route is either the IPv4 default route <code>0.0.0.0</code>
|
||
|
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
|
||
|
* route <code>::/0</code> if gateway is an instance of
|
||
|
* {@link Inet6Address}.
|
||
|
* <p>
|
||
|
* destination and gateway may not both be null.
|
||
|
*
|
||
|
* @param destination the destination prefix
|
||
|
* @param gateway the IP address to route packets through
|
||
|
* @param iface the interface name to send packets on
|
||
|
* @param type the type of this route
|
||
|
* @param mtu the maximum transmission unit size for this route
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
|
||
|
@Nullable String iface, @RouteType int type, int mtu) {
|
||
|
switch (type) {
|
||
|
case RTN_UNICAST:
|
||
|
case RTN_UNREACHABLE:
|
||
|
case RTN_THROW:
|
||
|
// TODO: It would be nice to ensure that route types that don't have nexthops or
|
||
|
// interfaces, such as unreachable or throw, can't be created if an interface or
|
||
|
// a gateway is specified. This is a bit too complicated to do at the moment
|
||
|
// because:
|
||
|
//
|
||
|
// - LinkProperties sets the interface on routes added to it, and modifies the
|
||
|
// interfaces of all the routes when its interface name changes.
|
||
|
// - Even when the gateway is null, we store a non-null gateway here.
|
||
|
//
|
||
|
// For now, we just rely on the code that sets routes to do things properly.
|
||
|
break;
|
||
|
default:
|
||
|
throw new IllegalArgumentException("Unknown route type " + type);
|
||
|
}
|
||
|
|
||
|
if (destination == null) {
|
||
|
if (gateway != null) {
|
||
|
if (gateway instanceof Inet4Address) {
|
||
|
destination = new IpPrefix(NetworkStackConstants.IPV4_ADDR_ANY, 0);
|
||
|
} else {
|
||
|
destination = new IpPrefix(NetworkStackConstants.IPV6_ADDR_ANY, 0);
|
||
|
}
|
||
|
} else {
|
||
|
// no destination, no gateway. invalid.
|
||
|
throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
|
||
|
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 = NetworkStackConstants.IPV4_ADDR_ANY;
|
||
|
} else {
|
||
|
gateway = NetworkStackConstants.IPV6_ADDR_ANY;
|
||
|
}
|
||
|
}
|
||
|
mHasGateway = (!gateway.isAnyLocalAddress());
|
||
|
|
||
|
if ((destination.getAddress() instanceof Inet4Address
|
||
|
&& !(gateway instanceof Inet4Address))
|
||
|
|| (destination.getAddress() instanceof Inet6Address
|
||
|
&& !(gateway instanceof Inet6Address))) {
|
||
|
throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
|
||
|
}
|
||
|
mDestination = destination; // IpPrefix objects are immutable.
|
||
|
mGateway = gateway; // InetAddress objects are immutable.
|
||
|
mInterface = iface; // Strings are immutable.
|
||
|
mType = type;
|
||
|
mIsHost = isHost();
|
||
|
mMtu = mtu;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructs a {@code RouteInfo} object.
|
||
|
*
|
||
|
* If destination is null, then gateway must be specified and the
|
||
|
* constructed route is either the IPv4 default route <code>0.0.0.0</code>
|
||
|
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
|
||
|
* route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
|
||
|
* <p>
|
||
|
* Destination and gateway may not both be null.
|
||
|
*
|
||
|
* @param destination the destination address and prefix in an {@link IpPrefix}
|
||
|
* @param gateway the {@link InetAddress} to route packets through
|
||
|
* @param iface the interface name to send packets on
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||
|
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
|
||
|
@Nullable String iface) {
|
||
|
this(destination, gateway, iface, RTN_UNICAST);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
@UnsupportedAppUsage
|
||
|
public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway,
|
||
|
@Nullable 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
|
||
|
* constructed route is either the IPv4 default route <code>0.0.0.0</code>
|
||
|
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
|
||
|
* route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
|
||
|
* <p>
|
||
|
* Destination and gateway may not both be null.
|
||
|
*
|
||
|
* @param destination the destination address and prefix in an {@link IpPrefix}
|
||
|
* @param gateway the {@link InetAddress} to route packets through
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) {
|
||
|
this(destination, gateway, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*
|
||
|
* TODO: Remove this.
|
||
|
*/
|
||
|
@UnsupportedAppUsage
|
||
|
public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) {
|
||
|
this(destination, gateway, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructs a default {@code RouteInfo} object.
|
||
|
*
|
||
|
* @param gateway the {@link InetAddress} to route packets through
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@UnsupportedAppUsage
|
||
|
public RouteInfo(@NonNull InetAddress gateway) {
|
||
|
this((IpPrefix) null, gateway, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Constructs a {@code RouteInfo} object representing a direct connected subnet.
|
||
|
*
|
||
|
* @param destination the {@link IpPrefix} describing the address and prefix
|
||
|
* length of the subnet.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public RouteInfo(@NonNull IpPrefix destination) {
|
||
|
this(destination, null, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public RouteInfo(@NonNull LinkAddress destination) {
|
||
|
this(destination, null, null);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) {
|
||
|
this(destination, null, null, type);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) {
|
||
|
return makeHostRoute(host, null, iface);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @hide
|
||
|
*/
|
||
|
public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway,
|
||
|
@Nullable String iface) {
|
||
|
if (host == null) return null;
|
||
|
|
||
|
if (host instanceof Inet4Address) {
|
||
|
return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
|
||
|
} else {
|
||
|
return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||
|
private boolean isHost() {
|
||
|
return (mDestination.getAddress() instanceof Inet4Address &&
|
||
|
mDestination.getPrefixLength() == 32) ||
|
||
|
(mDestination.getAddress() instanceof Inet6Address &&
|
||
|
mDestination.getPrefixLength() == 128);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
|
||
|
*
|
||
|
* @return {@link IpPrefix} specifying the destination. This is never {@code null}.
|
||
|
*/
|
||
|
@NonNull
|
||
|
public IpPrefix getDestination() {
|
||
|
return mDestination;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* TODO: Convert callers to use IpPrefix and then remove.
|
||
|
* @hide
|
||
|
*/
|
||
|
@NonNull
|
||
|
public LinkAddress getDestinationLinkAddress() {
|
||
|
return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the gateway or next hop {@link InetAddress} for this route.
|
||
|
*
|
||
|
* @return {@link InetAddress} specifying the gateway or next hop. This may be
|
||
|
* {@code null} for a directly-connected route."
|
||
|
*/
|
||
|
@Nullable
|
||
|
public InetAddress getGateway() {
|
||
|
return mGateway;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the interface used for this route if specified, else {@code null}.
|
||
|
*
|
||
|
* @return The name of the interface used for this route.
|
||
|
*/
|
||
|
@Nullable
|
||
|
public String getInterface() {
|
||
|
return mInterface;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the type of this route.
|
||
|
*
|
||
|
* @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
|
||
|
*/
|
||
|
@RouteType
|
||
|
public int getType() {
|
||
|
return mType;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the MTU size for this route.
|
||
|
*
|
||
|
* @return The MTU size, or 0 if it has not been set.
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public int getMtu() {
|
||
|
return mMtu;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route is a default route (ie, has no destination specified).
|
||
|
*
|
||
|
* @return {@code true} if the destination has a prefix length of 0.
|
||
|
*/
|
||
|
public boolean isDefaultRoute() {
|
||
|
return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route is an unreachable default route.
|
||
|
*
|
||
|
* @return {@code true} if it's an unreachable route with prefix length of 0.
|
||
|
* @hide
|
||
|
*/
|
||
|
private boolean isUnreachableDefaultRoute() {
|
||
|
return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route is an IPv4 default route.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean isIPv4Default() {
|
||
|
return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route is an IPv4 unreachable default route.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean isIPv4UnreachableDefault() {
|
||
|
return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route is an IPv6 default route.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean isIPv6Default() {
|
||
|
return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route is an IPv6 unreachable default route.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean isIPv6UnreachableDefault() {
|
||
|
return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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 or 128 for IPv4 or IPv6,
|
||
|
* respectively.
|
||
|
* @hide
|
||
|
*/
|
||
|
public boolean isHostRoute() {
|
||
|
return mIsHost;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Indicates if this route has a next hop ({@code true}) or is directly-connected
|
||
|
* ({@code false}).
|
||
|
*
|
||
|
* @return {@code true} if a gateway is specified
|
||
|
*/
|
||
|
public boolean hasGateway() {
|
||
|
return mHasGateway;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determines whether the destination and prefix of this route includes the specified
|
||
|
* address.
|
||
|
*
|
||
|
* @param destination A {@link InetAddress} to test to see if it would match this route.
|
||
|
* @return {@code true} if the destination and prefix length cover the given address.
|
||
|
*/
|
||
|
public boolean matches(InetAddress destination) {
|
||
|
return mDestination.contains(destination);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Find the route from a Collection of routes that best matches a given address.
|
||
|
* May return null if no routes are applicable.
|
||
|
* @param routes a Collection of RouteInfos to chose from
|
||
|
* @param dest the InetAddress your trying to get to
|
||
|
* @return the RouteInfo from the Collection that best fits the given address
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
|
||
|
@Nullable
|
||
|
public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
|
||
|
return NetUtils.selectBestRoute(routes, dest);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a human-readable description of this object.
|
||
|
*/
|
||
|
public String toString() {
|
||
|
String val = "";
|
||
|
if (mDestination != null) val = mDestination.toString();
|
||
|
if (mType == RTN_UNREACHABLE) {
|
||
|
val += " unreachable";
|
||
|
} else if (mType == RTN_THROW) {
|
||
|
val += " throw";
|
||
|
} else {
|
||
|
val += " ->";
|
||
|
if (mGateway != null) val += " " + mGateway.getHostAddress();
|
||
|
if (mInterface != null) val += " " + mInterface;
|
||
|
if (mType != RTN_UNICAST) {
|
||
|
val += " unknown type " + mType;
|
||
|
}
|
||
|
}
|
||
|
val += " mtu " + mMtu;
|
||
|
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(@Nullable Object obj) {
|
||
|
if (this == obj) return true;
|
||
|
|
||
|
if (!(obj instanceof RouteInfo)) return false;
|
||
|
|
||
|
RouteInfo target = (RouteInfo) obj;
|
||
|
|
||
|
return Objects.equals(mDestination, target.getDestination()) &&
|
||
|
Objects.equals(mGateway, target.getGateway()) &&
|
||
|
Objects.equals(mInterface, target.getInterface()) &&
|
||
|
mType == target.getType() && mMtu == target.getMtu();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* A helper class that contains the destination, the gateway and the interface in a
|
||
|
* {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or
|
||
|
* {@link LinkProperties#addRoute} to calculate the list to be updated.
|
||
|
* {@code RouteInfo} objects with different interfaces are treated as different routes because
|
||
|
* *usually* on Android different interfaces use different routing tables, and moving a route
|
||
|
* to a new routing table never constitutes an update, but is always a remove and an add.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static class RouteKey {
|
||
|
@NonNull private final IpPrefix mDestination;
|
||
|
@Nullable private final InetAddress mGateway;
|
||
|
@Nullable private final String mInterface;
|
||
|
|
||
|
RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway,
|
||
|
@Nullable String iface) {
|
||
|
mDestination = destination;
|
||
|
mGateway = gateway;
|
||
|
mInterface = iface;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(@Nullable Object o) {
|
||
|
if (!(o instanceof RouteKey)) {
|
||
|
return false;
|
||
|
}
|
||
|
RouteKey p = (RouteKey) o;
|
||
|
// No need to do anything special for scoped addresses. Inet6Address#equals does not
|
||
|
// consider the scope ID, but the route IPCs (e.g., RoutingCoordinatorManager#addRoute)
|
||
|
// and the kernel ignore scoped addresses both in the prefix and in the nexthop and only
|
||
|
// look at RTA_OIF.
|
||
|
return Objects.equals(p.mDestination, mDestination)
|
||
|
&& Objects.equals(p.mGateway, mGateway)
|
||
|
&& Objects.equals(p.mInterface, mInterface);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(mDestination, mGateway, mInterface);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get {@code RouteKey} of this {@code RouteInfo}.
|
||
|
* @return a {@code RouteKey} object.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@NonNull
|
||
|
public RouteKey getRouteKey() {
|
||
|
return new RouteKey(mDestination, mGateway, mInterface);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns a hashcode for this <code>RouteInfo</code> object.
|
||
|
*/
|
||
|
public int hashCode() {
|
||
|
return (mDestination.hashCode() * 41)
|
||
|
+ (mGateway == null ? 0 :mGateway.hashCode() * 47)
|
||
|
+ (mInterface == null ? 0 :mInterface.hashCode() * 67)
|
||
|
+ (mType * 71) + (mMtu * 89);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement the Parcelable interface
|
||
|
*/
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement the Parcelable interface
|
||
|
*/
|
||
|
public void writeToParcel(Parcel dest, int flags) {
|
||
|
dest.writeParcelable(mDestination, flags);
|
||
|
byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
|
||
|
dest.writeByteArray(gatewayBytes);
|
||
|
dest.writeString(mInterface);
|
||
|
dest.writeInt(mType);
|
||
|
dest.writeInt(mMtu);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Implement the Parcelable interface.
|
||
|
*/
|
||
|
public static final @android.annotation.NonNull Creator<RouteInfo> CREATOR =
|
||
|
new Creator<RouteInfo>() {
|
||
|
public RouteInfo createFromParcel(Parcel in) {
|
||
|
IpPrefix dest = in.readParcelable(null);
|
||
|
|
||
|
InetAddress gateway = null;
|
||
|
byte[] addr = in.createByteArray();
|
||
|
try {
|
||
|
gateway = InetAddress.getByAddress(addr);
|
||
|
} catch (UnknownHostException e) {}
|
||
|
|
||
|
String iface = in.readString();
|
||
|
int type = in.readInt();
|
||
|
int mtu = in.readInt();
|
||
|
|
||
|
return new RouteInfo(dest, gateway, iface, type, mtu);
|
||
|
}
|
||
|
|
||
|
public RouteInfo[] newArray(int size) {
|
||
|
return new RouteInfo[size];
|
||
|
}
|
||
|
};
|
||
|
}
|