blob: e8ebf8137ace2502067198b033a615833136e628 [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
Taras Antoshchuk2b3d62f2021-12-19 11:51:39 +000089 /**
90 * Unicast route.
91 *
92 * Indicates that destination is reachable directly or via gateway.
93 **/
Lorenzo Colitti21290342014-09-19 01:49:05 +090094 public static final int RTN_UNICAST = 1;
95
Taras Antoshchuk2b3d62f2021-12-19 11:51:39 +000096 /**
97 * Unreachable route.
98 *
99 * Indicates that destination is unreachable.
100 **/
Lorenzo Colitti21290342014-09-19 01:49:05 +0900101 public static final int RTN_UNREACHABLE = 7;
102
Taras Antoshchuk2b3d62f2021-12-19 11:51:39 +0000103 /**
104 * Throw route.
105 *
106 * Indicates that routing information about this destination is not in this table.
107 * Routing lookup should continue in another table.
108 **/
Lorenzo Colitti21290342014-09-19 01:49:05 +0900109 public static final int RTN_THROW = 9;
110
111 /**
112 * The type of this route; one of the RTN_xxx constants above.
113 */
114 private final int mType;
115
Sarah Chinf75d09f2020-01-16 11:19:52 -0800116 /**
117 * The maximum transmission unit size for this route.
118 */
119 private final int mMtu;
120
Lorenzo Colitti21290342014-09-19 01:49:05 +0900121 // Derived data members.
122 // TODO: remove these.
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +0000123 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700124 private final boolean mIsHost;
Robert Greenwalt59070cf2013-04-11 13:48:16 -0700125 private final boolean mHasGateway;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700126
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800127 /**
128 * Constructs a RouteInfo object.
129 *
Lorenzo Colittifb475942013-03-12 04:30:47 +0900130 * If destination is null, then gateway must be specified and the
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800131 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700132 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
Lorenzo Colittifb475942013-03-12 04:30:47 +0900133 * route <code>::/0</code> if gateway is an instance of
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800134 * {@link Inet6Address}.
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700135 * <p>
Lorenzo Colittifb475942013-03-12 04:30:47 +0900136 * destination and gateway may not both be null.
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800137 *
138 * @param destination the destination prefix
139 * @param gateway the IP address to route packets through
140 * @param iface the interface name to send packets on
paulhu895a7412019-03-27 22:26:37 +0800141 * @param type the type of this route
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700142 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700143 * @hide
144 */
Remi NGUYEN VANdaace812019-01-24 00:55:43 +0900145 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800146 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
paulhu895a7412019-03-27 22:26:37 +0800147 @Nullable String iface, @RouteType int type) {
Sarah Chinf75d09f2020-01-16 11:19:52 -0800148 this(destination, gateway, iface, type, 0);
149 }
150
151 /**
152 * Constructs a RouteInfo object.
153 *
154 * If destination is null, then gateway must be specified and the
155 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
156 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
157 * route <code>::/0</code> if gateway is an instance of
158 * {@link Inet6Address}.
159 * <p>
160 * destination and gateway may not both be null.
161 *
162 * @param destination the destination prefix
163 * @param gateway the IP address to route packets through
164 * @param iface the interface name to send packets on
165 * @param type the type of this route
166 * @param mtu the maximum transmission unit size for this route
167 *
168 * @hide
169 */
170 @SystemApi
171 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
172 @Nullable String iface, @RouteType int type, int mtu) {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900173 switch (type) {
174 case RTN_UNICAST:
175 case RTN_UNREACHABLE:
176 case RTN_THROW:
177 // TODO: It would be nice to ensure that route types that don't have nexthops or
178 // interfaces, such as unreachable or throw, can't be created if an interface or
179 // a gateway is specified. This is a bit too complicated to do at the moment
180 // because:
181 //
182 // - LinkProperties sets the interface on routes added to it, and modifies the
183 // interfaces of all the routes when its interface name changes.
184 // - Even when the gateway is null, we store a non-null gateway here.
185 //
186 // For now, we just rely on the code that sets routes to do things properly.
187 break;
188 default:
189 throw new IllegalArgumentException("Unknown route type " + type);
190 }
191
Robert Greenwalt5a901292011-04-28 14:28:50 -0700192 if (destination == null) {
Robert Greenwalt355205c2011-05-10 15:05:02 -0700193 if (gateway != null) {
194 if (gateway instanceof Inet4Address) {
paulhub5343312021-03-04 10:53:27 +0800195 destination = new IpPrefix(NetworkStackConstants.IPV4_ADDR_ANY, 0);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700196 } else {
paulhub5343312021-03-04 10:53:27 +0800197 destination = new IpPrefix(NetworkStackConstants.IPV6_ADDR_ANY, 0);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700198 }
Robert Greenwalt355205c2011-05-10 15:05:02 -0700199 } else {
200 // no destination, no gateway. invalid.
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800201 throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
Sarah Chinf75d09f2020-01-16 11:19:52 -0800202 destination);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700203 }
Robert Greenwalt5a901292011-04-28 14:28:50 -0700204 }
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900205 // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
206 // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
207 // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500208 if (gateway == null) {
209 if (destination.getAddress() instanceof Inet4Address) {
paulhub5343312021-03-04 10:53:27 +0800210 gateway = NetworkStackConstants.IPV4_ADDR_ANY;
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500211 } else {
paulhub5343312021-03-04 10:53:27 +0800212 gateway = NetworkStackConstants.IPV6_ADDR_ANY;
Kazuhiro Ondoefa66d92011-05-11 14:55:19 -0500213 }
214 }
Robert Greenwalt59070cf2013-04-11 13:48:16 -0700215 mHasGateway = (!gateway.isAnyLocalAddress());
216
Sarah Chinf75d09f2020-01-16 11:19:52 -0800217 if ((destination.getAddress() instanceof Inet4Address
218 && !(gateway instanceof Inet4Address))
219 || (destination.getAddress() instanceof Inet6Address
220 && !(gateway instanceof Inet6Address))) {
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700221 throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
222 }
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900223 mDestination = destination; // IpPrefix objects are immutable.
224 mGateway = gateway; // InetAddress objects are immutable.
225 mInterface = iface; // Strings are immutable.
Lorenzo Colitti21290342014-09-19 01:49:05 +0900226 mType = type;
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700227 mIsHost = isHost();
Sarah Chinf75d09f2020-01-16 11:19:52 -0800228 mMtu = mtu;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700229 }
230
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700231 /**
paulhu895a7412019-03-27 22:26:37 +0800232 * Constructs a {@code RouteInfo} object.
233 *
234 * If destination is null, then gateway must be specified and the
235 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
236 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
237 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
238 * <p>
239 * Destination and gateway may not both be null.
240 *
241 * @param destination the destination address and prefix in an {@link IpPrefix}
242 * @param gateway the {@link InetAddress} to route packets through
243 * @param iface the interface name to send packets on
244 *
245 * @hide
Lorenzo Colitti21290342014-09-19 01:49:05 +0900246 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000247 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu895a7412019-03-27 22:26:37 +0800248 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
249 @Nullable String iface) {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900250 this(destination, gateway, iface, RTN_UNICAST);
251 }
252
253 /**
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900254 * @hide
255 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100256 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +0800257 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway,
258 @Nullable String iface) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900259 this(destination == null ? null :
260 new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
261 gateway, iface);
262 }
263
264 /**
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700265 * Constructs a {@code RouteInfo} object.
266 *
267 * If destination is null, then gateway must be specified and the
268 * constructed route is either the IPv4 default route <code>0.0.0.0</code>
269 * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
270 * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
271 * <p>
272 * Destination and gateway may not both be null.
273 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700274 * @param destination the destination address and prefix in an {@link IpPrefix}
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700275 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700276 *
277 * @hide
278 */
paulhu895a7412019-03-27 22:26:37 +0800279 public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) {
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700280 this(destination, gateway, null);
281 }
282
283 /**
284 * @hide
Lorenzo Colitti21290342014-09-19 01:49:05 +0900285 *
286 * TODO: Remove this.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700287 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100288 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +0800289 public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) {
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800290 this(destination, gateway, null);
291 }
292
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700293 /**
294 * Constructs a default {@code RouteInfo} object.
295 *
296 * @param gateway the {@link InetAddress} to route packets through
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700297 *
298 * @hide
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700299 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100300 @UnsupportedAppUsage
paulhu895a7412019-03-27 22:26:37 +0800301 public RouteInfo(@NonNull InetAddress gateway) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900302 this((IpPrefix) null, gateway, null);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700303 }
304
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700305 /**
306 * Constructs a {@code RouteInfo} object representing a direct connected subnet.
307 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700308 * @param destination the {@link IpPrefix} describing the address and prefix
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700309 * length of the subnet.
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700310 *
311 * @hide
312 */
paulhu895a7412019-03-27 22:26:37 +0800313 public RouteInfo(@NonNull IpPrefix destination) {
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700314 this(destination, null, null);
315 }
316
317 /**
318 * @hide
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700319 */
paulhu895a7412019-03-27 22:26:37 +0800320 public RouteInfo(@NonNull LinkAddress destination) {
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700321 this(destination, null, null);
Robert Greenwalt462e5702012-10-31 14:32:53 -0700322 }
323
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700324 /**
325 * @hide
326 */
paulhu895a7412019-03-27 22:26:37 +0800327 public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900328 this(destination, null, null, type);
329 }
330
331 /**
332 * @hide
333 */
paulhu895a7412019-03-27 22:26:37 +0800334 public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) {
Lorenzo Colitti7a43b0f2013-03-08 12:30:44 -0800335 return makeHostRoute(host, null, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700336 }
337
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700338 /**
339 * @hide
340 */
paulhu895a7412019-03-27 22:26:37 +0800341 public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway,
342 @Nullable String iface) {
Robert Greenwalt355205c2011-05-10 15:05:02 -0700343 if (host == null) return null;
344
345 if (host instanceof Inet4Address) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900346 return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700347 } else {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900348 return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
Robert Greenwalt355205c2011-05-10 15:05:02 -0700349 }
350 }
351
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +0000352 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700353 private boolean isHost() {
Lorenzo Colittiaff54132013-03-27 13:07:18 +0900354 return (mDestination.getAddress() instanceof Inet4Address &&
Lorenzo Colittib0116bf2014-06-09 22:58:46 +0900355 mDestination.getPrefixLength() == 32) ||
Lorenzo Colittiaff54132013-03-27 13:07:18 +0900356 (mDestination.getAddress() instanceof Inet6Address &&
Lorenzo Colittib0116bf2014-06-09 22:58:46 +0900357 mDestination.getPrefixLength() == 128);
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700358 }
359
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700360 /**
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700361 * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700362 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700363 * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700364 */
paulhu895a7412019-03-27 22:26:37 +0800365 @NonNull
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700366 public IpPrefix getDestination() {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900367 return mDestination;
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700368 }
369
370 /**
371 * TODO: Convert callers to use IpPrefix and then remove.
372 * @hide
373 */
paulhu895a7412019-03-27 22:26:37 +0800374 @NonNull
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700375 public LinkAddress getDestinationLinkAddress() {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900376 return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
Robert Greenwalt5a901292011-04-28 14:28:50 -0700377 }
378
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700379 /**
380 * Retrieves the gateway or next hop {@link InetAddress} for this route.
381 *
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700382 * @return {@link InetAddress} specifying the gateway or next hop. This may be
Robert Greenwaltc4920a52014-06-12 16:24:38 -0700383 * {@code null} for a directly-connected route."
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700384 */
paulhu895a7412019-03-27 22:26:37 +0800385 @Nullable
Robert Greenwalt5a901292011-04-28 14:28:50 -0700386 public InetAddress getGateway() {
387 return mGateway;
388 }
389
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700390 /**
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700391 * Retrieves the interface used for this route if specified, else {@code null}.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700392 *
393 * @return The name of the interface used for this route.
394 */
paulhu895a7412019-03-27 22:26:37 +0800395 @Nullable
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800396 public String getInterface() {
397 return mInterface;
398 }
399
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700400 /**
Lorenzo Colitti21290342014-09-19 01:49:05 +0900401 * Retrieves the type of this route.
402 *
403 * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
Lorenzo Colitti21290342014-09-19 01:49:05 +0900404 */
paulhu895a7412019-03-27 22:26:37 +0800405 @RouteType
Lorenzo Colitti21290342014-09-19 01:49:05 +0900406 public int getType() {
407 return mType;
408 }
409
410 /**
Sarah Chinf75d09f2020-01-16 11:19:52 -0800411 * Retrieves the MTU size for this route.
412 *
413 * @return The MTU size, or 0 if it has not been set.
414 * @hide
415 */
416 @SystemApi
417 public int getMtu() {
418 return mMtu;
419 }
420
421 /**
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700422 * Indicates if this route is a default route (ie, has no destination specified).
423 *
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700424 * @return {@code true} if the destination has a prefix length of 0.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700425 */
Robert Greenwalt5a901292011-04-28 14:28:50 -0700426 public boolean isDefaultRoute() {
Lorenzo Colitti21290342014-09-19 01:49:05 +0900427 return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900428 }
429
430 /**
Rubin Xuab8cf302020-03-30 14:37:05 +0100431 * Indicates if this route is an unreachable default route.
432 *
433 * @return {@code true} if it's an unreachable route with prefix length of 0.
434 * @hide
435 */
436 private boolean isUnreachableDefaultRoute() {
437 return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0;
438 }
439
440 /**
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900441 * Indicates if this route is an IPv4 default route.
442 * @hide
443 */
444 public boolean isIPv4Default() {
445 return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
446 }
447
448 /**
Rubin Xuab8cf302020-03-30 14:37:05 +0100449 * Indicates if this route is an IPv4 unreachable default route.
450 * @hide
451 */
452 public boolean isIPv4UnreachableDefault() {
453 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
454 }
455
456 /**
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900457 * Indicates if this route is an IPv6 default route.
458 * @hide
459 */
460 public boolean isIPv6Default() {
461 return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700462 }
463
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700464 /**
Rubin Xuab8cf302020-03-30 14:37:05 +0100465 * Indicates if this route is an IPv6 unreachable default route.
466 * @hide
467 */
468 public boolean isIPv6UnreachableDefault() {
469 return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
470 }
471
472 /**
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700473 * Indicates if this route is a host route (ie, matches only a single host address).
474 *
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700475 * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
476 * respectively.
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700477 * @hide
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700478 */
Robert Greenwalte8d2a4a2011-07-14 14:28:05 -0700479 public boolean isHostRoute() {
480 return mIsHost;
481 }
482
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700483 /**
484 * Indicates if this route has a next hop ({@code true}) or is directly-connected
485 * ({@code false}).
486 *
487 * @return {@code true} if a gateway is specified
488 */
Robert Greenwalt59070cf2013-04-11 13:48:16 -0700489 public boolean hasGateway() {
490 return mHasGateway;
491 }
492
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700493 /**
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700494 * Determines whether the destination and prefix of this route includes the specified
495 * address.
496 *
497 * @param destination A {@link InetAddress} to test to see if it would match this route.
498 * @return {@code true} if the destination and prefix length cover the given address.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700499 */
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700500 public boolean matches(InetAddress destination) {
Erik Klineb98afb02015-04-13 15:33:34 +0900501 return mDestination.contains(destination);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700502 }
503
504 /**
505 * Find the route from a Collection of routes that best matches a given address.
506 * May return null if no routes are applicable.
507 * @param routes a Collection of RouteInfos to chose from
508 * @param dest the InetAddress your trying to get to
509 * @return the RouteInfo from the Collection that best fits the given address
510 *
511 * @hide
512 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000513 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhu895a7412019-03-27 22:26:37 +0800514 @Nullable
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700515 public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
Aaron Huang0e1759b2019-12-17 00:33:18 +0800516 return NetUtils.selectBestRoute(routes, dest);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700517 }
518
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700519 /**
520 * Returns a human-readable description of this object.
521 */
Robert Greenwalt5a901292011-04-28 14:28:50 -0700522 public String toString() {
523 String val = "";
524 if (mDestination != null) val = mDestination.toString();
Lorenzo Colitti21290342014-09-19 01:49:05 +0900525 if (mType == RTN_UNREACHABLE) {
526 val += " unreachable";
527 } else if (mType == RTN_THROW) {
528 val += " throw";
529 } else {
530 val += " ->";
531 if (mGateway != null) val += " " + mGateway.getHostAddress();
532 if (mInterface != null) val += " " + mInterface;
533 if (mType != RTN_UNICAST) {
534 val += " unknown type " + mType;
535 }
536 }
Sarah Chinf75d09f2020-01-16 11:19:52 -0800537 val += " mtu " + mMtu;
Robert Greenwalt5a901292011-04-28 14:28:50 -0700538 return val;
539 }
540
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700541 /**
542 * Compares this RouteInfo object against the specified object and indicates if they are equal.
543 * @return {@code true} if the objects are equal, {@code false} otherwise.
544 */
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -0700545 public boolean equals(@Nullable Object obj) {
Wink Savillef23fb202011-05-18 15:59:04 -0700546 if (this == obj) return true;
547
548 if (!(obj instanceof RouteInfo)) return false;
549
550 RouteInfo target = (RouteInfo) obj;
551
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900552 return Objects.equals(mDestination, target.getDestination()) &&
Robert Greenwalt223a6bd2014-05-18 23:33:07 -0700553 Objects.equals(mGateway, target.getGateway()) &&
Lorenzo Colitti21290342014-09-19 01:49:05 +0900554 Objects.equals(mInterface, target.getInterface()) &&
Sarah Chinf75d09f2020-01-16 11:19:52 -0800555 mType == target.getType() && mMtu == target.getMtu();
Wink Savillef23fb202011-05-18 15:59:04 -0700556 }
557
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700558 /**
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100559 * A helper class that contains the destination, the gateway and the interface in a
560 * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or
junyulaia1493a52020-03-23 20:49:43 +0800561 * {@link LinkProperties#addRoute} to calculate the list to be updated.
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100562 * {@code RouteInfo} objects with different interfaces are treated as different routes because
563 * *usually* on Android different interfaces use different routing tables, and moving a route
564 * to a new routing table never constitutes an update, but is always a remove and an add.
Tyler Weare4314862019-12-05 14:55:30 -0800565 *
566 * @hide
567 */
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100568 public static class RouteKey {
569 @NonNull private final IpPrefix mDestination;
570 @Nullable private final InetAddress mGateway;
571 @Nullable private final String mInterface;
572
573 RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway,
574 @Nullable String iface) {
575 mDestination = destination;
576 mGateway = gateway;
577 mInterface = iface;
578 }
579
580 @Override
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -0700581 public boolean equals(@Nullable Object o) {
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100582 if (!(o instanceof RouteKey)) {
583 return false;
584 }
585 RouteKey p = (RouteKey) o;
586 // No need to do anything special for scoped addresses. Inet6Address#equals does not
Chalard Jean2fb66f12023-08-25 12:50:37 +0900587 // consider the scope ID, but the route IPCs (e.g., RoutingCoordinatorManager#addRoute)
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100588 // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only
589 // look at RTA_OIF.
590 return Objects.equals(p.mDestination, mDestination)
591 && Objects.equals(p.mGateway, mGateway)
592 && Objects.equals(p.mInterface, mInterface);
593 }
594
595 @Override
596 public int hashCode() {
597 return Objects.hash(mDestination, mGateway, mInterface);
Tyler Weare4314862019-12-05 14:55:30 -0800598 }
junyulaia1493a52020-03-23 20:49:43 +0800599 }
600
601 /**
602 * Get {@code RouteKey} of this {@code RouteInfo}.
603 * @return a {@code RouteKey} object.
604 *
605 * @hide
606 */
607 @NonNull
608 public RouteKey getRouteKey() {
Rubin Xubc4c5ca2020-06-11 16:40:13 +0100609 return new RouteKey(mDestination, mGateway, mInterface);
Tyler Weare4314862019-12-05 14:55:30 -0800610 }
611
612 /**
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700613 * Returns a hashcode for this <code>RouteInfo</code> object.
614 */
Wink Savillef23fb202011-05-18 15:59:04 -0700615 public int hashCode() {
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900616 return (mDestination.hashCode() * 41)
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700617 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
Lorenzo Colitti21290342014-09-19 01:49:05 +0900618 + (mInterface == null ? 0 :mInterface.hashCode() * 67)
Sarah Chinf75d09f2020-01-16 11:19:52 -0800619 + (mType * 71) + (mMtu * 89);
Wink Savillef23fb202011-05-18 15:59:04 -0700620 }
621
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700622 /**
623 * Implement the Parcelable interface
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700624 */
625 public int describeContents() {
626 return 0;
627 }
628
629 /**
630 * Implement the Parcelable interface
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700631 */
632 public void writeToParcel(Parcel dest, int flags) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900633 dest.writeParcelable(mDestination, flags);
634 byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
635 dest.writeByteArray(gatewayBytes);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700636 dest.writeString(mInterface);
Lorenzo Colitti21290342014-09-19 01:49:05 +0900637 dest.writeInt(mType);
Sarah Chinf75d09f2020-01-16 11:19:52 -0800638 dest.writeInt(mMtu);
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700639 }
640
641 /**
642 * Implement the Parcelable interface.
Robert Greenwalt1aacd722014-05-18 12:05:05 -0700643 */
Jeff Sharkeyf8525282019-02-28 12:06:45 -0700644 public static final @android.annotation.NonNull Creator<RouteInfo> CREATOR =
Robert Greenwalt5a901292011-04-28 14:28:50 -0700645 new Creator<RouteInfo>() {
646 public RouteInfo createFromParcel(Parcel in) {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900647 IpPrefix dest = in.readParcelable(null);
648
Robert Greenwalt5a901292011-04-28 14:28:50 -0700649 InetAddress gateway = null;
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900650 byte[] addr = in.createByteArray();
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900651 try {
Lorenzo Colitti435565d2014-08-12 12:37:50 +0900652 gateway = InetAddress.getByAddress(addr);
Lorenzo Colitti99064fa2014-06-23 21:27:53 +0900653 } catch (UnknownHostException e) {}
Robert Greenwalt5a901292011-04-28 14:28:50 -0700654
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800655 String iface = in.readString();
Lorenzo Colitti21290342014-09-19 01:49:05 +0900656 int type = in.readInt();
Sarah Chinf75d09f2020-01-16 11:19:52 -0800657 int mtu = in.readInt();
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800658
Sarah Chinf75d09f2020-01-16 11:19:52 -0800659 return new RouteInfo(dest, gateway, iface, type, mtu);
Robert Greenwalt5a901292011-04-28 14:28:50 -0700660 }
661
662 public RouteInfo[] newArray(int size) {
663 return new RouteInfo[size];
664 }
665 };
Robert Greenwalt5a901292011-04-28 14:28:50 -0700666}