blob: e550f85e6b9afae2ea6bcd69f2f3e8ec1f590df2 [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
paulhu819e0af2019-03-27 22:26:37 +080019import android.annotation.IntDef;
20import android.annotation.NonNull;
paulhud9736de2019-03-08 16:35:20 +080021import android.annotation.Nullable;
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090022import android.annotation.SystemApi;
23import android.annotation.TestApi;
Artur Satayev26958002019-12-10 17:47:52 +000024import android.compat.annotation.UnsupportedAppUsage;
Aaron Huang94df39a2019-12-17 00:33:18 +080025import android.net.util.NetUtils;
Mathew Inwood55418ea2018-12-20 15:30:45 +000026import android.os.Build;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070027import android.os.Parcel;
28import android.os.Parcelable;
Treehugger Robot5dfba4b2020-03-24 06:53:37 +000029import android.util.Pair;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070030
paulhu819e0af2019-03-27 22:26:37 +080031import java.lang.annotation.Retention;
32import java.lang.annotation.RetentionPolicy;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070033import java.net.Inet4Address;
34import java.net.Inet6Address;
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090035import java.net.InetAddress;
36import java.net.UnknownHostException;
Robert Greenwaltf43396c2011-05-06 17:10:53 -070037import java.util.Collection;
Robert Greenwalt386aba82014-05-18 23:33:07 -070038import java.util.Objects;
Robert Greenwaltf43396c2011-05-06 17:10:53 -070039
Robert Greenwaltaa70f102011-04-28 14:28:50 -070040/**
Robert Greenwalt386aba82014-05-18 23:33:07 -070041 * Represents a network route.
Robert Greenwalt4095bd52014-05-18 12:05:05 -070042 * <p>
43 * This is used both to describe static network configuration and live network
Robert Greenwalt386aba82014-05-18 23:33:07 -070044 * configuration information.
Robert Greenwaltaa70f102011-04-28 14:28:50 -070045 *
Robert Greenwalt386aba82014-05-18 23:33:07 -070046 * A route contains three pieces of information:
Robert Greenwalt4095bd52014-05-18 12:05:05 -070047 * <ul>
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070048 * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route.
49 * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6)
Robert Greenwalt386aba82014-05-18 23:33:07 -070050 * implied by the gateway IP address.
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -070051 * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
Robert Greenwalt386aba82014-05-18 23:33:07 -070052 * indicates a directly-connected route.
53 * <li>an interface (which may be unspecified).
Robert Greenwalt4095bd52014-05-18 12:05:05 -070054 * </ul>
Robert Greenwalt386aba82014-05-18 23:33:07 -070055 * Either the destination or the gateway may be {@code null}, but not both. If the
56 * destination and gateway are both specified, they must be of the same address family
57 * (IPv4 or IPv6).
Robert Greenwaltaa70f102011-04-28 14:28:50 -070058 */
Robert Greenwalte595b972014-06-12 16:24:38 -070059public final class RouteInfo implements Parcelable {
paulhu819e0af2019-03-27 22:26:37 +080060 /** @hide */
61 @IntDef(value = {
62 RTN_UNICAST,
63 RTN_UNREACHABLE,
64 RTN_THROW,
65 })
66 @Retention(RetentionPolicy.SOURCE)
67 public @interface RouteType {}
68
Robert Greenwaltaa70f102011-04-28 14:28:50 -070069 /**
70 * The IP destination address for this route.
71 */
paulhu819e0af2019-03-27 22:26:37 +080072 @NonNull
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +090073 private final IpPrefix mDestination;
Robert Greenwaltaa70f102011-04-28 14:28:50 -070074
75 /**
76 * The gateway address for this route.
77 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010078 @UnsupportedAppUsage
paulhu819e0af2019-03-27 22:26:37 +080079 @Nullable
Robert Greenwaltaa70f102011-04-28 14:28:50 -070080 private final InetAddress mGateway;
81
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080082 /**
83 * The interface for this route.
84 */
paulhu819e0af2019-03-27 22:26:37 +080085 @Nullable
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -080086 private final String mInterface;
87
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090088
89 /** Unicast route. @hide */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090090 @SystemApi
91 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090092 public static final int RTN_UNICAST = 1;
93
94 /** Unreachable route. @hide */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +090095 @SystemApi
96 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +090097 public static final int RTN_UNREACHABLE = 7;
98
99 /** Throw route. @hide */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +0900100 @SystemApi
101 @TestApi
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900102 public static final int RTN_THROW = 9;
103
104 /**
105 * The type of this route; one of the RTN_xxx constants above.
106 */
107 private final int mType;
108
Sarah Chin77a7ea62020-01-16 11:19:52 -0800109 /**
110 * The maximum transmission unit size for this route.
111 */
112 private final int mMtu;
113
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900114 // Derived data members.
115 // TODO: remove these.
Mathew Inwood55418ea2018-12-20 15:30:45 +0000116 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700117 private final boolean mIsHost;
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700118 private final boolean mHasGateway;
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700119
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800120 /**
121 * Constructs a RouteInfo object.
122 *
Lorenzo Colitti574b00a2013-03-12 04:30:47 +0900123 * If destination is null, then gateway must be specified and the
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800124 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700125 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
Lorenzo Colitti574b00a2013-03-12 04:30:47 +0900126 * route <code>::/0</code> if gateway is an instance of
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800127 * {@link Inet6Address}.
Robert Greenwalt386aba82014-05-18 23:33:07 -0700128 * <p>
Lorenzo Colitti574b00a2013-03-12 04:30:47 +0900129 * destination and gateway may not both be null.
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800130 *
131 * @param destination the destination prefix
132 * @param gateway the IP address to route packets through
133 * @param iface the interface name to send packets on
paulhu819e0af2019-03-27 22:26:37 +0800134 * @param type the type of this route
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700135 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700136 * @hide
137 */
Remi NGUYEN VAN39fbb922019-01-24 00:55:43 +0900138 @SystemApi
139 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800140 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
paulhu819e0af2019-03-27 22:26:37 +0800141 @Nullable String iface, @RouteType int type) {
Sarah Chin77a7ea62020-01-16 11:19:52 -0800142 this(destination, gateway, iface, type, 0);
143 }
144
145 /**
146 * Constructs a RouteInfo object.
147 *
148 * If destination is null, then gateway must be specified and the
149 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
150 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
151 * route <code>::/0</code> if gateway is an instance of
152 * {@link Inet6Address}.
153 * <p>
154 * destination and gateway may not both be null.
155 *
156 * @param destination the destination prefix
157 * @param gateway the IP address to route packets through
158 * @param iface the interface name to send packets on
159 * @param type the type of this route
160 * @param mtu the maximum transmission unit size for this route
161 *
162 * @hide
163 */
164 @SystemApi
165 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
166 @Nullable String iface, @RouteType int type, int mtu) {
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900167 switch (type) {
168 case RTN_UNICAST:
169 case RTN_UNREACHABLE:
170 case RTN_THROW:
171 // TODO: It would be nice to ensure that route types that don't have nexthops or
172 // interfaces, such as unreachable or throw, can't be created if an interface or
173 // a gateway is specified. This is a bit too complicated to do at the moment
174 // because:
175 //
176 // - LinkProperties sets the interface on routes added to it, and modifies the
177 // interfaces of all the routes when its interface name changes.
178 // - Even when the gateway is null, we store a non-null gateway here.
179 //
180 // For now, we just rely on the code that sets routes to do things properly.
181 break;
182 default:
183 throw new IllegalArgumentException("Unknown route type " + type);
184 }
185
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700186 if (destination == null) {
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700187 if (gateway != null) {
188 if (gateway instanceof Inet4Address) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900189 destination = new IpPrefix(Inet4Address.ANY, 0);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700190 } else {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900191 destination = new IpPrefix(Inet6Address.ANY, 0);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700192 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700193 } else {
194 // no destination, no gateway. invalid.
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800195 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
Sarah Chin77a7ea62020-01-16 11:19:52 -0800196 destination);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700197 }
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700198 }
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900199 // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
200 // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
201 // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
Kazuhiro Ondo8c0b5282011-05-11 14:55:19 -0500202 if (gateway == null) {
203 if (destination.getAddress() instanceof Inet4Address) {
204 gateway = Inet4Address.ANY;
205 } else {
206 gateway = Inet6Address.ANY;
207 }
208 }
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700209 mHasGateway = (!gateway.isAnyLocalAddress());
210
Sarah Chin77a7ea62020-01-16 11:19:52 -0800211 if ((destination.getAddress() instanceof Inet4Address
212 && !(gateway instanceof Inet4Address))
213 || (destination.getAddress() instanceof Inet6Address
214 && !(gateway instanceof Inet6Address))) {
Robert Greenwalt386aba82014-05-18 23:33:07 -0700215 throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
216 }
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900217 mDestination = destination; // IpPrefix objects are immutable.
218 mGateway = gateway; // InetAddress objects are immutable.
219 mInterface = iface; // Strings are immutable.
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900220 mType = type;
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700221 mIsHost = isHost();
Sarah Chin77a7ea62020-01-16 11:19:52 -0800222 mMtu = mtu;
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700223 }
224
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700225 /**
paulhu819e0af2019-03-27 22:26:37 +0800226 * Constructs a {@code RouteInfo} object.
227 *
228 * If destination is null, then gateway must be specified and the
229 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
230 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
231 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
232 * <p>
233 * Destination and gateway may not both be null.
234 *
235 * @param destination the destination address and prefix in an {@link IpPrefix}
236 * @param gateway the {@link InetAddress} to route packets through
237 * @param iface the interface name to send packets on
238 *
239 * @hide
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900240 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100241 @UnsupportedAppUsage
paulhu819e0af2019-03-27 22:26:37 +0800242 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
243 @Nullable String iface) {
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900244 this(destination, gateway, iface, RTN_UNICAST);
245 }
246
247 /**
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900248 * @hide
249 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100250 @UnsupportedAppUsage
paulhu819e0af2019-03-27 22:26:37 +0800251 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway,
252 @Nullable String iface) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900253 this(destination == null ? null :
254 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
255 gateway, iface);
256 }
257
258 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700259 * Constructs a {@code RouteInfo} object.
260 *
261 * If destination is null, then gateway must be specified and the
262 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
263 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
264 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
265 * <p>
266 * Destination and gateway may not both be null.
267 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700268 * @param destination the destination address and prefix in an {@link IpPrefix}
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700269 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700270 *
271 * @hide
272 */
paulhu819e0af2019-03-27 22:26:37 +0800273 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) {
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700274 this(destination, gateway, null);
275 }
276
277 /**
278 * @hide
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900279 *
280 * TODO: Remove this.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700281 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100282 @UnsupportedAppUsage
paulhu819e0af2019-03-27 22:26:37 +0800283 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) {
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800284 this(destination, gateway, null);
285 }
286
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700287 /**
288 * Constructs a default {@code RouteInfo} object.
289 *
290 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700291 *
292 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700293 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100294 @UnsupportedAppUsage
paulhu819e0af2019-03-27 22:26:37 +0800295 public RouteInfo(@NonNull InetAddress gateway) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900296 this((IpPrefix) null, gateway, null);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700297 }
298
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700299 /**
300 * Constructs a {@code RouteInfo} object representing a direct connected subnet.
301 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700302 * @param destination the {@link IpPrefix} describing the address and prefix
Robert Greenwalt386aba82014-05-18 23:33:07 -0700303 * length of the subnet.
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700304 *
305 * @hide
306 */
paulhu819e0af2019-03-27 22:26:37 +0800307 public RouteInfo(@NonNull IpPrefix destination) {
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700308 this(destination, null, null);
309 }
310
311 /**
312 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700313 */
paulhu819e0af2019-03-27 22:26:37 +0800314 public RouteInfo(@NonNull LinkAddress destination) {
Robert Greenwalt386aba82014-05-18 23:33:07 -0700315 this(destination, null, null);
Robert Greenwalt4717c262012-10-31 14:32:53 -0700316 }
317
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700318 /**
319 * @hide
320 */
paulhu819e0af2019-03-27 22:26:37 +0800321 public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) {
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900322 this(destination, null, null, type);
323 }
324
325 /**
326 * @hide
327 */
paulhu819e0af2019-03-27 22:26:37 +0800328 public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) {
Lorenzo Colittie1671352013-03-08 12:30:44 -0800329 return makeHostRoute(host, null, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700330 }
331
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700332 /**
333 * @hide
334 */
paulhu819e0af2019-03-27 22:26:37 +0800335 public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway,
336 @Nullable String iface) {
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700337 if (host == null) return null;
338
339 if (host instanceof Inet4Address) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900340 return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700341 } else {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900342 return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700343 }
344 }
345
Mathew Inwood55418ea2018-12-20 15:30:45 +0000346 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700347 private boolean isHost() {
Lorenzo Colittifdadc4e2013-03-27 13:07:18 +0900348 return (mDestination.getAddress() instanceof Inet4Address &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900349 mDestination.getPrefixLength() == 32) ||
Lorenzo Colittifdadc4e2013-03-27 13:07:18 +0900350 (mDestination.getAddress() instanceof Inet6Address &&
Lorenzo Colitti7dc78cf2014-06-09 22:58:46 +0900351 mDestination.getPrefixLength() == 128);
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700352 }
353
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700354 /**
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700355 * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700356 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700357 * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700358 */
paulhu819e0af2019-03-27 22:26:37 +0800359 @NonNull
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700360 public IpPrefix getDestination() {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900361 return mDestination;
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700362 }
363
364 /**
365 * TODO: Convert callers to use IpPrefix and then remove.
366 * @hide
367 */
paulhu819e0af2019-03-27 22:26:37 +0800368 @NonNull
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700369 public LinkAddress getDestinationLinkAddress() {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900370 return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700371 }
372
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700373 /**
374 * Retrieves the gateway or next hop {@link InetAddress} for this route.
375 *
Robert Greenwalt386aba82014-05-18 23:33:07 -0700376 * @return {@link InetAddress} specifying the gateway or next hop. This may be
Robert Greenwalte595b972014-06-12 16:24:38 -0700377 * {@code null} for a directly-connected route."
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700378 */
paulhu819e0af2019-03-27 22:26:37 +0800379 @Nullable
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700380 public InetAddress getGateway() {
381 return mGateway;
382 }
383
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700384 /**
Robert Greenwalt386aba82014-05-18 23:33:07 -0700385 * Retrieves the interface used for this route if specified, else {@code null}.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700386 *
387 * @return The name of the interface used for this route.
388 */
paulhu819e0af2019-03-27 22:26:37 +0800389 @Nullable
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800390 public String getInterface() {
391 return mInterface;
392 }
393
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700394 /**
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900395 * Retrieves the type of this route.
396 *
397 * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
398 *
399 * @hide
400 */
Remi NGUYEN VAN31f1d0c2019-01-20 12:52:43 +0900401 @TestApi
402 @SystemApi
paulhu819e0af2019-03-27 22:26:37 +0800403 @RouteType
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900404 public int getType() {
405 return mType;
406 }
407
408 /**
Sarah Chin77a7ea62020-01-16 11:19:52 -0800409 * Retrieves the MTU size for this route.
410 *
411 * @return The MTU size, or 0 if it has not been set.
412 * @hide
413 */
414 @SystemApi
415 public int getMtu() {
416 return mMtu;
417 }
418
419 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700420 * Indicates if this route is a default route (ie, has no destination specified).
421 *
Robert Greenwalt386aba82014-05-18 23:33:07 -0700422 * @return {@code true} if the destination has a prefix length of 0.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700423 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700424 public boolean isDefaultRoute() {
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900425 return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900426 }
427
428 /**
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +0000429 * Indicates if this route is an unreachable default route.
430 *
431 * @return {@code true} if it's an unreachable route with prefix length of 0.
432 * @hide
433 */
434 private boolean isUnreachableDefaultRoute() {
435 return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0;
436 }
437
438 /**
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900439 * Indicates if this route is an IPv4 default route.
440 * @hide
441 */
442 public boolean isIPv4Default() {
443 return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
444 }
445
446 /**
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +0000447 * Indicates if this route is an IPv4 unreachable default route.
448 * @hide
449 */
450 public boolean isIPv4UnreachableDefault() {
451 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
452 }
453
454 /**
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900455 * Indicates if this route is an IPv6 default route.
456 * @hide
457 */
458 public boolean isIPv6Default() {
459 return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700460 }
461
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700462 /**
Lorenzo Colitti5ccee0c2020-04-02 04:50:41 +0000463 * Indicates if this route is an IPv6 unreachable default route.
464 * @hide
465 */
466 public boolean isIPv6UnreachableDefault() {
467 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
468 }
469
470 /**
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700471 * Indicates if this route is a host route (ie, matches only a single host address).
472 *
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700473 * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
474 * respectively.
Robert Greenwalt386aba82014-05-18 23:33:07 -0700475 * @hide
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700476 */
Robert Greenwalt0a46db52011-07-14 14:28:05 -0700477 public boolean isHostRoute() {
478 return mIsHost;
479 }
480
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700481 /**
482 * Indicates if this route has a next hop ({@code true}) or is directly-connected
483 * ({@code false}).
484 *
485 * @return {@code true} if a gateway is specified
486 */
Robert Greenwaltca441ee2013-04-11 13:48:16 -0700487 public boolean hasGateway() {
488 return mHasGateway;
489 }
490
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700491 /**
Robert Greenwalt386aba82014-05-18 23:33:07 -0700492 * Determines whether the destination and prefix of this route includes the specified
493 * address.
494 *
495 * @param destination A {@link InetAddress} to test to see if it would match this route.
496 * @return {@code true} if the destination and prefix length cover the given address.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700497 */
Robert Greenwalt386aba82014-05-18 23:33:07 -0700498 public boolean matches(InetAddress destination) {
Erik Klineacc8c092015-04-13 15:33:34 +0900499 return mDestination.contains(destination);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700500 }
501
502 /**
503 * Find the route from a Collection of routes that best matches a given address.
504 * May return null if no routes are applicable.
505 * @param routes a Collection of RouteInfos to chose from
506 * @param dest the InetAddress your trying to get to
507 * @return the RouteInfo from the Collection that best fits the given address
508 *
509 * @hide
510 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100511 @UnsupportedAppUsage
paulhu819e0af2019-03-27 22:26:37 +0800512 @Nullable
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700513 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
Aaron Huang94df39a2019-12-17 00:33:18 +0800514 return NetUtils.selectBestRoute(routes, dest);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700515 }
516
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700517 /**
518 * Returns a human-readable description of this object.
519 */
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700520 public String toString() {
521 String val = "";
522 if (mDestination != null) val = mDestination.toString();
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900523 if (mType == RTN_UNREACHABLE) {
524 val += " unreachable";
525 } else if (mType == RTN_THROW) {
526 val += " throw";
527 } else {
528 val += " ->";
529 if (mGateway != null) val += " " + mGateway.getHostAddress();
530 if (mInterface != null) val += " " + mInterface;
531 if (mType != RTN_UNICAST) {
532 val += " unknown type " + mType;
533 }
534 }
Sarah Chin77a7ea62020-01-16 11:19:52 -0800535 val += " mtu " + mMtu;
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700536 return val;
537 }
538
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700539 /**
540 * Compares this RouteInfo object against the specified object and indicates if they are equal.
541 * @return {@code true} if the objects are equal, {@code false} otherwise.
542 */
Wink Savillebe2b0582011-05-18 15:59:04 -0700543 public boolean equals(Object obj) {
544 if (this == obj) return true;
545
546 if (!(obj instanceof RouteInfo)) return false;
547
548 RouteInfo target = (RouteInfo) obj;
549
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900550 return Objects.equals(mDestination, target.getDestination()) &&
Robert Greenwalt386aba82014-05-18 23:33:07 -0700551 Objects.equals(mGateway, target.getGateway()) &&
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900552 Objects.equals(mInterface, target.getInterface()) &&
Sarah Chin77a7ea62020-01-16 11:19:52 -0800553 mType == target.getType() && mMtu == target.getMtu();
Wink Savillebe2b0582011-05-18 15:59:04 -0700554 }
555
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700556 /**
Treehugger Robot5dfba4b2020-03-24 06:53:37 +0000557 * A helper class that contains the destination and the gateway in a {@code RouteInfo},
558 * used by {@link ConnectivityService#updateRoutes} or
559 * {@link LinkProperties#addRoute} to calculate the list to be updated.
Lorenzo Colittid86407b2020-03-18 07:52:25 +0000560 *
561 * @hide
562 */
Treehugger Robot5dfba4b2020-03-24 06:53:37 +0000563 public static class RouteKey extends Pair<IpPrefix, InetAddress> {
564 RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway) {
565 super(destination, gateway);
Lorenzo Colittid86407b2020-03-18 07:52:25 +0000566 }
Treehugger Robot5dfba4b2020-03-24 06:53:37 +0000567 }
568
569 /**
570 * Get {@code RouteKey} of this {@code RouteInfo}.
571 * @return a {@code RouteKey} object.
572 *
573 * @hide
574 */
575 @NonNull
576 public RouteKey getRouteKey() {
577 return new RouteKey(mDestination, mGateway);
Lorenzo Colittid86407b2020-03-18 07:52:25 +0000578 }
579
580 /**
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700581 * Returns a hashcode for this <code>RouteInfo</code> object.
582 */
Wink Savillebe2b0582011-05-18 15:59:04 -0700583 public int hashCode() {
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900584 return (mDestination.hashCode() * 41)
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700585 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900586 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
Sarah Chin77a7ea62020-01-16 11:19:52 -0800587 + (mType * 71) + (mMtu * 89);
Wink Savillebe2b0582011-05-18 15:59:04 -0700588 }
589
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700590 /**
591 * Implement the Parcelable interface
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700592 */
593 public int describeContents() {
594 return 0;
595 }
596
597 /**
598 * Implement the Parcelable interface
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700599 */
600 public void writeToParcel(Parcel dest, int flags) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900601 dest.writeParcelable(mDestination, flags);
602 byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
603 dest.writeByteArray(gatewayBytes);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700604 dest.writeString(mInterface);
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900605 dest.writeInt(mType);
Sarah Chin77a7ea62020-01-16 11:19:52 -0800606 dest.writeInt(mMtu);
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700607 }
608
609 /**
610 * Implement the Parcelable interface.
Robert Greenwalt4095bd52014-05-18 12:05:05 -0700611 */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700612 public static final @android.annotation.NonNull Creator<RouteInfo> CREATOR =
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700613 new Creator<RouteInfo>() {
614 public RouteInfo createFromParcel(Parcel in) {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900615 IpPrefix dest = in.readParcelable(null);
616
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700617 InetAddress gateway = null;
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900618 byte[] addr = in.createByteArray();
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900619 try {
Lorenzo Colitti1806b1f2014-08-12 12:37:50 +0900620 gateway = InetAddress.getByAddress(addr);
Lorenzo Colitti64c43b12014-06-23 21:27:53 +0900621 } catch (UnknownHostException e) {}
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700622
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800623 String iface = in.readString();
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900624 int type = in.readInt();
Sarah Chin77a7ea62020-01-16 11:19:52 -0800625 int mtu = in.readInt();
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800626
Sarah Chin77a7ea62020-01-16 11:19:52 -0800627 return new RouteInfo(dest, gateway, iface, type, mtu);
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700628 }
629
630 public RouteInfo[] newArray(int size) {
631 return new RouteInfo[size];
632 }
633 };
Robert Greenwaltaa70f102011-04-28 14:28:50 -0700634}