blob: 94f849f006f369519165e456c43c4740654fcee3 [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
paulhu6f2c1b52019-03-27 22:26:37 +080019import android.annotation.IntDef;
20import android.annotation.NonNull;
paulhu9bb04802019-03-08 16:35:20 +080021import android.annotation.Nullable;
Remi NGUYEN VAN5af2e292019-01-20 12:52:43 +090022import android.annotation.SystemApi;
Artur Satayev0e45d782019-12-10 17:47:52 +000023import android.compat.annotation.UnsupportedAppUsage;
Mathew Inwoodac5968e2018-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 Jeanfa159c12020-08-19 16:07:22 +090028import com.android.net.module.util.NetUtils;
29
paulhu6f2c1b52019-03-27 22:26:37 +080030import java.lang.annotation.Retention;
31import java.lang.annotation.RetentionPolicy;
Robert Greenwalt5a901292011-04-28 14:28:50 -070032import java.net.Inet4Address;
33import java.net.Inet6Address;
Remi NGUYEN VAN5af2e292019-01-20 12:52:43 +090034import java.net.InetAddress;
35import java.net.UnknownHostException;
Robert Greenwaltbd492212011-05-06 17:10:53 -070036import java.util.Collection;
Robert Greenwalt791a40d2014-05-18 23:33:07 -070037import java.util.Objects;
Robert Greenwaltbd492212011-05-06 17:10:53 -070038
Robert Greenwalt5a901292011-04-28 14:28:50 -070039/**
Robert Greenwalt791a40d2014-05-18 23:33:07 -070040 * Represents a network route.
Robert Greenwalt8b57c412014-05-18 12:05:05 -070041 * <p>
42 * This is used both to describe static network configuration and live network
Robert Greenwalt791a40d2014-05-18 23:33:07 -070043 * configuration information.
Robert Greenwalt5a901292011-04-28 14:28:50 -070044 *
Robert Greenwalt791a40d2014-05-18 23:33:07 -070045 * A route contains three pieces of information:
Robert Greenwalt8b57c412014-05-18 12:05:05 -070046 * <ul>
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -070047 * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route.
48 * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6)
Robert Greenwalt791a40d2014-05-18 23:33:07 -070049 * implied by the gateway IP address.
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -070050 * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
Robert Greenwalt791a40d2014-05-18 23:33:07 -070051 * indicates a directly-connected route.
52 * <li>an interface (which may be unspecified).
Robert Greenwalt8b57c412014-05-18 12:05:05 -070053 * </ul>
Robert Greenwalt791a40d2014-05-18 23:33:07 -070054 * Either the destination or the gateway may be {@code null}, but not both. If the
55 * destination and gateway are both specified, they must be of the same address family
56 * (IPv4 or IPv6).
Robert Greenwalt5a901292011-04-28 14:28:50 -070057 */
Robert Greenwaltcccf73a2014-06-12 16:24:38 -070058public final class RouteInfo implements Parcelable {
paulhu6f2c1b52019-03-27 22:26:37 +080059 /** @hide */
60 @IntDef(value = {
61 RTN_UNICAST,
62 RTN_UNREACHABLE,
63 RTN_THROW,
64 })
65 @Retention(RetentionPolicy.SOURCE)
66 public @interface RouteType {}
67
Robert Greenwalt5a901292011-04-28 14:28:50 -070068 /**
69 * The IP destination address for this route.
70 */
paulhu6f2c1b52019-03-27 22:26:37 +080071 @NonNull
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +090072 private final IpPrefix mDestination;
Robert Greenwalt5a901292011-04-28 14:28:50 -070073
74 /**
75 * The gateway address for this route.
76 */
Mathew Inwood0b8f8612018-08-08 14:52:47 +010077 @UnsupportedAppUsage
paulhu6f2c1b52019-03-27 22:26:37 +080078 @Nullable
Robert Greenwalt5a901292011-04-28 14:28:50 -070079 private final InetAddress mGateway;
80
Lorenzo Colitti05805982013-03-08 11:30:39 -080081 /**
82 * The interface for this route.
83 */
paulhu6f2c1b52019-03-27 22:26:37 +080084 @Nullable
Lorenzo Colitti05805982013-03-08 11:30:39 -080085 private final String mInterface;
86
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +090087
88 /** Unicast route. @hide */
Remi NGUYEN VAN5af2e292019-01-20 12:52:43 +090089 @SystemApi
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +090090 public static final int RTN_UNICAST = 1;
91
92 /** Unreachable route. @hide */
Remi NGUYEN VAN5af2e292019-01-20 12:52:43 +090093 @SystemApi
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +090094 public static final int RTN_UNREACHABLE = 7;
95
96 /** Throw route. @hide */
Remi NGUYEN VAN5af2e292019-01-20 12:52:43 +090097 @SystemApi
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +090098 public static final int RTN_THROW = 9;
99
100 /**
101 * The type of this route; one of the RTN_xxx constants above.
102 */
103 private final int mType;
104
Sarah Chin707c0e92020-01-16 11:19:52 -0800105 /**
106 * The maximum transmission unit size for this route.
107 */
108 private final int mMtu;
109
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900110 // Derived data members.
111 // TODO: remove these.
Mathew Inwoodac5968e2018-12-20 15:30:45 +0000112 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700113 private final boolean mIsHost;
Robert Greenwalt24bc5342013-04-11 13:48:16 -0700114 private final boolean mHasGateway;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700115
Lorenzo Colitti05805982013-03-08 11:30:39 -0800116 /**
117 * Constructs a RouteInfo object.
118 *
Lorenzo Colittiab7ad3a2013-03-12 04:30:47 +0900119 * If destination is null, then gateway must be specified and the
Lorenzo Colitti05805982013-03-08 11:30:39 -0800120 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700121 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
Lorenzo Colittiab7ad3a2013-03-12 04:30:47 +0900122 * route <code>::/0</code> if gateway is an instance of
Lorenzo Colitti05805982013-03-08 11:30:39 -0800123 * {@link Inet6Address}.
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700124 * <p>
Lorenzo Colittiab7ad3a2013-03-12 04:30:47 +0900125 * destination and gateway may not both be null.
Lorenzo Colitti05805982013-03-08 11:30:39 -0800126 *
127 * @param destination the destination prefix
128 * @param gateway the IP address to route packets through
129 * @param iface the interface name to send packets on
paulhu6f2c1b52019-03-27 22:26:37 +0800130 * @param type the type of this route
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700131 *
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700132 * @hide
133 */
Remi NGUYEN VAN76be7232019-01-24 00:55:43 +0900134 @SystemApi
paulhu9bb04802019-03-08 16:35:20 +0800135 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
paulhu6f2c1b52019-03-27 22:26:37 +0800136 @Nullable String iface, @RouteType int type) {
Sarah Chin707c0e92020-01-16 11:19:52 -0800137 this(destination, gateway, iface, type, 0);
138 }
139
140 /**
141 * Constructs a RouteInfo object.
142 *
143 * If destination is null, then gateway must be specified and the
144 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
145 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
146 * route <code>::/0</code> if gateway is an instance of
147 * {@link Inet6Address}.
148 * <p>
149 * destination and gateway may not both be null.
150 *
151 * @param destination the destination prefix
152 * @param gateway the IP address to route packets through
153 * @param iface the interface name to send packets on
154 * @param type the type of this route
155 * @param mtu the maximum transmission unit size for this route
156 *
157 * @hide
158 */
159 @SystemApi
160 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
161 @Nullable String iface, @RouteType int type, int mtu) {
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900162 switch (type) {
163 case RTN_UNICAST:
164 case RTN_UNREACHABLE:
165 case RTN_THROW:
166 // TODO: It would be nice to ensure that route types that don't have nexthops or
167 // interfaces, such as unreachable or throw, can't be created if an interface or
168 // a gateway is specified. This is a bit too complicated to do at the moment
169 // because:
170 //
171 // - LinkProperties sets the interface on routes added to it, and modifies the
172 // interfaces of all the routes when its interface name changes.
173 // - Even when the gateway is null, we store a non-null gateway here.
174 //
175 // For now, we just rely on the code that sets routes to do things properly.
176 break;
177 default:
178 throw new IllegalArgumentException("Unknown route type " + type);
179 }
180
Robert Greenwalt5a901292011-04-28 14:28:50 -0700181 if (destination == null) {
Robert Greenwalt355205c2011-05-10 15:05:02 -0700182 if (gateway != null) {
183 if (gateway instanceof Inet4Address) {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900184 destination = new IpPrefix(Inet4Address.ANY, 0);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700185 } else {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900186 destination = new IpPrefix(Inet6Address.ANY, 0);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700187 }
Robert Greenwalt355205c2011-05-10 15:05:02 -0700188 } else {
189 // no destination, no gateway. invalid.
Lorenzo Colitti05805982013-03-08 11:30:39 -0800190 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
Sarah Chin707c0e92020-01-16 11:19:52 -0800191 destination);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700192 }
Robert Greenwalt5a901292011-04-28 14:28:50 -0700193 }
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900194 // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
195 // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
196 // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500197 if (gateway == null) {
198 if (destination.getAddress() instanceof Inet4Address) {
199 gateway = Inet4Address.ANY;
200 } else {
201 gateway = Inet6Address.ANY;
202 }
203 }
Robert Greenwalt24bc5342013-04-11 13:48:16 -0700204 mHasGateway = (!gateway.isAnyLocalAddress());
205
Sarah Chin707c0e92020-01-16 11:19:52 -0800206 if ((destination.getAddress() instanceof Inet4Address
207 && !(gateway instanceof Inet4Address))
208 || (destination.getAddress() instanceof Inet6Address
209 && !(gateway instanceof Inet6Address))) {
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700210 throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
211 }
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900212 mDestination = destination; // IpPrefix objects are immutable.
213 mGateway = gateway; // InetAddress objects are immutable.
214 mInterface = iface; // Strings are immutable.
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900215 mType = type;
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700216 mIsHost = isHost();
Sarah Chin707c0e92020-01-16 11:19:52 -0800217 mMtu = mtu;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700218 }
219
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700220 /**
paulhu6f2c1b52019-03-27 22:26:37 +0800221 * Constructs a {@code RouteInfo} object.
222 *
223 * If destination is null, then gateway must be specified and the
224 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
225 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
226 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
227 * <p>
228 * Destination and gateway may not both be null.
229 *
230 * @param destination the destination address and prefix in an {@link IpPrefix}
231 * @param gateway the {@link InetAddress} to route packets through
232 * @param iface the interface name to send packets on
233 *
234 * @hide
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900235 */
Mathew Inwood5a09a712020-11-04 09:29:36 +0000236 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu6f2c1b52019-03-27 22:26:37 +0800237 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
238 @Nullable String iface) {
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900239 this(destination, gateway, iface, RTN_UNICAST);
240 }
241
242 /**
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900243 * @hide
244 */
Mathew Inwood0b8f8612018-08-08 14:52:47 +0100245 @UnsupportedAppUsage
paulhu6f2c1b52019-03-27 22:26:37 +0800246 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway,
247 @Nullable String iface) {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900248 this(destination == null ? null :
249 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
250 gateway, iface);
251 }
252
253 /**
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700254 * Constructs a {@code RouteInfo} object.
255 *
256 * If destination is null, then gateway must be specified and the
257 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
258 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
259 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
260 * <p>
261 * Destination and gateway may not both be null.
262 *
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700263 * @param destination the destination address and prefix in an {@link IpPrefix}
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700264 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700265 *
266 * @hide
267 */
paulhu6f2c1b52019-03-27 22:26:37 +0800268 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) {
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700269 this(destination, gateway, null);
270 }
271
272 /**
273 * @hide
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900274 *
275 * TODO: Remove this.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700276 */
Mathew Inwood0b8f8612018-08-08 14:52:47 +0100277 @UnsupportedAppUsage
paulhu6f2c1b52019-03-27 22:26:37 +0800278 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) {
Lorenzo Colitti05805982013-03-08 11:30:39 -0800279 this(destination, gateway, null);
280 }
281
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700282 /**
283 * Constructs a default {@code RouteInfo} object.
284 *
285 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700286 *
287 * @hide
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700288 */
Mathew Inwood0b8f8612018-08-08 14:52:47 +0100289 @UnsupportedAppUsage
paulhu6f2c1b52019-03-27 22:26:37 +0800290 public RouteInfo(@NonNull InetAddress gateway) {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900291 this((IpPrefix) null, gateway, null);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700292 }
293
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700294 /**
295 * Constructs a {@code RouteInfo} object representing a direct connected subnet.
296 *
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700297 * @param destination the {@link IpPrefix} describing the address and prefix
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700298 * length of the subnet.
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700299 *
300 * @hide
301 */
paulhu6f2c1b52019-03-27 22:26:37 +0800302 public RouteInfo(@NonNull IpPrefix destination) {
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700303 this(destination, null, null);
304 }
305
306 /**
307 * @hide
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700308 */
paulhu6f2c1b52019-03-27 22:26:37 +0800309 public RouteInfo(@NonNull LinkAddress destination) {
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700310 this(destination, null, null);
Robert Greenwalte110d002012-10-31 14:32:53 -0700311 }
312
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700313 /**
314 * @hide
315 */
paulhu6f2c1b52019-03-27 22:26:37 +0800316 public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) {
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900317 this(destination, null, null, type);
318 }
319
320 /**
321 * @hide
322 */
paulhu6f2c1b52019-03-27 22:26:37 +0800323 public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) {
Lorenzo Colitti697e1c02013-03-08 12:30:44 -0800324 return makeHostRoute(host, null, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700325 }
326
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700327 /**
328 * @hide
329 */
paulhu6f2c1b52019-03-27 22:26:37 +0800330 public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway,
331 @Nullable String iface) {
Robert Greenwalt355205c2011-05-10 15:05:02 -0700332 if (host == null) return null;
333
334 if (host instanceof Inet4Address) {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900335 return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700336 } else {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900337 return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700338 }
339 }
340
Mathew Inwoodac5968e2018-12-20 15:30:45 +0000341 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700342 private boolean isHost() {
Lorenzo Colitticdc56fe2013-03-27 13:07:18 +0900343 return (mDestination.getAddress() instanceof Inet4Address &&
Lorenzo Colitti48a7da02014-06-09 22:58:46 +0900344 mDestination.getPrefixLength() == 32) ||
Lorenzo Colitticdc56fe2013-03-27 13:07:18 +0900345 (mDestination.getAddress() instanceof Inet6Address &&
Lorenzo Colitti48a7da02014-06-09 22:58:46 +0900346 mDestination.getPrefixLength() == 128);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700347 }
348
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700349 /**
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700350 * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700351 *
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700352 * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700353 */
paulhu6f2c1b52019-03-27 22:26:37 +0800354 @NonNull
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700355 public IpPrefix getDestination() {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900356 return mDestination;
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700357 }
358
359 /**
360 * TODO: Convert callers to use IpPrefix and then remove.
361 * @hide
362 */
paulhu6f2c1b52019-03-27 22:26:37 +0800363 @NonNull
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700364 public LinkAddress getDestinationLinkAddress() {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900365 return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
Robert Greenwalt5a901292011-04-28 14:28:50 -0700366 }
367
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700368 /**
369 * Retrieves the gateway or next hop {@link InetAddress} for this route.
370 *
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700371 * @return {@link InetAddress} specifying the gateway or next hop. This may be
Robert Greenwaltcccf73a2014-06-12 16:24:38 -0700372 * {@code null} for a directly-connected route."
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700373 */
paulhu6f2c1b52019-03-27 22:26:37 +0800374 @Nullable
Robert Greenwalt5a901292011-04-28 14:28:50 -0700375 public InetAddress getGateway() {
376 return mGateway;
377 }
378
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700379 /**
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700380 * Retrieves the interface used for this route if specified, else {@code null}.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700381 *
382 * @return The name of the interface used for this route.
383 */
paulhu6f2c1b52019-03-27 22:26:37 +0800384 @Nullable
Lorenzo Colitti05805982013-03-08 11:30:39 -0800385 public String getInterface() {
386 return mInterface;
387 }
388
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700389 /**
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900390 * Retrieves the type of this route.
391 *
392 * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
393 *
394 * @hide
395 */
Remi NGUYEN VAN5af2e292019-01-20 12:52:43 +0900396 @SystemApi
paulhu6f2c1b52019-03-27 22:26:37 +0800397 @RouteType
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900398 public int getType() {
399 return mType;
400 }
401
402 /**
Sarah Chin707c0e92020-01-16 11:19:52 -0800403 * Retrieves the MTU size for this route.
404 *
405 * @return The MTU size, or 0 if it has not been set.
406 * @hide
407 */
408 @SystemApi
409 public int getMtu() {
410 return mMtu;
411 }
412
413 /**
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700414 * Indicates if this route is a default route (ie, has no destination specified).
415 *
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700416 * @return {@code true} if the destination has a prefix length of 0.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700417 */
Robert Greenwalt5a901292011-04-28 14:28:50 -0700418 public boolean isDefaultRoute() {
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900419 return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900420 }
421
422 /**
Rubin Xufa429012020-03-30 14:37:05 +0100423 * Indicates if this route is an unreachable default route.
424 *
425 * @return {@code true} if it's an unreachable route with prefix length of 0.
426 * @hide
427 */
428 private boolean isUnreachableDefaultRoute() {
429 return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0;
430 }
431
432 /**
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900433 * Indicates if this route is an IPv4 default route.
434 * @hide
435 */
436 public boolean isIPv4Default() {
437 return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
438 }
439
440 /**
Rubin Xufa429012020-03-30 14:37:05 +0100441 * Indicates if this route is an IPv4 unreachable default route.
442 * @hide
443 */
444 public boolean isIPv4UnreachableDefault() {
445 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
446 }
447
448 /**
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900449 * Indicates if this route is an IPv6 default route.
450 * @hide
451 */
452 public boolean isIPv6Default() {
453 return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700454 }
455
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700456 /**
Rubin Xufa429012020-03-30 14:37:05 +0100457 * Indicates if this route is an IPv6 unreachable default route.
458 * @hide
459 */
460 public boolean isIPv6UnreachableDefault() {
461 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
462 }
463
464 /**
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700465 * Indicates if this route is a host route (ie, matches only a single host address).
466 *
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700467 * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
468 * respectively.
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700469 * @hide
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700470 */
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700471 public boolean isHostRoute() {
472 return mIsHost;
473 }
474
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700475 /**
476 * Indicates if this route has a next hop ({@code true}) or is directly-connected
477 * ({@code false}).
478 *
479 * @return {@code true} if a gateway is specified
480 */
Robert Greenwalt24bc5342013-04-11 13:48:16 -0700481 public boolean hasGateway() {
482 return mHasGateway;
483 }
484
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700485 /**
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700486 * Determines whether the destination and prefix of this route includes the specified
487 * address.
488 *
489 * @param destination A {@link InetAddress} to test to see if it would match this route.
490 * @return {@code true} if the destination and prefix length cover the given address.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700491 */
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700492 public boolean matches(InetAddress destination) {
Erik Kline8a100e32015-04-13 15:33:34 +0900493 return mDestination.contains(destination);
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700494 }
495
496 /**
497 * Find the route from a Collection of routes that best matches a given address.
498 * May return null if no routes are applicable.
499 * @param routes a Collection of RouteInfos to chose from
500 * @param dest the InetAddress your trying to get to
501 * @return the RouteInfo from the Collection that best fits the given address
502 *
503 * @hide
504 */
Mathew Inwood5a09a712020-11-04 09:29:36 +0000505 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu6f2c1b52019-03-27 22:26:37 +0800506 @Nullable
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700507 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
Aaron Huang2a21ea72019-12-17 00:33:18 +0800508 return NetUtils.selectBestRoute(routes, dest);
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700509 }
510
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700511 /**
512 * Returns a human-readable description of this object.
513 */
Robert Greenwalt5a901292011-04-28 14:28:50 -0700514 public String toString() {
515 String val = "";
516 if (mDestination != null) val = mDestination.toString();
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900517 if (mType == RTN_UNREACHABLE) {
518 val += " unreachable";
519 } else if (mType == RTN_THROW) {
520 val += " throw";
521 } else {
522 val += " ->";
523 if (mGateway != null) val += " " + mGateway.getHostAddress();
524 if (mInterface != null) val += " " + mInterface;
525 if (mType != RTN_UNICAST) {
526 val += " unknown type " + mType;
527 }
528 }
Sarah Chin707c0e92020-01-16 11:19:52 -0800529 val += " mtu " + mMtu;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700530 return val;
531 }
532
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700533 /**
534 * Compares this RouteInfo object against the specified object and indicates if they are equal.
535 * @return {@code true} if the objects are equal, {@code false} otherwise.
536 */
Wink Savillef23fb202011-05-18 15:59:04 -0700537 public boolean equals(Object obj) {
538 if (this == obj) return true;
539
540 if (!(obj instanceof RouteInfo)) return false;
541
542 RouteInfo target = (RouteInfo) obj;
543
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900544 return Objects.equals(mDestination, target.getDestination()) &&
Robert Greenwalt791a40d2014-05-18 23:33:07 -0700545 Objects.equals(mGateway, target.getGateway()) &&
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900546 Objects.equals(mInterface, target.getInterface()) &&
Sarah Chin707c0e92020-01-16 11:19:52 -0800547 mType == target.getType() && mMtu == target.getMtu();
Wink Savillef23fb202011-05-18 15:59:04 -0700548 }
549
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700550 /**
Rubin Xuad524de2020-06-11 16:40:13 +0100551 * A helper class that contains the destination, the gateway and the interface in a
552 * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or
junyulai21c26da2020-03-23 20:49:43 +0800553 * {@link LinkProperties#addRoute} to calculate the list to be updated.
Rubin Xuad524de2020-06-11 16:40:13 +0100554 * {@code RouteInfo} objects with different interfaces are treated as different routes because
555 * *usually* on Android different interfaces use different routing tables, and moving a route
556 * to a new routing table never constitutes an update, but is always a remove and an add.
Tyler Weara8978d42019-12-05 14:55:30 -0800557 *
558 * @hide
559 */
Rubin Xuad524de2020-06-11 16:40:13 +0100560 public static class RouteKey {
561 @NonNull private final IpPrefix mDestination;
562 @Nullable private final InetAddress mGateway;
563 @Nullable private final String mInterface;
564
565 RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway,
566 @Nullable String iface) {
567 mDestination = destination;
568 mGateway = gateway;
569 mInterface = iface;
570 }
571
572 @Override
573 public boolean equals(Object o) {
574 if (!(o instanceof RouteKey)) {
575 return false;
576 }
577 RouteKey p = (RouteKey) o;
578 // No need to do anything special for scoped addresses. Inet6Address#equals does not
579 // consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel)
580 // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only
581 // look at RTA_OIF.
582 return Objects.equals(p.mDestination, mDestination)
583 && Objects.equals(p.mGateway, mGateway)
584 && Objects.equals(p.mInterface, mInterface);
585 }
586
587 @Override
588 public int hashCode() {
589 return Objects.hash(mDestination, mGateway, mInterface);
Tyler Weara8978d42019-12-05 14:55:30 -0800590 }
junyulai21c26da2020-03-23 20:49:43 +0800591 }
592
593 /**
594 * Get {@code RouteKey} of this {@code RouteInfo}.
595 * @return a {@code RouteKey} object.
596 *
597 * @hide
598 */
599 @NonNull
600 public RouteKey getRouteKey() {
Rubin Xuad524de2020-06-11 16:40:13 +0100601 return new RouteKey(mDestination, mGateway, mInterface);
Tyler Weara8978d42019-12-05 14:55:30 -0800602 }
603
604 /**
Sreeram Ramachandran8162a5e2014-06-03 18:41:43 -0700605 * Returns a hashcode for this <code>RouteInfo</code> object.
606 */
Wink Savillef23fb202011-05-18 15:59:04 -0700607 public int hashCode() {
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900608 return (mDestination.hashCode() * 41)
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700609 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900610 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
Sarah Chin707c0e92020-01-16 11:19:52 -0800611 + (mType * 71) + (mMtu * 89);
Wink Savillef23fb202011-05-18 15:59:04 -0700612 }
613
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700614 /**
615 * Implement the Parcelable interface
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700616 */
617 public int describeContents() {
618 return 0;
619 }
620
621 /**
622 * Implement the Parcelable interface
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700623 */
624 public void writeToParcel(Parcel dest, int flags) {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900625 dest.writeParcelable(mDestination, flags);
626 byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
627 dest.writeByteArray(gatewayBytes);
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700628 dest.writeString(mInterface);
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900629 dest.writeInt(mType);
Sarah Chin707c0e92020-01-16 11:19:52 -0800630 dest.writeInt(mMtu);
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700631 }
632
633 /**
634 * Implement the Parcelable interface.
Robert Greenwalt8b57c412014-05-18 12:05:05 -0700635 */
Jeff Sharkey9286f912019-02-28 12:06:45 -0700636 public static final @android.annotation.NonNull Creator<RouteInfo> CREATOR =
Robert Greenwalt5a901292011-04-28 14:28:50 -0700637 new Creator<RouteInfo>() {
638 public RouteInfo createFromParcel(Parcel in) {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900639 IpPrefix dest = in.readParcelable(null);
640
Robert Greenwalt5a901292011-04-28 14:28:50 -0700641 InetAddress gateway = null;
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900642 byte[] addr = in.createByteArray();
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900643 try {
Lorenzo Colitti4a0ff022014-08-12 12:37:50 +0900644 gateway = InetAddress.getByAddress(addr);
Lorenzo Colitti1b72e052014-06-23 21:27:53 +0900645 } catch (UnknownHostException e) {}
Robert Greenwalt5a901292011-04-28 14:28:50 -0700646
Lorenzo Colitti05805982013-03-08 11:30:39 -0800647 String iface = in.readString();
Lorenzo Colitti8eac7b32014-09-19 01:49:05 +0900648 int type = in.readInt();
Sarah Chin707c0e92020-01-16 11:19:52 -0800649 int mtu = in.readInt();
Lorenzo Colitti05805982013-03-08 11:30:39 -0800650
Sarah Chin707c0e92020-01-16 11:19:52 -0800651 return new RouteInfo(dest, gateway, iface, type, mtu);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700652 }
653
654 public RouteInfo[] newArray(int size) {
655 return new RouteInfo[size];
656 }
657 };
Robert Greenwalt5a901292011-04-28 14:28:50 -0700658}