blob: 90a2460ff20c0f10d56387d59a80a17a8773254f [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
19import android.os.Parcel;
20import android.os.Parcelable;
21
22import java.net.UnknownHostException;
23import java.net.InetAddress;
24import java.net.Inet4Address;
25import java.net.Inet6Address;
Robert Greenwaltf43396c2011-05-06 17:10:53 -070026
27import java.util.Collection;
Robert Greenwalt386aba82014-05-18 23:33:07 -070028import java.util.Objects;
Robert Greenwaltf43396c2011-05-06 17:10:53 -070029
Robert Greenwaltaa70f102011-04-28 14:28:50 -070030/**
Robert Greenwalt386aba82014-05-18 23:33:07 -070031 * Represents a network route.
Robert Greenwalt4095bd52014-05-18 12:05:05 -070032 * <p>
33 * This is used both to describe static network configuration and live network
Robert Greenwalt386aba82014-05-18 23:33:07 -070034 * configuration information.
Robert Greenwaltaa70f102011-04-28 14:28:50 -070035 *
Robert Greenwalt386aba82014-05-18 23:33:07 -070036 * A route contains three pieces of information:
Robert Greenwalt4095bd52014-05-18 12:05:05 -070037 * <ul>
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070038 * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route.
39 * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6)
Robert Greenwalt386aba82014-05-18 23:33:07 -070040 * implied by the gateway IP address.
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070041 * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
Robert Greenwalt386aba82014-05-18 23:33:07 -070042 * indicates a directly-connected route.
43 * <li>an interface (which may be unspecified).
Robert Greenwalt4095bd52014-05-18 12:05:05 -070044 * </ul>
Robert Greenwalt386aba82014-05-18 23:33:07 -070045 * Either the destination or the gateway may be {@code null}, but not both. If the
46 * destination and gateway are both specified, they must be of the same address family
47 * (IPv4 or IPv6).
Robert Greenwaltaa70f102011-04-28 14:28:50 -070048 */
Robert Greenwalte595b972014-06-12 16:24:38 -070049public final class RouteInfo implements Parcelable {
Robert Greenwaltaa70f102011-04-28 14:28:50 -070050 /**
51 * The IP destination address for this route.
52 */
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +090053 private final IpPrefix mDestination;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070054
55 /**
56 * The gateway address for this route.
57 */
58 private final InetAddress mGateway;
59
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080060 /**
61 * The interface for this route.
62 */
63 private final String mInterface;
64
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090065
66 /** Unicast route. @hide */
67 public static final int RTN_UNICAST = 1;
68
69 /** Unreachable route. @hide */
70 public static final int RTN_UNREACHABLE = 7;
71
72 /** Throw route. @hide */
73 public static final int RTN_THROW = 9;
74
75 /**
76 * The type of this route; one of the RTN_xxx constants above.
77 */
78 private final int mType;
79
80 // Derived data members.
81 // TODO: remove these.
Robert Greenwalt0a46db52011-07-14 14:28:05 -070082 private final boolean mIsHost;
Robert Greenwaltca441ee2013-04-11 13:48:16 -070083 private final boolean mHasGateway;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070084
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080085 /**
86 * Constructs a RouteInfo object.
87 *
Lorenzo Colitti574b00a2013-03-12 04:30:47 +090088 * If destination is null, then gateway must be specified and the
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080089 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
Robert Greenwalt4095bd52014-05-18 12:05:05 -070090 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
Lorenzo Colitti574b00a2013-03-12 04:30:47 +090091 * route <code>::/0</code> if gateway is an instance of
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080092 * {@link Inet6Address}.
Robert Greenwalt386aba82014-05-18 23:33:07 -070093 * <p>
Lorenzo Colitti574b00a2013-03-12 04:30:47 +090094 * destination and gateway may not both be null.
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080095 *
96 * @param destination the destination prefix
97 * @param gateway the IP address to route packets through
98 * @param iface the interface name to send packets on
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070099 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700100 * @hide
101 */
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900102 public RouteInfo(IpPrefix destination, InetAddress gateway, String iface, int type) {
103 switch (type) {
104 case RTN_UNICAST:
105 case RTN_UNREACHABLE:
106 case RTN_THROW:
107 // TODO: It would be nice to ensure that route types that don't have nexthops or
108 // interfaces, such as unreachable or throw, can't be created if an interface or
109 // a gateway is specified. This is a bit too complicated to do at the moment
110 // because:
111 //
112 // - LinkProperties sets the interface on routes added to it, and modifies the
113 // interfaces of all the routes when its interface name changes.
114 // - Even when the gateway is null, we store a non-null gateway here.
115 //
116 // For now, we just rely on the code that sets routes to do things properly.
117 break;
118 default:
119 throw new IllegalArgumentException("Unknown route type " + type);
120 }
121
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700122 if (destination == null) {
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700123 if (gateway != null) {
124 if (gateway instanceof Inet4Address) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900125 destination = new IpPrefix(Inet4Address.ANY, 0);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700126 } else {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900127 destination = new IpPrefix(Inet6Address.ANY, 0);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700128 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700129 } else {
130 // no destination, no gateway. invalid.
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800131 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
132 destination);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700133 }
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700134 }
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900135 // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
136 // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
137 // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
Kazuhiro Ondo8c0b5282011-05-11 14:55:19 -0500138 if (gateway == null) {
139 if (destination.getAddress() instanceof Inet4Address) {
140 gateway = Inet4Address.ANY;
141 } else {
142 gateway = Inet6Address.ANY;
143 }
144 }
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700145 mHasGateway = (!gateway.isAnyLocalAddress());
146
Robert Greenwalt386aba82014-05-18 23:33:07 -0700147 if ((destination.getAddress() instanceof Inet4Address &&
148 (gateway instanceof Inet4Address == false)) ||
149 (destination.getAddress() instanceof Inet6Address &&
150 (gateway instanceof Inet6Address == false))) {
151 throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
152 }
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900153 mDestination = destination; // IpPrefix objects are immutable.
154 mGateway = gateway; // InetAddress objects are immutable.
155 mInterface = iface; // Strings are immutable.
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900156 mType = type;
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700157 mIsHost = isHost();
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700158 }
159
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700160 /**
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900161 * @hide
162 */
163 public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
164 this(destination, gateway, iface, RTN_UNICAST);
165 }
166
167 /**
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900168 * @hide
169 */
170 public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
171 this(destination == null ? null :
172 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
173 gateway, iface);
174 }
175
176 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700177 * Constructs a {@code RouteInfo} object.
178 *
179 * If destination is null, then gateway must be specified and the
180 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
181 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
182 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
183 * <p>
184 * Destination and gateway may not both be null.
185 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700186 * @param destination the destination address and prefix in an {@link IpPrefix}
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700187 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700188 *
189 * @hide
190 */
191 public RouteInfo(IpPrefix destination, InetAddress gateway) {
192 this(destination, gateway, null);
193 }
194
195 /**
196 * @hide
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900197 *
198 * TODO: Remove this.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700199 */
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800200 public RouteInfo(LinkAddress destination, InetAddress gateway) {
201 this(destination, gateway, null);
202 }
203
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700204 /**
205 * Constructs a default {@code RouteInfo} object.
206 *
207 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700208 *
209 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700210 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700211 public RouteInfo(InetAddress gateway) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900212 this((IpPrefix) null, gateway, null);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700213 }
214
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700215 /**
216 * Constructs a {@code RouteInfo} object representing a direct connected subnet.
217 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700218 * @param destination the {@link IpPrefix} describing the address and prefix
Robert Greenwalt386aba82014-05-18 23:33:07 -0700219 * length of the subnet.
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700220 *
221 * @hide
222 */
223 public RouteInfo(IpPrefix destination) {
224 this(destination, null, null);
225 }
226
227 /**
228 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700229 */
Robert Greenwalt386aba82014-05-18 23:33:07 -0700230 public RouteInfo(LinkAddress destination) {
231 this(destination, null, null);
Robert Greenwalt4717c262012-10-31 14:32:53 -0700232 }
233
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700234 /**
235 * @hide
236 */
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900237 public RouteInfo(IpPrefix destination, int type) {
238 this(destination, null, null, type);
239 }
240
241 /**
242 * @hide
243 */
Lorenzo Colittie1671352013-03-08 12:30:44 -0800244 public static RouteInfo makeHostRoute(InetAddress host, String iface) {
245 return makeHostRoute(host, null, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700246 }
247
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700248 /**
249 * @hide
250 */
Lorenzo Colittie1671352013-03-08 12:30:44 -0800251 public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700252 if (host == null) return null;
253
254 if (host instanceof Inet4Address) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900255 return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700256 } else {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900257 return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700258 }
259 }
260
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700261 private boolean isHost() {
Lorenzo Colittifdadc4e2013-03-27 13:07:18 +0900262 return (mDestination.getAddress() instanceof Inet4Address &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900263 mDestination.getPrefixLength() == 32) ||
Lorenzo Colittifdadc4e2013-03-27 13:07:18 +0900264 (mDestination.getAddress() instanceof Inet6Address &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900265 mDestination.getPrefixLength() == 128);
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700266 }
267
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700268 /**
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700269 * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700270 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700271 * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700272 */
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700273 public IpPrefix getDestination() {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900274 return mDestination;
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700275 }
276
277 /**
278 * TODO: Convert callers to use IpPrefix and then remove.
279 * @hide
280 */
281 public LinkAddress getDestinationLinkAddress() {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900282 return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700283 }
284
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700285 /**
286 * Retrieves the gateway or next hop {@link InetAddress} for this route.
287 *
Robert Greenwalt386aba82014-05-18 23:33:07 -0700288 * @return {@link InetAddress} specifying the gateway or next hop. This may be
Robert Greenwalte595b972014-06-12 16:24:38 -0700289 * {@code null} for a directly-connected route."
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700290 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700291 public InetAddress getGateway() {
292 return mGateway;
293 }
294
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700295 /**
Robert Greenwalt386aba82014-05-18 23:33:07 -0700296 * Retrieves the interface used for this route if specified, else {@code null}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700297 *
298 * @return The name of the interface used for this route.
299 */
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800300 public String getInterface() {
301 return mInterface;
302 }
303
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700304 /**
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900305 * Retrieves the type of this route.
306 *
307 * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
308 *
309 * @hide
310 */
311 public int getType() {
312 return mType;
313 }
314
315 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700316 * Indicates if this route is a default route (ie, has no destination specified).
317 *
Robert Greenwalt386aba82014-05-18 23:33:07 -0700318 * @return {@code true} if the destination has a prefix length of 0.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700319 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700320 public boolean isDefaultRoute() {
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900321 return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900322 }
323
324 /**
325 * Indicates if this route is an IPv4 default route.
326 * @hide
327 */
328 public boolean isIPv4Default() {
329 return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
330 }
331
332 /**
333 * Indicates if this route is an IPv6 default route.
334 * @hide
335 */
336 public boolean isIPv6Default() {
337 return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700338 }
339
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700340 /**
341 * Indicates if this route is a host route (ie, matches only a single host address).
342 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700343 * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
344 * respectively.
Robert Greenwalt386aba82014-05-18 23:33:07 -0700345 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700346 */
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700347 public boolean isHostRoute() {
348 return mIsHost;
349 }
350
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700351 /**
352 * Indicates if this route has a next hop ({@code true}) or is directly-connected
353 * ({@code false}).
354 *
355 * @return {@code true} if a gateway is specified
Robert Greenwalt386aba82014-05-18 23:33:07 -0700356 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700357 */
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700358 public boolean hasGateway() {
359 return mHasGateway;
360 }
361
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700362 /**
Robert Greenwalt386aba82014-05-18 23:33:07 -0700363 * Determines whether the destination and prefix of this route includes the specified
364 * address.
365 *
366 * @param destination A {@link InetAddress} to test to see if it would match this route.
367 * @return {@code true} if the destination and prefix length cover the given address.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700368 */
Robert Greenwalt386aba82014-05-18 23:33:07 -0700369 public boolean matches(InetAddress destination) {
Erik Klineacc8c092015-04-13 15:33:34 +0900370 return mDestination.contains(destination);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700371 }
372
373 /**
374 * Find the route from a Collection of routes that best matches a given address.
375 * May return null if no routes are applicable.
376 * @param routes a Collection of RouteInfos to chose from
377 * @param dest the InetAddress your trying to get to
378 * @return the RouteInfo from the Collection that best fits the given address
379 *
380 * @hide
381 */
382 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
383 if ((routes == null) || (dest == null)) return null;
384
385 RouteInfo bestRoute = null;
386 // pick a longest prefix match under same address type
387 for (RouteInfo route : routes) {
388 if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
389 if ((bestRoute != null) &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900390 (bestRoute.mDestination.getPrefixLength() >=
391 route.mDestination.getPrefixLength())) {
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700392 continue;
393 }
394 if (route.matches(dest)) bestRoute = route;
395 }
396 }
397 return bestRoute;
398 }
399
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700400 /**
401 * Returns a human-readable description of this object.
402 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700403 public String toString() {
404 String val = "";
405 if (mDestination != null) val = mDestination.toString();
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900406 if (mType == RTN_UNREACHABLE) {
407 val += " unreachable";
408 } else if (mType == RTN_THROW) {
409 val += " throw";
410 } else {
411 val += " ->";
412 if (mGateway != null) val += " " + mGateway.getHostAddress();
413 if (mInterface != null) val += " " + mInterface;
414 if (mType != RTN_UNICAST) {
415 val += " unknown type " + mType;
416 }
417 }
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700418 return val;
419 }
420
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700421 /**
422 * Compares this RouteInfo object against the specified object and indicates if they are equal.
423 * @return {@code true} if the objects are equal, {@code false} otherwise.
424 */
Wink Savillebe2b0582011-05-18 15:59:04 -0700425 public boolean equals(Object obj) {
426 if (this == obj) return true;
427
428 if (!(obj instanceof RouteInfo)) return false;
429
430 RouteInfo target = (RouteInfo) obj;
431
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900432 return Objects.equals(mDestination, target.getDestination()) &&
Robert Greenwalt386aba82014-05-18 23:33:07 -0700433 Objects.equals(mGateway, target.getGateway()) &&
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900434 Objects.equals(mInterface, target.getInterface()) &&
435 mType == target.getType();
Wink Savillebe2b0582011-05-18 15:59:04 -0700436 }
437
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700438 /**
439 * Returns a hashcode for this <code>RouteInfo</code> object.
440 */
Wink Savillebe2b0582011-05-18 15:59:04 -0700441 public int hashCode() {
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900442 return (mDestination.hashCode() * 41)
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700443 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900444 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
445 + (mType * 71);
Wink Savillebe2b0582011-05-18 15:59:04 -0700446 }
447
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700448 /**
449 * Implement the Parcelable interface
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700450 */
451 public int describeContents() {
452 return 0;
453 }
454
455 /**
456 * Implement the Parcelable interface
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700457 */
458 public void writeToParcel(Parcel dest, int flags) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900459 dest.writeParcelable(mDestination, flags);
460 byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
461 dest.writeByteArray(gatewayBytes);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700462 dest.writeString(mInterface);
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900463 dest.writeInt(mType);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700464 }
465
466 /**
467 * Implement the Parcelable interface.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700468 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700469 public static final Creator<RouteInfo> CREATOR =
470 new Creator<RouteInfo>() {
471 public RouteInfo createFromParcel(Parcel in) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900472 IpPrefix dest = in.readParcelable(null);
473
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700474 InetAddress gateway = null;
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900475 byte[] addr = in.createByteArray();
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900476 try {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900477 gateway = InetAddress.getByAddress(addr);
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900478 } catch (UnknownHostException e) {}
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700479
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800480 String iface = in.readString();
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900481 int type = in.readInt();
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800482
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900483 return new RouteInfo(dest, gateway, iface, type);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700484 }
485
486 public RouteInfo[] newArray(int size) {
487 return new RouteInfo[size];
488 }
489 };
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700490}