RouteInfo.java revision 1806b1fc25bcffaa005e72a55042031a42b168b1
1aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt/*
2aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * Copyright (C) 2011 The Android Open Source Project
3aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt *
4aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
5aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * you may not use this file except in compliance with the License.
6aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * You may obtain a copy of the License at
7aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt *
8aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
9aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt *
10aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * Unless required by applicable law or agreed to in writing, software
11aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
12aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * See the License for the specific language governing permissions and
14aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * limitations under the License.
15aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt */
16aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
17aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltpackage android.net;
18aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
19aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport android.os.Parcel;
20aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport android.os.Parcelable;
21aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
22aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport java.net.UnknownHostException;
23aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport java.net.InetAddress;
24aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport java.net.Inet4Address;
25aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport java.net.Inet6Address;
26f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
27f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwaltimport java.util.Collection;
28386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwaltimport java.util.Objects;
29f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
30aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt/**
31386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * Represents a network route.
324095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt * <p>
334095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt * This is used both to describe static network configuration and live network
34386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * configuration information.
35aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt *
36386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * A route contains three pieces of information:
374095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt * <ul>
38cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route.
39cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran *     If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6)
40386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt *     implied by the gateway IP address.
41cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran * <li>a gateway {@link InetAddress} indicating the next hop to use.  If this is {@code null} it
42386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt *     indicates a directly-connected route.
43386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * <li>an interface (which may be unspecified).
444095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt * </ul>
45386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * Either the destination or the gateway may be {@code null}, but not both.  If the
46386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * destination and gateway are both specified, they must be of the same address family
47386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt * (IPv4 or IPv6).
48aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt */
49e595b97ff470a5e92151350e4d7b4173032fde23Robert Greenwaltpublic final class RouteInfo implements Parcelable {
50aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    /**
51aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     * The IP destination address for this route.
52aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     */
531806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    private final IpPrefix mDestination;
54aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
55aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    /**
56aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     * The gateway address for this route.
57aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     */
58aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final InetAddress mGateway;
59aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
6045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    /**
6145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * The interface for this route.
6245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     */
6345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    private final String mInterface;
6445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
650a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private final boolean mIsHost;
66ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    private final boolean mHasGateway;
67aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
6845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    /**
6945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * Constructs a RouteInfo object.
7045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
71574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * If destination is null, then gateway must be specified and the
7245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
734095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
74574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * route <code>::/0</code> if gateway is an instance of
7545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * {@link Inet6Address}.
76386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * <p>
77574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * destination and gateway may not both be null.
7845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
7945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param destination the destination prefix
8045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param gateway the IP address to route packets through
8145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param iface the interface name to send packets on
82cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
83cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
84cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
85cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
86aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (destination == null) {
8759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (gateway != null) {
8859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (gateway instanceof Inet4Address) {
891806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                    destination = new IpPrefix(Inet4Address.ANY, 0);
90aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } else {
911806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                    destination = new IpPrefix(Inet6Address.ANY, 0);
92aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                }
9359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            } else {
9459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                // no destination, no gateway. invalid.
9545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
9645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                                                   destination);
9759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
98aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
991806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
1001806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
1011806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
1028c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        if (gateway == null) {
1038c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            if (destination.getAddress() instanceof Inet4Address) {
1048c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet4Address.ANY;
1058c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            } else {
1068c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet6Address.ANY;
1078c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            }
1088c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        }
109ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt        mHasGateway = (!gateway.isAnyLocalAddress());
110ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt
111386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt        if ((destination.getAddress() instanceof Inet4Address &&
112386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                 (gateway instanceof Inet4Address == false)) ||
113386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                (destination.getAddress() instanceof Inet6Address &&
114386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                 (gateway instanceof Inet6Address == false))) {
115386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt            throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
116386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt        }
1171806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        mDestination = destination;  // IpPrefix objects are immutable.
1181806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        mGateway = gateway;          // InetAddress objects are immutable.
1191806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        mInterface = iface;          // Strings are immutable.
1200a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        mIsHost = isHost();
121aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
122aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1234095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
1241806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti     * @hide
1251806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti     */
1261806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
1271806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        this(destination == null ? null :
1281806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
1291806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                gateway, iface);
1301806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    }
1311806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti
1321806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    /**
1334095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Constructs a {@code RouteInfo} object.
1344095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
1354095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * If destination is null, then gateway must be specified and the
1364095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
1374095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
1384095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
1394095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * <p>
1404095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Destination and gateway may not both be null.
1414095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
142cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @param destination the destination address and prefix in an {@link IpPrefix}
1434095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param gateway the {@link InetAddress} to route packets through
144cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
145cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
146cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
147cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public RouteInfo(IpPrefix destination, InetAddress gateway) {
148cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        this(destination, gateway, null);
149cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    }
150cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran
151cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
152cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
1534095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
15445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway) {
15545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(destination, gateway, null);
15645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
15745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
1584095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
1594095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Constructs a default {@code RouteInfo} object.
1604095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
1614095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param gateway the {@link InetAddress} to route packets through
162cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
163cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
1644095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
165aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public RouteInfo(InetAddress gateway) {
1661806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        this((IpPrefix) null, gateway, null);
167aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
168aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1694095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
1704095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Constructs a {@code RouteInfo} object representing a direct connected subnet.
1714095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
172cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @param destination the {@link IpPrefix} describing the address and prefix
173386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     *                    length of the subnet.
174cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
175cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
176cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
177cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public RouteInfo(IpPrefix destination) {
178cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        this(destination, null, null);
179cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    }
180cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran
181cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
182cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
1834095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
184386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt    public RouteInfo(LinkAddress destination) {
185386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt        this(destination, null, null);
1864717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    }
1874717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
1884095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
1894095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @hide
1904095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
191e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti    public static RouteInfo makeHostRoute(InetAddress host, String iface) {
192e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti        return makeHostRoute(host, null, iface);
19359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
19459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
1954095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
1964095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @hide
1974095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
198e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti    public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
19959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host == null) return null;
20059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
20159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host instanceof Inet4Address) {
2021806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
20359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } else {
2041806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
20559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
20659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
20759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
2080a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private boolean isHost() {
209fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti        return (mDestination.getAddress() instanceof Inet4Address &&
2107dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                mDestination.getPrefixLength() == 32) ||
211fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti               (mDestination.getAddress() instanceof Inet6Address &&
2127dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                mDestination.getPrefixLength() == 128);
2130a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
2140a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
2154095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
216cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
2174095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
218cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @return {@link IpPrefix} specifying the destination.  This is never {@code null}.
219cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
220cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public IpPrefix getDestination() {
2211806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        return mDestination;
222cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    }
223cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran
224cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
225cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * TODO: Convert callers to use IpPrefix and then remove.
226cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
2274095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
228cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public LinkAddress getDestinationLinkAddress() {
2291806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
230aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
231aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
2324095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2334095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Retrieves the gateway or next hop {@link InetAddress} for this route.
2344095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
235386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @return {@link InetAddress} specifying the gateway or next hop.  This may be
236e595b97ff470a5e92151350e4d7b4173032fde23Robert Greenwalt     *                             {@code null} for a directly-connected route."
2374095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
238aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public InetAddress getGateway() {
239aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mGateway;
240aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
241aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
2424095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
243386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * Retrieves the interface used for this route if specified, else {@code null}.
2444095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
2454095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @return The name of the interface used for this route.
2464095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
24745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public String getInterface() {
24845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return mInterface;
24945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
25045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
2514095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2524095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Indicates if this route is a default route (ie, has no destination specified).
2534095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
254386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @return {@code true} if the destination has a prefix length of 0.
2554095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
256aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public boolean isDefaultRoute() {
25764c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return mDestination.getPrefixLength() == 0;
25864c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    }
25964c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti
26064c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    /**
26164c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * Indicates if this route is an IPv4 default route.
26264c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * @hide
26364c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     */
26464c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    public boolean isIPv4Default() {
26564c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
26664c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    }
26764c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti
26864c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    /**
26964c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * Indicates if this route is an IPv6 default route.
27064c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * @hide
27164c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     */
27264c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    public boolean isIPv6Default() {
27364c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
274aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
275aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
2764095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2774095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Indicates if this route is a host route (ie, matches only a single host address).
2784095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
279cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
280cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * respectively.
281386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @hide
2824095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
2830a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public boolean isHostRoute() {
2840a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return mIsHost;
2850a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
2860a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
2874095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2884095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Indicates if this route has a next hop ({@code true}) or is directly-connected
2894095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * ({@code false}).
2904095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
2914095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @return {@code true} if a gateway is specified
292386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @hide
2934095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
294ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    public boolean hasGateway() {
295ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt        return mHasGateway;
296ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    }
297ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt
2984095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
299386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * Determines whether the destination and prefix of this route includes the specified
300386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * address.
301386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     *
302386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @param destination A {@link InetAddress} to test to see if it would match this route.
303386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @return {@code true} if the destination and prefix length cover the given address.
3044095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
305386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt    public boolean matches(InetAddress destination) {
3064095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        if (destination == null) return false;
307aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
3084095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        // match the route destination and destination with prefix length
3094095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
3107dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                mDestination.getPrefixLength());
3114095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt
3124095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return mDestination.getAddress().equals(dstNet);
313aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
314aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
3154095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3164095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Find the route from a Collection of routes that best matches a given address.
3174095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * May return null if no routes are applicable.
3184095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param routes a Collection of RouteInfos to chose from
3194095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param dest the InetAddress your trying to get to
3204095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @return the RouteInfo from the Collection that best fits the given address
3214095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
3224095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @hide
3234095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
3244095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
3254095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        if ((routes == null) || (dest == null)) return null;
326aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
3274095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        RouteInfo bestRoute = null;
3284095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        // pick a longest prefix match under same address type
3294095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        for (RouteInfo route : routes) {
3304095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
3314095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                if ((bestRoute != null) &&
3327dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                        (bestRoute.mDestination.getPrefixLength() >=
3337dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                        route.mDestination.getPrefixLength())) {
3344095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                    continue;
3354095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                }
3364095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                if (route.matches(dest)) bestRoute = route;
3374095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt            }
338aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
3394095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return bestRoute;
3404095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    }
34145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
342cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
343cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Returns a human-readable description of this object.
344cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
3454095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public String toString() {
3464095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        String val = "";
3474095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        if (mDestination != null) val = mDestination.toString();
348cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        val += " ->";
349cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        if (mGateway != null) val += " " + mGateway.getHostAddress();
350cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        if (mInterface != null) val += " " + mInterface;
3514095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return val;
352aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
353aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
354cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
355cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Compares this RouteInfo object against the specified object and indicates if they are equal.
356cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @return {@code true} if the objects are equal, {@code false} otherwise.
357cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
358be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public boolean equals(Object obj) {
359be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (this == obj) return true;
360be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
361be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (!(obj instanceof RouteInfo)) return false;
362be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
363be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        RouteInfo target = (RouteInfo) obj;
364be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
3651806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        return Objects.equals(mDestination, target.getDestination()) &&
366386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                Objects.equals(mGateway, target.getGateway()) &&
367386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                Objects.equals(mInterface, target.getInterface());
368be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
369be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
370cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
371cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *  Returns a hashcode for this <code>RouteInfo</code> object.
372cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
373be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public int hashCode() {
37464c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return (mDestination.hashCode() * 41)
3754095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                + (mGateway == null ? 0 :mGateway.hashCode() * 47)
37664c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti                + (mInterface == null ? 0 :mInterface.hashCode() * 67);
377be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
378be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
3794095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3804095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Implement the Parcelable interface
3814095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
3824095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public int describeContents() {
3834095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return 0;
3844095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    }
3854095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt
3864095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3874095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Implement the Parcelable interface
3884095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
3894095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
3901806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        dest.writeParcelable(mDestination, flags);
3911806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
3921806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        dest.writeByteArray(gatewayBytes);
3934095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        dest.writeString(mInterface);
3944095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    }
3954095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt
3964095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3974095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Implement the Parcelable interface.
3984095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
399aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public static final Creator<RouteInfo> CREATOR =
400aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        new Creator<RouteInfo>() {
401aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo createFromParcel(Parcel in) {
4021806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            IpPrefix dest = in.readParcelable(null);
403aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
4041806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            InetAddress gateway = null;
40564c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti            byte[] addr = in.createByteArray();
40664c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti            try {
4071806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                gateway = InetAddress.getByAddress(addr);
40864c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti            } catch (UnknownHostException e) {}
409aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
41045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String iface = in.readString();
41145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
41245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            return new RouteInfo(dest, gateway, iface);
413aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
414aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
415aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo[] newArray(int size) {
416aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            return new RouteInfo[size];
417aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
418aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    };
419aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt}
420