blob: fad3144a4b80a87076550f2e6631d432e07a8524 [file] [log] [blame]
Robert Greenwalt5a901292011-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
paulhu895a7412019-03-27 22:26:37 +080019import android.annotation.IntDef;
20import android.annotation.NonNull;
paulhucbbc3db2019-03-08 16:35:20 +080021import android.annotation.Nullable;
Remi NGUYEN VAN85b96652019-01-20 12:52:43 +090022import android.annotation.SystemApi;
Artur Satayev9c2add62019-12-10 17:47:52 +000023import android.compat.annotation.UnsupportedAppUsage;
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +000024import android.os.Build;
Robert Greenwalt5a901292011-04-28 14:28:50 -070025import android.os.Parcel;
26import android.os.Parcelable;
27
Chalard Jean79162542020-08-19 16:07:22 +090028import com.android.net.module.util.NetUtils;
paulhub5343312021-03-04 10:53:27 +080029import com.android.net.module.util.NetworkStackConstants;
Chalard Jean79162542020-08-19 16:07:22 +090030
paulhu895a7412019-03-27 22:26:37 +080031import java.lang.annotation.Retention;
32import java.lang.annotation.RetentionPolicy;
Robert Greenwalt5a901292011-04-28 14:28:50 -070033import java.net.Inet4Address;
34import java.net.Inet6Address;
Remi NGUYEN VAN85b96652019-01-20 12:52:43 +090035import java.net.InetAddress;
36import java.net.UnknownHostException;
Robert Greenwaltbd492212011-05-06 17:10:53 -070037import java.util.Collection;
Robert Greenwalt223a6bd2014-05-18 23:33:07 -070038import java.util.Objects;
Robert Greenwaltbd492212011-05-06 17:10:53 -070039
Robert Greenwalt5a901292011-04-28 14:28:50 -070040/**
Robert Greenwalt223a6bd2014-05-18 23:33:07 -070041 * Represents a network route.
Robert Greenwalt1aacd722014-05-18 12:05:05 -070042 * <p>
43 * This is used both to describe static network configuration and live network
Robert Greenwalt223a6bd2014-05-18 23:33:07 -070044 * configuration information.
Robert Greenwalt5a901292011-04-28 14:28:50 -070045 *
Robert Greenwalt223a6bd2014-05-18 23:33:07 -070046 * A route contains three pieces of information:
Robert Greenwalt1aacd722014-05-18 12:05:05 -070047 * <ul>
Sreeram Ramachandran887d7b12014-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 Greenwalt223a6bd2014-05-18 23:33:07 -070050 * implied by the gateway IP address.
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -070051 * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
Robert Greenwalt223a6bd2014-05-18 23:33:07 -070052 * indicates a directly-connected route.
53 * <li>an interface (which may be unspecified).
Robert Greenwalt1aacd722014-05-18 12:05:05 -070054 * </ul>
Robert Greenwalt223a6bd2014-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 Greenwalt5a901292011-04-28 14:28:50 -070058 */
Robert Greenwaltc4920a52014-06-12 16:24:38 -070059public final class RouteInfo implements Parcelable {
paulhu895a7412019-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 Greenwalt5a901292011-04-28 14:28:50 -070069 /**
70 * The IP destination address for this route.
71 */
paulhu895a7412019-03-27 22:26:37 +080072 @NonNull
Lorenzo Colitti435565d2014-08-12 12:37:50 +090073 private final IpPrefix mDestination;
Robert Greenwalt5a901292011-04-28 14:28:50 -070074
75 /**
76 * The gateway address for this route.
77 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +010078 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +080079 @Nullable
Robert Greenwalt5a901292011-04-28 14:28:50 -070080 private final InetAddress mGateway;
81
Lorenzo Colitti73b97852013-03-08 11:30:39 -080082 /**
83 * The interface for this route.
84 */
paulhu895a7412019-03-27 22:26:37 +080085 @Nullable
Lorenzo Colitti73b97852013-03-08 11:30:39 -080086 private final String mInterface;
87
Lorenzo Colitti21290342014-09-19 01:49:05 +090088
89 /** Unicast route. @hide */
Remi NGUYEN VAN85b96652019-01-20 12:52:43 +090090 @SystemApi
Lorenzo Colitti21290342014-09-19 01:49:05 +090091 public static final int RTN_UNICAST = 1;
92
93 /** Unreachable route. @hide */
Remi NGUYEN VAN85b96652019-01-20 12:52:43 +090094 @SystemApi
Lorenzo Colitti21290342014-09-19 01:49:05 +090095 public static final int RTN_UNREACHABLE = 7;
96
97 /** Throw route. @hide */
Remi NGUYEN VAN85b96652019-01-20 12:52:43 +090098 @SystemApi
Lorenzo Colitti21290342014-09-19 01:49:05 +090099 public static final int RTN_THROW = 9;
100
101 /**
102 * The type of this route; one of the RTN_xxx constants above.
103 */
104 private final int mType;
105
Sarah Chinf75d09f2020-01-16 11:19:52 -0800106 /**
107 * The maximum transmission unit size for this route.
108 */
109 private final int mMtu;
110
Lorenzo Colitti21290342014-09-19 01:49:05 +0900111 // Derived data members.
112 // TODO: remove these.
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +0000113 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700114 private final boolean mIsHost;
Robert Greenwalt59070cf2013-04-11 13:48:16 -0700115 private final boolean mHasGateway;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700116
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800117 /**
118 * Constructs a RouteInfo object.
119 *
Lorenzo Colittifb475942013-03-12 04:30:47 +0900120 * If destination is null, then gateway must be specified and the
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800121 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700122 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
Lorenzo Colittifb475942013-03-12 04:30:47 +0900123 * route <code>::/0</code> if gateway is an instance of
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800124 * {@link Inet6Address}.
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700125 * <p>
Lorenzo Colittifb475942013-03-12 04:30:47 +0900126 * destination and gateway may not both be null.
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800127 *
128 * @param destination the destination prefix
129 * @param gateway the IP address to route packets through
130 * @param iface the interface name to send packets on
paulhu895a7412019-03-27 22:26:37 +0800131 * @param type the type of this route
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700132 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700133 * @hide
134 */
Remi NGUYEN VANdaace812019-01-24 00:55:43 +0900135 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800136 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
paulhu895a7412019-03-27 22:26:37 +0800137 @Nullable String iface, @RouteType int type) {
Sarah Chinf75d09f2020-01-16 11:19:52 -0800138 this(destination, gateway, iface, type, 0);
139 }
140
141 /**
142 * Constructs a RouteInfo object.
143 *
144 * If destination is null, then gateway must be specified and the
145 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
146 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
147 * route <code>::/0</code> if gateway is an instance of
148 * {@link Inet6Address}.
149 * <p>
150 * destination and gateway may not both be null.
151 *
152 * @param destination the destination prefix
153 * @param gateway the IP address to route packets through
154 * @param iface the interface name to send packets on
155 * @param type the type of this route
156 * @param mtu the maximum transmission unit size for this route
157 *
158 * @hide
159 */
160 @SystemApi
161 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
162 @Nullable String iface, @RouteType int type, int mtu) {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900163 switch (type) {
164 case RTN_UNICAST:
165 case RTN_UNREACHABLE:
166 case RTN_THROW:
167 // TODO: It would be nice to ensure that route types that don't have nexthops or
168 // interfaces, such as unreachable or throw, can't be created if an interface or
169 // a gateway is specified. This is a bit too complicated to do at the moment
170 // because:
171 //
172 // - LinkProperties sets the interface on routes added to it, and modifies the
173 // interfaces of all the routes when its interface name changes.
174 // - Even when the gateway is null, we store a non-null gateway here.
175 //
176 // For now, we just rely on the code that sets routes to do things properly.
177 break;
178 default:
179 throw new IllegalArgumentException("Unknown route type " + type);
180 }
181
Robert Greenwalt5a901292011-04-28 14:28:50 -0700182 if (destination == null) {
Robert Greenwalt355205c2011-05-10 15:05:02 -0700183 if (gateway != null) {
184 if (gateway instanceof Inet4Address) {
paulhub5343312021-03-04 10:53:27 +0800185 destination = new IpPrefix(NetworkStackConstants.IPV4_ADDR_ANY, 0);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700186 } else {
paulhub5343312021-03-04 10:53:27 +0800187 destination = new IpPrefix(NetworkStackConstants.IPV6_ADDR_ANY, 0);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700188 }
Robert Greenwalt355205c2011-05-10 15:05:02 -0700189 } else {
190 // no destination, no gateway. invalid.
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800191 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
Sarah Chinf75d09f2020-01-16 11:19:52 -0800192 destination);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700193 }
Robert Greenwalt5a901292011-04-28 14:28:50 -0700194 }
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900195 // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
196 // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
197 // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500198 if (gateway == null) {
199 if (destination.getAddress() instanceof Inet4Address) {
paulhub5343312021-03-04 10:53:27 +0800200 gateway = NetworkStackConstants.IPV4_ADDR_ANY;
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500201 } else {
paulhub5343312021-03-04 10:53:27 +0800202 gateway = NetworkStackConstants.IPV6_ADDR_ANY;
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500203 }
204 }
Robert Greenwalt59070cf2013-04-11 13:48:16 -0700205 mHasGateway = (!gateway.isAnyLocalAddress());
206
Sarah Chinf75d09f2020-01-16 11:19:52 -0800207 if ((destination.getAddress() instanceof Inet4Address
208 && !(gateway instanceof Inet4Address))
209 || (destination.getAddress() instanceof Inet6Address
210 && !(gateway instanceof Inet6Address))) {
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700211 throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
212 }
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900213 mDestination = destination; // IpPrefix objects are immutable.
214 mGateway = gateway; // InetAddress objects are immutable.
215 mInterface = iface; // Strings are immutable.
Lorenzo Colitti21290342014-09-19 01:49:05 +0900216 mType = type;
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700217 mIsHost = isHost();
Sarah Chinf75d09f2020-01-16 11:19:52 -0800218 mMtu = mtu;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700219 }
220
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700221 /**
paulhu895a7412019-03-27 22:26:37 +0800222 * Constructs a {@code RouteInfo} object.
223 *
224 * If destination is null, then gateway must be specified and the
225 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
226 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
227 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
228 * <p>
229 * Destination and gateway may not both be null.
230 *
231 * @param destination the destination address and prefix in an {@link IpPrefix}
232 * @param gateway the {@link InetAddress} to route packets through
233 * @param iface the interface name to send packets on
234 *
235 * @hide
Lorenzo Colitti21290342014-09-19 01:49:05 +0900236 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000237 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu895a7412019-03-27 22:26:37 +0800238 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
239 @Nullable String iface) {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900240 this(destination, gateway, iface, RTN_UNICAST);
241 }
242
243 /**
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900244 * @hide
245 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100246 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +0800247 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway,
248 @Nullable String iface) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900249 this(destination == null ? null :
250 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
251 gateway, iface);
252 }
253
254 /**
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700255 * Constructs a {@code RouteInfo} object.
256 *
257 * If destination is null, then gateway must be specified and the
258 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
259 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
260 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
261 * <p>
262 * Destination and gateway may not both be null.
263 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700264 * @param destination the destination address and prefix in an {@link IpPrefix}
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700265 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700266 *
267 * @hide
268 */
paulhu895a7412019-03-27 22:26:37 +0800269 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) {
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700270 this(destination, gateway, null);
271 }
272
273 /**
274 * @hide
Lorenzo Colitti21290342014-09-19 01:49:05 +0900275 *
276 * TODO: Remove this.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700277 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100278 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +0800279 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) {
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800280 this(destination, gateway, null);
281 }
282
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700283 /**
284 * Constructs a default {@code RouteInfo} object.
285 *
286 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700287 *
288 * @hide
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700289 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100290 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +0800291 public RouteInfo(@NonNull InetAddress gateway) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900292 this((IpPrefix) null, gateway, null);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700293 }
294
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700295 /**
296 * Constructs a {@code RouteInfo} object representing a direct connected subnet.
297 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700298 * @param destination the {@link IpPrefix} describing the address and prefix
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700299 * length of the subnet.
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700300 *
301 * @hide
302 */
paulhu895a7412019-03-27 22:26:37 +0800303 public RouteInfo(@NonNull IpPrefix destination) {
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700304 this(destination, null, null);
305 }
306
307 /**
308 * @hide
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700309 */
paulhu895a7412019-03-27 22:26:37 +0800310 public RouteInfo(@NonNull LinkAddress destination) {
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700311 this(destination, null, null);
Robert Greenwalt462e5702012-10-31 14:32:53 -0700312 }
313
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700314 /**
315 * @hide
316 */
paulhu895a7412019-03-27 22:26:37 +0800317 public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900318 this(destination, null, null, type);
319 }
320
321 /**
322 * @hide
323 */
paulhu895a7412019-03-27 22:26:37 +0800324 public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) {
Lorenzo Colitti7a43b0f2013-03-08 12:30:44 -0800325 return makeHostRoute(host, null, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700326 }
327
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700328 /**
329 * @hide
330 */
paulhu895a7412019-03-27 22:26:37 +0800331 public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway,
332 @Nullable String iface) {
Robert Greenwalt355205c2011-05-10 15:05:02 -0700333 if (host == null) return null;
334
335 if (host instanceof Inet4Address) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900336 return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700337 } else {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900338 return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700339 }
340 }
341
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +0000342 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700343 private boolean isHost() {
Lorenzo Colittiaff54132013-03-27 13:07:18 +0900344 return (mDestination.getAddress() instanceof Inet4Address &&
Lorenzo Colittib0116bf2014-06-09 22:58:46 +0900345 mDestination.getPrefixLength() == 32) ||
Lorenzo Colittiaff54132013-03-27 13:07:18 +0900346 (mDestination.getAddress() instanceof Inet6Address &&
Lorenzo Colittib0116bf2014-06-09 22:58:46 +0900347 mDestination.getPrefixLength() == 128);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700348 }
349
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700350 /**
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700351 * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700352 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700353 * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700354 */
paulhu895a7412019-03-27 22:26:37 +0800355 @NonNull
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700356 public IpPrefix getDestination() {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900357 return mDestination;
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700358 }
359
360 /**
361 * TODO: Convert callers to use IpPrefix and then remove.
362 * @hide
363 */
paulhu895a7412019-03-27 22:26:37 +0800364 @NonNull
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700365 public LinkAddress getDestinationLinkAddress() {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900366 return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
Robert Greenwalt5a901292011-04-28 14:28:50 -0700367 }
368
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700369 /**
370 * Retrieves the gateway or next hop {@link InetAddress} for this route.
371 *
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700372 * @return {@link InetAddress} specifying the gateway or next hop. This may be
Robert Greenwaltc4920a52014-06-12 16:24:38 -0700373 * {@code null} for a directly-connected route."
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700374 */
paulhu895a7412019-03-27 22:26:37 +0800375 @Nullable
Robert Greenwalt5a901292011-04-28 14:28:50 -0700376 public InetAddress getGateway() {
377 return mGateway;
378 }
379
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700380 /**
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700381 * Retrieves the interface used for this route if specified, else {@code null}.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700382 *
383 * @return The name of the interface used for this route.
384 */
paulhu895a7412019-03-27 22:26:37 +0800385 @Nullable
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800386 public String getInterface() {
387 return mInterface;
388 }
389
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700390 /**
Lorenzo Colitti21290342014-09-19 01:49:05 +0900391 * Retrieves the type of this route.
392 *
393 * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
394 *
395 * @hide
396 */
Remi NGUYEN VAN85b96652019-01-20 12:52:43 +0900397 @SystemApi
paulhu895a7412019-03-27 22:26:37 +0800398 @RouteType
Lorenzo Colitti21290342014-09-19 01:49:05 +0900399 public int getType() {
400 return mType;
401 }
402
403 /**
Sarah Chinf75d09f2020-01-16 11:19:52 -0800404 * Retrieves the MTU size for this route.
405 *
406 * @return The MTU size, or 0 if it has not been set.
407 * @hide
408 */
409 @SystemApi
410 public int getMtu() {
411 return mMtu;
412 }
413
414 /**
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700415 * Indicates if this route is a default route (ie, has no destination specified).
416 *
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700417 * @return {@code true} if the destination has a prefix length of 0.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700418 */
Robert Greenwalt5a901292011-04-28 14:28:50 -0700419 public boolean isDefaultRoute() {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900420 return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900421 }
422
423 /**
Rubin Xuab8cf302020-03-30 14:37:05 +0100424 * Indicates if this route is an unreachable default route.
425 *
426 * @return {@code true} if it's an unreachable route with prefix length of 0.
427 * @hide
428 */
429 private boolean isUnreachableDefaultRoute() {
430 return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0;
431 }
432
433 /**
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900434 * Indicates if this route is an IPv4 default route.
435 * @hide
436 */
437 public boolean isIPv4Default() {
438 return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
439 }
440
441 /**
Rubin Xuab8cf302020-03-30 14:37:05 +0100442 * Indicates if this route is an IPv4 unreachable default route.
443 * @hide
444 */
445 public boolean isIPv4UnreachableDefault() {
446 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
447 }
448
449 /**
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900450 * Indicates if this route is an IPv6 default route.
451 * @hide
452 */
453 public boolean isIPv6Default() {
454 return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700455 }
456
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700457 /**
Rubin Xuab8cf302020-03-30 14:37:05 +0100458 * Indicates if this route is an IPv6 unreachable default route.
459 * @hide
460 */
461 public boolean isIPv6UnreachableDefault() {
462 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
463 }
464
465 /**
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700466 * Indicates if this route is a host route (ie, matches only a single host address).
467 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700468 * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
469 * respectively.
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700470 * @hide
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700471 */
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700472 public boolean isHostRoute() {
473 return mIsHost;
474 }
475
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700476 /**
477 * Indicates if this route has a next hop ({@code true}) or is directly-connected
478 * ({@code false}).
479 *
480 * @return {@code true} if a gateway is specified
481 */
Robert Greenwalt59070cf2013-04-11 13:48:16 -0700482 public boolean hasGateway() {
483 return mHasGateway;
484 }
485
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700486 /**
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700487 * Determines whether the destination and prefix of this route includes the specified
488 * address.
489 *
490 * @param destination A {@link InetAddress} to test to see if it would match this route.
491 * @return {@code true} if the destination and prefix length cover the given address.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700492 */
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700493 public boolean matches(InetAddress destination) {
Erik Klineb98afb02015-04-13 15:33:34 +0900494 return mDestination.contains(destination);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700495 }
496
497 /**
498 * Find the route from a Collection of routes that best matches a given address.
499 * May return null if no routes are applicable.
500 * @param routes a Collection of RouteInfos to chose from
501 * @param dest the InetAddress your trying to get to
502 * @return the RouteInfo from the Collection that best fits the given address
503 *
504 * @hide
505 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000506 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu895a7412019-03-27 22:26:37 +0800507 @Nullable
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700508 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
Aaron Huang0e1759b2019-12-17 00:33:18 +0800509 return NetUtils.selectBestRoute(routes, dest);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700510 }
511
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700512 /**
513 * Returns a human-readable description of this object.
514 */
Robert Greenwalt5a901292011-04-28 14:28:50 -0700515 public String toString() {
516 String val = "";
517 if (mDestination != null) val = mDestination.toString();
Lorenzo Colitti21290342014-09-19 01:49:05 +0900518 if (mType == RTN_UNREACHABLE) {
519 val += " unreachable";
520 } else if (mType == RTN_THROW) {
521 val += " throw";
522 } else {
523 val += " ->";
524 if (mGateway != null) val += " " + mGateway.getHostAddress();
525 if (mInterface != null) val += " " + mInterface;
526 if (mType != RTN_UNICAST) {
527 val += " unknown type " + mType;
528 }
529 }
Sarah Chinf75d09f2020-01-16 11:19:52 -0800530 val += " mtu " + mMtu;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700531 return val;
532 }
533
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700534 /**
535 * Compares this RouteInfo object against the specified object and indicates if they are equal.
536 * @return {@code true} if the objects are equal, {@code false} otherwise.
537 */
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -0700538 public boolean equals(@Nullable Object obj) {
Wink Savillef23fb202011-05-18 15:59:04 -0700539 if (this == obj) return true;
540
541 if (!(obj instanceof RouteInfo)) return false;
542
543 RouteInfo target = (RouteInfo) obj;
544
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900545 return Objects.equals(mDestination, target.getDestination()) &&
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700546 Objects.equals(mGateway, target.getGateway()) &&
Lorenzo Colitti21290342014-09-19 01:49:05 +0900547 Objects.equals(mInterface, target.getInterface()) &&
Sarah Chinf75d09f2020-01-16 11:19:52 -0800548 mType == target.getType() && mMtu == target.getMtu();
Wink Savillef23fb202011-05-18 15:59:04 -0700549 }
550
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700551 /**
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100552 * A helper class that contains the destination, the gateway and the interface in a
553 * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or
junyulaia1493a52020-03-23 20:49:43 +0800554 * {@link LinkProperties#addRoute} to calculate the list to be updated.
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100555 * {@code RouteInfo} objects with different interfaces are treated as different routes because
556 * *usually* on Android different interfaces use different routing tables, and moving a route
557 * to a new routing table never constitutes an update, but is always a remove and an add.
Tyler Weare4314862019-12-05 14:55:30 -0800558 *
559 * @hide
560 */
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100561 public static class RouteKey {
562 @NonNull private final IpPrefix mDestination;
563 @Nullable private final InetAddress mGateway;
564 @Nullable private final String mInterface;
565
566 RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway,
567 @Nullable String iface) {
568 mDestination = destination;
569 mGateway = gateway;
570 mInterface = iface;
571 }
572
573 @Override
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -0700574 public boolean equals(@Nullable Object o) {
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100575 if (!(o instanceof RouteKey)) {
576 return false;
577 }
578 RouteKey p = (RouteKey) o;
579 // No need to do anything special for scoped addresses. Inet6Address#equals does not
580 // consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel)
581 // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only
582 // look at RTA_OIF.
583 return Objects.equals(p.mDestination, mDestination)
584 && Objects.equals(p.mGateway, mGateway)
585 && Objects.equals(p.mInterface, mInterface);
586 }
587
588 @Override
589 public int hashCode() {
590 return Objects.hash(mDestination, mGateway, mInterface);
Tyler Weare4314862019-12-05 14:55:30 -0800591 }
junyulaia1493a52020-03-23 20:49:43 +0800592 }
593
594 /**
595 * Get {@code RouteKey} of this {@code RouteInfo}.
596 * @return a {@code RouteKey} object.
597 *
598 * @hide
599 */
600 @NonNull
601 public RouteKey getRouteKey() {
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100602 return new RouteKey(mDestination, mGateway, mInterface);
Tyler Weare4314862019-12-05 14:55:30 -0800603 }
604
605 /**
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700606 * Returns a hashcode for this <code>RouteInfo</code> object.
607 */
Wink Savillef23fb202011-05-18 15:59:04 -0700608 public int hashCode() {
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900609 return (mDestination.hashCode() * 41)
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700610 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
Lorenzo Colitti21290342014-09-19 01:49:05 +0900611 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
Sarah Chinf75d09f2020-01-16 11:19:52 -0800612 + (mType * 71) + (mMtu * 89);
Wink Savillef23fb202011-05-18 15:59:04 -0700613 }
614
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700615 /**
616 * Implement the Parcelable interface
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700617 */
618 public int describeContents() {
619 return 0;
620 }
621
622 /**
623 * Implement the Parcelable interface
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700624 */
625 public void writeToParcel(Parcel dest, int flags) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900626 dest.writeParcelable(mDestination, flags);
627 byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
628 dest.writeByteArray(gatewayBytes);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700629 dest.writeString(mInterface);
Lorenzo Colitti21290342014-09-19 01:49:05 +0900630 dest.writeInt(mType);
Sarah Chinf75d09f2020-01-16 11:19:52 -0800631 dest.writeInt(mMtu);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700632 }
633
634 /**
635 * Implement the Parcelable interface.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700636 */
Jeff Sharkeyf8525282019-02-28 12:06:45 -0700637 public static final @android.annotation.NonNull Creator<RouteInfo> CREATOR =
Robert Greenwalt5a901292011-04-28 14:28:50 -0700638 new Creator<RouteInfo>() {
639 public RouteInfo createFromParcel(Parcel in) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900640 IpPrefix dest = in.readParcelable(null);
641
Robert Greenwalt5a901292011-04-28 14:28:50 -0700642 InetAddress gateway = null;
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900643 byte[] addr = in.createByteArray();
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900644 try {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900645 gateway = InetAddress.getByAddress(addr);
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900646 } catch (UnknownHostException e) {}
Robert Greenwalt5a901292011-04-28 14:28:50 -0700647
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800648 String iface = in.readString();
Lorenzo Colitti21290342014-09-19 01:49:05 +0900649 int type = in.readInt();
Sarah Chinf75d09f2020-01-16 11:19:52 -0800650 int mtu = in.readInt();
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800651
Sarah Chinf75d09f2020-01-16 11:19:52 -0800652 return new RouteInfo(dest, gateway, iface, type, mtu);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700653 }
654
655 public RouteInfo[] newArray(int size) {
656 return new RouteInfo[size];
657 }
658 };
Robert Greenwalt5a901292011-04-28 14:28:50 -0700659}