blob: 5c0f7582091ddc2afcf4d6b381c5e74263896e8e [file] [log] [blame]
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090019import android.annotation.SystemApi;
20import android.annotation.TestApi;
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010021import android.annotation.UnsupportedAppUsage;
Mathew Inwood55418ea2018-12-20 15:30:45 +000022import android.os.Build;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070023import android.os.Parcel;
24import android.os.Parcelable;
25
Robert Greenwaltaa70f102011-04-28 14:28:50 -070026import java.net.Inet4Address;
27import java.net.Inet6Address;
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090028import java.net.InetAddress;
29import java.net.UnknownHostException;
Robert Greenwaltf43396c2011-05-06 17:10:53 -070030import java.util.Collection;
Robert Greenwalt386aba82014-05-18 23:33:07 -070031import java.util.Objects;
Robert Greenwaltf43396c2011-05-06 17:10:53 -070032
Robert Greenwaltaa70f102011-04-28 14:28:50 -070033/**
Robert Greenwalt386aba82014-05-18 23:33:07 -070034 * Represents a network route.
Robert Greenwalt4095bd52014-05-18 12:05:05 -070035 * <p>
36 * This is used both to describe static network configuration and live network
Robert Greenwalt386aba82014-05-18 23:33:07 -070037 * configuration information.
Robert Greenwaltaa70f102011-04-28 14:28:50 -070038 *
Robert Greenwalt386aba82014-05-18 23:33:07 -070039 * A route contains three pieces of information:
Robert Greenwalt4095bd52014-05-18 12:05:05 -070040 * <ul>
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070041 * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route.
42 * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6)
Robert Greenwalt386aba82014-05-18 23:33:07 -070043 * implied by the gateway IP address.
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070044 * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
Robert Greenwalt386aba82014-05-18 23:33:07 -070045 * indicates a directly-connected route.
46 * <li>an interface (which may be unspecified).
Robert Greenwalt4095bd52014-05-18 12:05:05 -070047 * </ul>
Robert Greenwalt386aba82014-05-18 23:33:07 -070048 * Either the destination or the gateway may be {@code null}, but not both. If the
49 * destination and gateway are both specified, they must be of the same address family
50 * (IPv4 or IPv6).
Robert Greenwaltaa70f102011-04-28 14:28:50 -070051 */
Robert Greenwalte595b972014-06-12 16:24:38 -070052public final class RouteInfo implements Parcelable {
Robert Greenwaltaa70f102011-04-28 14:28:50 -070053 /**
54 * The IP destination address for this route.
55 */
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +090056 private final IpPrefix mDestination;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070057
58 /**
59 * The gateway address for this route.
60 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010061 @UnsupportedAppUsage
Robert Greenwaltaa70f102011-04-28 14:28:50 -070062 private final InetAddress mGateway;
63
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080064 /**
65 * The interface for this route.
66 */
67 private final String mInterface;
68
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090069
70 /** Unicast route. @hide */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090071 @SystemApi
72 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090073 public static final int RTN_UNICAST = 1;
74
75 /** Unreachable route. @hide */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090076 @SystemApi
77 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090078 public static final int RTN_UNREACHABLE = 7;
79
80 /** Throw route. @hide */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090081 @SystemApi
82 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090083 public static final int RTN_THROW = 9;
84
85 /**
86 * The type of this route; one of the RTN_xxx constants above.
87 */
88 private final int mType;
89
90 // Derived data members.
91 // TODO: remove these.
Mathew Inwood55418ea2018-12-20 15:30:45 +000092 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt0a46db52011-07-14 14:28:05 -070093 private final boolean mIsHost;
Robert Greenwaltca441ee2013-04-11 13:48:16 -070094 private final boolean mHasGateway;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070095
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080096 /**
97 * Constructs a RouteInfo object.
98 *
Lorenzo Colitti574b00a2013-03-12 04:30:47 +090099 * If destination is null, then gateway must be specified and the
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800100 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700101 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
Lorenzo Colitti574b00a2013-03-12 04:30:47 +0900102 * route <code>::/0</code> if gateway is an instance of
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800103 * {@link Inet6Address}.
Robert Greenwalt386aba82014-05-18 23:33:07 -0700104 * <p>
Lorenzo Colitti574b00a2013-03-12 04:30:47 +0900105 * destination and gateway may not both be null.
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800106 *
107 * @param destination the destination prefix
108 * @param gateway the IP address to route packets through
109 * @param iface the interface name to send packets on
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700110 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700111 * @hide
112 */
Remi NGUYEN VAN39fbb922019-01-24 00:55:43 +0900113 @SystemApi
114 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900115 public RouteInfo(IpPrefix destination, InetAddress gateway, String iface, int type) {
116 switch (type) {
117 case RTN_UNICAST:
118 case RTN_UNREACHABLE:
119 case RTN_THROW:
120 // TODO: It would be nice to ensure that route types that don't have nexthops or
121 // interfaces, such as unreachable or throw, can't be created if an interface or
122 // a gateway is specified. This is a bit too complicated to do at the moment
123 // because:
124 //
125 // - LinkProperties sets the interface on routes added to it, and modifies the
126 // interfaces of all the routes when its interface name changes.
127 // - Even when the gateway is null, we store a non-null gateway here.
128 //
129 // For now, we just rely on the code that sets routes to do things properly.
130 break;
131 default:
132 throw new IllegalArgumentException("Unknown route type " + type);
133 }
134
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700135 if (destination == null) {
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700136 if (gateway != null) {
137 if (gateway instanceof Inet4Address) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900138 destination = new IpPrefix(Inet4Address.ANY, 0);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700139 } else {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900140 destination = new IpPrefix(Inet6Address.ANY, 0);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700141 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700142 } else {
143 // no destination, no gateway. invalid.
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800144 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
145 destination);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700146 }
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700147 }
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900148 // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
149 // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
150 // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
Kazuhiro Ondo8c0b5282011-05-11 14:55:19 -0500151 if (gateway == null) {
152 if (destination.getAddress() instanceof Inet4Address) {
153 gateway = Inet4Address.ANY;
154 } else {
155 gateway = Inet6Address.ANY;
156 }
157 }
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700158 mHasGateway = (!gateway.isAnyLocalAddress());
159
Robert Greenwalt386aba82014-05-18 23:33:07 -0700160 if ((destination.getAddress() instanceof Inet4Address &&
161 (gateway instanceof Inet4Address == false)) ||
162 (destination.getAddress() instanceof Inet6Address &&
163 (gateway instanceof Inet6Address == false))) {
164 throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
165 }
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900166 mDestination = destination; // IpPrefix objects are immutable.
167 mGateway = gateway; // InetAddress objects are immutable.
168 mInterface = iface; // Strings are immutable.
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900169 mType = type;
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700170 mIsHost = isHost();
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700171 }
172
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700173 /**
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900174 * @hide
175 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100176 @UnsupportedAppUsage
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900177 public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
178 this(destination, gateway, iface, RTN_UNICAST);
179 }
180
181 /**
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900182 * @hide
183 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100184 @UnsupportedAppUsage
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900185 public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
186 this(destination == null ? null :
187 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
188 gateway, iface);
189 }
190
191 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700192 * Constructs a {@code RouteInfo} object.
193 *
194 * If destination is null, then gateway must be specified and the
195 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
196 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
197 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
198 * <p>
199 * Destination and gateway may not both be null.
200 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700201 * @param destination the destination address and prefix in an {@link IpPrefix}
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700202 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700203 *
204 * @hide
205 */
206 public RouteInfo(IpPrefix destination, InetAddress gateway) {
207 this(destination, gateway, null);
208 }
209
210 /**
211 * @hide
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900212 *
213 * TODO: Remove this.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700214 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100215 @UnsupportedAppUsage
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800216 public RouteInfo(LinkAddress destination, InetAddress gateway) {
217 this(destination, gateway, null);
218 }
219
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700220 /**
221 * Constructs a default {@code RouteInfo} object.
222 *
223 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700224 *
225 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700226 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100227 @UnsupportedAppUsage
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700228 public RouteInfo(InetAddress gateway) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900229 this((IpPrefix) null, gateway, null);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700230 }
231
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700232 /**
233 * Constructs a {@code RouteInfo} object representing a direct connected subnet.
234 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700235 * @param destination the {@link IpPrefix} describing the address and prefix
Robert Greenwalt386aba82014-05-18 23:33:07 -0700236 * length of the subnet.
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700237 *
238 * @hide
239 */
240 public RouteInfo(IpPrefix destination) {
241 this(destination, null, null);
242 }
243
244 /**
245 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700246 */
Robert Greenwalt386aba82014-05-18 23:33:07 -0700247 public RouteInfo(LinkAddress destination) {
248 this(destination, null, null);
Robert Greenwalt4717c262012-10-31 14:32:53 -0700249 }
250
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700251 /**
252 * @hide
253 */
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900254 public RouteInfo(IpPrefix destination, int type) {
255 this(destination, null, null, type);
256 }
257
258 /**
259 * @hide
260 */
Lorenzo Colittie1671352013-03-08 12:30:44 -0800261 public static RouteInfo makeHostRoute(InetAddress host, String iface) {
262 return makeHostRoute(host, null, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700263 }
264
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700265 /**
266 * @hide
267 */
Lorenzo Colittie1671352013-03-08 12:30:44 -0800268 public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700269 if (host == null) return null;
270
271 if (host instanceof Inet4Address) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900272 return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700273 } else {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900274 return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700275 }
276 }
277
Mathew Inwood55418ea2018-12-20 15:30:45 +0000278 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700279 private boolean isHost() {
Lorenzo Colittifdadc4e2013-03-27 13:07:18 +0900280 return (mDestination.getAddress() instanceof Inet4Address &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900281 mDestination.getPrefixLength() == 32) ||
Lorenzo Colittifdadc4e2013-03-27 13:07:18 +0900282 (mDestination.getAddress() instanceof Inet6Address &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900283 mDestination.getPrefixLength() == 128);
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700284 }
285
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700286 /**
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700287 * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700288 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700289 * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700290 */
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700291 public IpPrefix getDestination() {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900292 return mDestination;
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700293 }
294
295 /**
296 * TODO: Convert callers to use IpPrefix and then remove.
297 * @hide
298 */
299 public LinkAddress getDestinationLinkAddress() {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900300 return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700301 }
302
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700303 /**
304 * Retrieves the gateway or next hop {@link InetAddress} for this route.
305 *
Robert Greenwalt386aba82014-05-18 23:33:07 -0700306 * @return {@link InetAddress} specifying the gateway or next hop. This may be
Robert Greenwalte595b972014-06-12 16:24:38 -0700307 * {@code null} for a directly-connected route."
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700308 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700309 public InetAddress getGateway() {
310 return mGateway;
311 }
312
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700313 /**
Robert Greenwalt386aba82014-05-18 23:33:07 -0700314 * Retrieves the interface used for this route if specified, else {@code null}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700315 *
316 * @return The name of the interface used for this route.
317 */
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800318 public String getInterface() {
319 return mInterface;
320 }
321
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700322 /**
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900323 * Retrieves the type of this route.
324 *
325 * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
326 *
327 * @hide
328 */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +0900329 @TestApi
330 @SystemApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900331 public int getType() {
332 return mType;
333 }
334
335 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700336 * Indicates if this route is a default route (ie, has no destination specified).
337 *
Robert Greenwalt386aba82014-05-18 23:33:07 -0700338 * @return {@code true} if the destination has a prefix length of 0.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700339 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700340 public boolean isDefaultRoute() {
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900341 return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900342 }
343
344 /**
345 * Indicates if this route is an IPv4 default route.
346 * @hide
347 */
348 public boolean isIPv4Default() {
349 return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
350 }
351
352 /**
353 * Indicates if this route is an IPv6 default route.
354 * @hide
355 */
356 public boolean isIPv6Default() {
357 return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700358 }
359
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700360 /**
361 * Indicates if this route is a host route (ie, matches only a single host address).
362 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700363 * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
364 * respectively.
Robert Greenwalt386aba82014-05-18 23:33:07 -0700365 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700366 */
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700367 public boolean isHostRoute() {
368 return mIsHost;
369 }
370
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700371 /**
372 * Indicates if this route has a next hop ({@code true}) or is directly-connected
373 * ({@code false}).
374 *
375 * @return {@code true} if a gateway is specified
376 */
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700377 public boolean hasGateway() {
378 return mHasGateway;
379 }
380
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700381 /**
Robert Greenwalt386aba82014-05-18 23:33:07 -0700382 * Determines whether the destination and prefix of this route includes the specified
383 * address.
384 *
385 * @param destination A {@link InetAddress} to test to see if it would match this route.
386 * @return {@code true} if the destination and prefix length cover the given address.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700387 */
Robert Greenwalt386aba82014-05-18 23:33:07 -0700388 public boolean matches(InetAddress destination) {
Erik Klineacc8c092015-04-13 15:33:34 +0900389 return mDestination.contains(destination);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700390 }
391
392 /**
393 * Find the route from a Collection of routes that best matches a given address.
394 * May return null if no routes are applicable.
395 * @param routes a Collection of RouteInfos to chose from
396 * @param dest the InetAddress your trying to get to
397 * @return the RouteInfo from the Collection that best fits the given address
398 *
399 * @hide
400 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100401 @UnsupportedAppUsage
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700402 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
403 if ((routes == null) || (dest == null)) return null;
404
405 RouteInfo bestRoute = null;
406 // pick a longest prefix match under same address type
407 for (RouteInfo route : routes) {
408 if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
409 if ((bestRoute != null) &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900410 (bestRoute.mDestination.getPrefixLength() >=
411 route.mDestination.getPrefixLength())) {
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700412 continue;
413 }
414 if (route.matches(dest)) bestRoute = route;
415 }
416 }
417 return bestRoute;
418 }
419
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700420 /**
421 * Returns a human-readable description of this object.
422 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700423 public String toString() {
424 String val = "";
425 if (mDestination != null) val = mDestination.toString();
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900426 if (mType == RTN_UNREACHABLE) {
427 val += " unreachable";
428 } else if (mType == RTN_THROW) {
429 val += " throw";
430 } else {
431 val += " ->";
432 if (mGateway != null) val += " " + mGateway.getHostAddress();
433 if (mInterface != null) val += " " + mInterface;
434 if (mType != RTN_UNICAST) {
435 val += " unknown type " + mType;
436 }
437 }
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700438 return val;
439 }
440
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700441 /**
442 * Compares this RouteInfo object against the specified object and indicates if they are equal.
443 * @return {@code true} if the objects are equal, {@code false} otherwise.
444 */
Wink Savillebe2b0582011-05-18 15:59:04 -0700445 public boolean equals(Object obj) {
446 if (this == obj) return true;
447
448 if (!(obj instanceof RouteInfo)) return false;
449
450 RouteInfo target = (RouteInfo) obj;
451
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900452 return Objects.equals(mDestination, target.getDestination()) &&
Robert Greenwalt386aba82014-05-18 23:33:07 -0700453 Objects.equals(mGateway, target.getGateway()) &&
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900454 Objects.equals(mInterface, target.getInterface()) &&
455 mType == target.getType();
Wink Savillebe2b0582011-05-18 15:59:04 -0700456 }
457
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700458 /**
459 * Returns a hashcode for this <code>RouteInfo</code> object.
460 */
Wink Savillebe2b0582011-05-18 15:59:04 -0700461 public int hashCode() {
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900462 return (mDestination.hashCode() * 41)
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700463 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900464 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
465 + (mType * 71);
Wink Savillebe2b0582011-05-18 15:59:04 -0700466 }
467
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700468 /**
469 * Implement the Parcelable interface
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700470 */
471 public int describeContents() {
472 return 0;
473 }
474
475 /**
476 * Implement the Parcelable interface
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700477 */
478 public void writeToParcel(Parcel dest, int flags) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900479 dest.writeParcelable(mDestination, flags);
480 byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
481 dest.writeByteArray(gatewayBytes);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700482 dest.writeString(mInterface);
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900483 dest.writeInt(mType);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700484 }
485
486 /**
487 * Implement the Parcelable interface.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700488 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700489 public static final Creator<RouteInfo> CREATOR =
490 new Creator<RouteInfo>() {
491 public RouteInfo createFromParcel(Parcel in) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900492 IpPrefix dest = in.readParcelable(null);
493
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700494 InetAddress gateway = null;
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900495 byte[] addr = in.createByteArray();
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900496 try {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900497 gateway = InetAddress.getByAddress(addr);
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900498 } catch (UnknownHostException e) {}
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700499
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800500 String iface = in.readString();
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900501 int type = in.readInt();
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800502
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900503 return new RouteInfo(dest, gateway, iface, type);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700504 }
505
506 public RouteInfo[] newArray(int size) {
507 return new RouteInfo[size];
508 }
509 };
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700510}