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
654b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
664b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /** Unicast route. @hide */
674b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public static final int RTN_UNICAST = 1;
684b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
694b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /** Unreachable route. @hide */
704b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public static final int RTN_UNREACHABLE = 7;
714b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
724b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /** Throw route. @hide */
734b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public static final int RTN_THROW = 9;
744b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
754b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /**
764b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     * The type of this route; one of the RTN_xxx constants above.
774b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     */
784b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    private final int mType;
794b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
804b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    // Derived data members.
814b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    // TODO: remove these.
820a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private final boolean mIsHost;
83ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    private final boolean mHasGateway;
84aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
8545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    /**
8645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * Constructs a RouteInfo object.
8745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
88574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * If destination is null, then gateway must be specified and the
8945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
904095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
91574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * route <code>::/0</code> if gateway is an instance of
9245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * {@link Inet6Address}.
93386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * <p>
94574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * destination and gateway may not both be null.
9545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
9645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param destination the destination prefix
9745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param gateway the IP address to route packets through
9845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param iface the interface name to send packets on
99cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
100cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
101cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
1024b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public RouteInfo(IpPrefix destination, InetAddress gateway, String iface, int type) {
1034b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        switch (type) {
1044b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            case RTN_UNICAST:
1054b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            case RTN_UNREACHABLE:
1064b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            case RTN_THROW:
1074b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // TODO: It would be nice to ensure that route types that don't have nexthops or
1084b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // interfaces, such as unreachable or throw, can't be created if an interface or
1094b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // a gateway is specified. This is a bit too complicated to do at the moment
1104b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // because:
1114b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                //
1124b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // - LinkProperties sets the interface on routes added to it, and modifies the
1134b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                //   interfaces of all the routes when its interface name changes.
1144b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // - Even when the gateway is null, we store a non-null gateway here.
1154b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                //
1164b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                // For now, we just rely on the code that sets routes to do things properly.
1174b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                break;
1184b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            default:
1194b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                throw new IllegalArgumentException("Unknown route type " + type);
1204b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        }
1214b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
122aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (destination == null) {
12359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (gateway != null) {
12459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (gateway instanceof Inet4Address) {
1251806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                    destination = new IpPrefix(Inet4Address.ANY, 0);
126aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } else {
1271806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                    destination = new IpPrefix(Inet6Address.ANY, 0);
128aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                }
12959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            } else {
13059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                // no destination, no gateway. invalid.
13145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
13245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                                                   destination);
13359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
134aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
1351806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and
1361806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        // matches the documented behaviour. Before we can do this we need to fix all callers (e.g.,
1371806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        // ConnectivityService) to stop doing things like r.getGateway().equals(), ... .
1388c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        if (gateway == null) {
1398c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            if (destination.getAddress() instanceof Inet4Address) {
1408c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet4Address.ANY;
1418c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            } else {
1428c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet6Address.ANY;
1438c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            }
1448c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        }
145ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt        mHasGateway = (!gateway.isAnyLocalAddress());
146ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt
147386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt        if ((destination.getAddress() instanceof Inet4Address &&
148386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                 (gateway instanceof Inet4Address == false)) ||
149386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                (destination.getAddress() instanceof Inet6Address &&
150386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                 (gateway instanceof Inet6Address == false))) {
151386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt            throw new IllegalArgumentException("address family mismatch in RouteInfo constructor");
152386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt        }
1531806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        mDestination = destination;  // IpPrefix objects are immutable.
1541806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        mGateway = gateway;          // InetAddress objects are immutable.
1551806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        mInterface = iface;          // Strings are immutable.
1564b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        mType = type;
1570a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        mIsHost = isHost();
158aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
159aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1604095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
1614b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     *  @hide
1624b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     */
1634b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
1644b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        this(destination, gateway, iface, RTN_UNICAST);
1654b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    }
1664b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
1674b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /**
1681806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti     * @hide
1691806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti     */
1701806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
1711806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        this(destination == null ? null :
1721806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
1731806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                gateway, iface);
1741806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    }
1751806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti
1761806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti    /**
1774095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Constructs a {@code RouteInfo} object.
1784095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
1794095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * If destination is null, then gateway must be specified and the
1804095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
1814095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
1824095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
1834095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * <p>
1844095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Destination and gateway may not both be null.
1854095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
186cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @param destination the destination address and prefix in an {@link IpPrefix}
1874095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param gateway the {@link InetAddress} to route packets through
188cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
189cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
190cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
191cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public RouteInfo(IpPrefix destination, InetAddress gateway) {
192cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        this(destination, gateway, null);
193cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    }
194cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran
195cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
196cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
1974b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     *
1984b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     * TODO: Remove this.
1994095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
20045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway) {
20145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(destination, gateway, null);
20245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
20345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
2044095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2054095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Constructs a default {@code RouteInfo} object.
2064095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
2074095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param gateway the {@link InetAddress} to route packets through
208cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
209cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
2104095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
211aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public RouteInfo(InetAddress gateway) {
2121806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        this((IpPrefix) null, gateway, null);
213aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
214aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
2154095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2164095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Constructs a {@code RouteInfo} object representing a direct connected subnet.
2174095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
218cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @param destination the {@link IpPrefix} describing the address and prefix
219386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     *                    length of the subnet.
220cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *
221cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
222cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
223cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public RouteInfo(IpPrefix destination) {
224cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran        this(destination, null, null);
225cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    }
226cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran
227cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
228cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
2294095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
230386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt    public RouteInfo(LinkAddress destination) {
231386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt        this(destination, null, null);
2324717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    }
2334717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
2344095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2354095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @hide
2364095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
2374b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public RouteInfo(IpPrefix destination, int type) {
2384b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        this(destination, null, null, type);
2394b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    }
2404b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
2414b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /**
2424b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     * @hide
2434b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     */
244e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti    public static RouteInfo makeHostRoute(InetAddress host, String iface) {
245e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti        return makeHostRoute(host, null, iface);
24659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
24759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
2484095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2494095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @hide
2504095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
251e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti    public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
25259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host == null) return null;
25359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
25459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host instanceof Inet4Address) {
2551806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            return new RouteInfo(new IpPrefix(host, 32), gateway, iface);
25659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } else {
2571806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            return new RouteInfo(new IpPrefix(host, 128), gateway, iface);
25859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
25959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
26059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
2610a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private boolean isHost() {
262fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti        return (mDestination.getAddress() instanceof Inet4Address &&
2637dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                mDestination.getPrefixLength() == 32) ||
264fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti               (mDestination.getAddress() instanceof Inet6Address &&
2657dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                mDestination.getPrefixLength() == 128);
2660a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
2670a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
2684095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
269cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
2704095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
271cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @return {@link IpPrefix} specifying the destination.  This is never {@code null}.
272cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
273cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public IpPrefix getDestination() {
2741806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        return mDestination;
275cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    }
276cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran
277cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
278cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * TODO: Convert callers to use IpPrefix and then remove.
279cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @hide
2804095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
281cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    public LinkAddress getDestinationLinkAddress() {
2821806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
283aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
284aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
2854095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
2864095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Retrieves the gateway or next hop {@link InetAddress} for this route.
2874095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
288386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @return {@link InetAddress} specifying the gateway or next hop.  This may be
289e595b97ff470a5e92151350e4d7b4173032fde23Robert Greenwalt     *                             {@code null} for a directly-connected route."
2904095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
291aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public InetAddress getGateway() {
292aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mGateway;
293aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
294aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
2954095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
296386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * Retrieves the interface used for this route if specified, else {@code null}.
2974095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
2984095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @return The name of the interface used for this route.
2994095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
30045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public String getInterface() {
30145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return mInterface;
30245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
30345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
3044095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3054b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     * Retrieves the type of this route.
3064b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     *
3074b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
3084b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     *
3094b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     * @hide
3104b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti     */
3114b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    public int getType() {
3124b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        return mType;
3134b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    }
3144b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti
3154b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti    /**
3164095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Indicates if this route is a default route (ie, has no destination specified).
3174095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
318386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @return {@code true} if the destination has a prefix length of 0.
3194095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
320aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public boolean isDefaultRoute() {
3214b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
32264c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    }
32364c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti
32464c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    /**
32564c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * Indicates if this route is an IPv4 default route.
32664c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * @hide
32764c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     */
32864c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    public boolean isIPv4Default() {
32964c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address;
33064c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    }
33164c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti
33264c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    /**
33364c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * Indicates if this route is an IPv6 default route.
33464c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     * @hide
33564c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti     */
33664c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti    public boolean isIPv6Default() {
33764c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address;
338aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
339aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
3404095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3414095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Indicates if this route is a host route (ie, matches only a single host address).
3424095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
343cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
344cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * respectively.
345386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @hide
3464095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
3470a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public boolean isHostRoute() {
3480a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return mIsHost;
3490a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
3500a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
3514095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3524095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Indicates if this route has a next hop ({@code true}) or is directly-connected
3534095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * ({@code false}).
3544095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
3554095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @return {@code true} if a gateway is specified
356386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @hide
3574095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
358ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    public boolean hasGateway() {
359ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt        return mHasGateway;
360ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    }
361ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt
3624095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
363386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * Determines whether the destination and prefix of this route includes the specified
364386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * address.
365386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     *
366386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @param destination A {@link InetAddress} to test to see if it would match this route.
367386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt     * @return {@code true} if the destination and prefix length cover the given address.
3684095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
369386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt    public boolean matches(InetAddress destination) {
370acc8c09d3a12d00b565a76acc26061172c3dd3c6Erik Kline        return mDestination.contains(destination);
371aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
372aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
3734095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
3744095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Find the route from a Collection of routes that best matches a given address.
3754095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * May return null if no routes are applicable.
3764095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param routes a Collection of RouteInfos to chose from
3774095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @param dest the InetAddress your trying to get to
3784095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @return the RouteInfo from the Collection that best fits the given address
3794095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     *
3804095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * @hide
3814095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
3824095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
3834095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        if ((routes == null) || (dest == null)) return null;
384aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
3854095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        RouteInfo bestRoute = null;
3864095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        // pick a longest prefix match under same address type
3874095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        for (RouteInfo route : routes) {
3884095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
3894095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                if ((bestRoute != null) &&
3907dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                        (bestRoute.mDestination.getPrefixLength() >=
3917dc78cf3af9fd11a4f1e2e981ce584a23755ea9eLorenzo Colitti                        route.mDestination.getPrefixLength())) {
3924095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                    continue;
3934095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                }
3944095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                if (route.matches(dest)) bestRoute = route;
3954095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt            }
396aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
3974095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return bestRoute;
3984095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    }
39945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
400cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
401cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Returns a human-readable description of this object.
402cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
4034095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public String toString() {
4044095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        String val = "";
4054095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        if (mDestination != null) val = mDestination.toString();
4064b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        if (mType == RTN_UNREACHABLE) {
4074b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            val += " unreachable";
4084b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        } else if (mType == RTN_THROW) {
4094b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            val += " throw";
4104b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        } else {
4114b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            val += " ->";
4124b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            if (mGateway != null) val += " " + mGateway.getHostAddress();
4134b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            if (mInterface != null) val += " " + mInterface;
4144b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            if (mType != RTN_UNICAST) {
4154b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                val += " unknown type " + mType;
4164b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            }
4174b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        }
4184095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return val;
419aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
420aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
421cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
422cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * Compares this RouteInfo object against the specified object and indicates if they are equal.
423cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     * @return {@code true} if the objects are equal, {@code false} otherwise.
424cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
425be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public boolean equals(Object obj) {
426be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (this == obj) return true;
427be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
428be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (!(obj instanceof RouteInfo)) return false;
429be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
430be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        RouteInfo target = (RouteInfo) obj;
431be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
4321806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        return Objects.equals(mDestination, target.getDestination()) &&
433386aba8bd1c83bb8c088b8dd7b2024ba77c9c36cRobert Greenwalt                Objects.equals(mGateway, target.getGateway()) &&
4344b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                Objects.equals(mInterface, target.getInterface()) &&
4354b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                mType == target.getType();
436be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
437be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
438cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran    /**
439cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     *  Returns a hashcode for this <code>RouteInfo</code> object.
440cc91c7b804a079f7b20404827277c61dd403805fSreeram Ramachandran     */
441be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public int hashCode() {
44264c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti        return (mDestination.hashCode() * 41)
4434095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt                + (mGateway == null ? 0 :mGateway.hashCode() * 47)
4444b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                + (mInterface == null ? 0 :mInterface.hashCode() * 67)
4454b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti                + (mType * 71);
446be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
447be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
4484095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
4494095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Implement the Parcelable interface
4504095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
4514095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public int describeContents() {
4524095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        return 0;
4534095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    }
4544095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt
4554095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
4564095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Implement the Parcelable interface
4574095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
4584095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
4591806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        dest.writeParcelable(mDestination, flags);
4601806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
4611806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti        dest.writeByteArray(gatewayBytes);
4624095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt        dest.writeString(mInterface);
4634b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti        dest.writeInt(mType);
4644095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    }
4654095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt
4664095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt    /**
4674095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     * Implement the Parcelable interface.
4684095bd5a8811d4d8c2bb0efc28d9610629e27c89Robert Greenwalt     */
469aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public static final Creator<RouteInfo> CREATOR =
470aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        new Creator<RouteInfo>() {
471aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo createFromParcel(Parcel in) {
4721806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            IpPrefix dest = in.readParcelable(null);
473aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
4741806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti            InetAddress gateway = null;
47564c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti            byte[] addr = in.createByteArray();
47664c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti            try {
4771806b1fc25bcffaa005e72a55042031a42b168b1Lorenzo Colitti                gateway = InetAddress.getByAddress(addr);
47864c43b1948a2b2fcd692cd4a48f031efbf7f7336Lorenzo Colitti            } catch (UnknownHostException e) {}
479aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
48045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String iface = in.readString();
4814b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            int type = in.readInt();
48245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
4834b0f8e6fb707e19799011c1f4a5e4f54603e34b1Lorenzo Colitti            return new RouteInfo(dest, gateway, iface, type);
484aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
485aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
486aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo[] newArray(int size) {
487aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            return new RouteInfo[size];
488aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
489aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    };
490aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt}
491