RouteInfo.java revision ca441ee2f0d53c3d3a00b2a9aa96c064378fd535
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;
28f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
29aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt/**
30aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * A simple container for route information.
31aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt *
3245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * In order to be used, a route must have a destination prefix and:
3345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti *
3445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * - A gateway address (next-hop, for gatewayed routes), or
3545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * - An interface (for directly-connected routes), or
3645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * - Both a gateway and an interface.
3745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti *
3845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * This class does not enforce these constraints because there is code that
3945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * uses RouteInfo objects to store directly-connected routes without interfaces.
4045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * Such objects cannot be used directly, but can be put into a LinkProperties
4145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti * object which then specifies the interface.
4245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti *
43aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * @hide
44aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt */
45aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltpublic class RouteInfo implements Parcelable {
46aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    /**
47aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     * The IP destination address for this route.
48aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     */
49aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final LinkAddress mDestination;
50aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
51aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    /**
52aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     * The gateway address for this route.
53aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     */
54aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final InetAddress mGateway;
55aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
5645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    /**
5745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * The interface for this route.
5845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     */
5945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    private final String mInterface;
6045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
61aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final boolean mIsDefault;
620a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private final boolean mIsHost;
63ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    private final boolean mHasGateway;
64aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
6545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    /**
6645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * Constructs a RouteInfo object.
6745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
68574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * If destination is null, then gateway must be specified and the
6945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
7045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * if @gateway is an instance of {@link Inet4Address}, or the IPv6 default
71574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * route <code>::/0</code> if gateway is an instance of
7245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * {@link Inet6Address}.
7345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
74574b00a3621d1e6db560ea2f4593a0ae7a90e145Lorenzo Colitti     * destination and gateway may not both be null.
7545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
7645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param destination the destination prefix
7745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param gateway the IP address to route packets through
7845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param iface the interface name to send packets on
7945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     */
8045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
81aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (destination == null) {
8259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (gateway != null) {
8359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (gateway instanceof Inet4Address) {
8459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    destination = new LinkAddress(Inet4Address.ANY, 0);
85aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } else {
8659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    destination = new LinkAddress(Inet6Address.ANY, 0);
87aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                }
8859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            } else {
8959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                // no destination, no gateway. invalid.
9045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
9145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                                                   destination);
9259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
93aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
948c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        if (gateway == null) {
958c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            if (destination.getAddress() instanceof Inet4Address) {
968c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet4Address.ANY;
978c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            } else {
988c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet6Address.ANY;
998c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            }
1008c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        }
101ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt        mHasGateway = (!gateway.isAnyLocalAddress());
102ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt
103f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
104f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
105aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        mGateway = gateway;
10645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        mInterface = iface;
107aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        mIsDefault = isDefault();
1080a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        mIsHost = isHost();
109aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
110aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
11145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway) {
11245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(destination, gateway, null);
11345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
11445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
115aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public RouteInfo(InetAddress gateway) {
11645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(null, gateway, null);
117aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
118aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1194717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    public RouteInfo(LinkAddress host) {
12045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(host, null, null);
1214717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    }
1224717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
123e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti    public static RouteInfo makeHostRoute(InetAddress host, String iface) {
124e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti        return makeHostRoute(host, null, iface);
12559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
12659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
127e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti    public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
12859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host == null) return null;
12959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
13059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host instanceof Inet4Address) {
131e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti            return new RouteInfo(new LinkAddress(host, 32), gateway, iface);
13259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } else {
133e16713597661c326d2bb6586a8b13e27520c4227Lorenzo Colitti            return new RouteInfo(new LinkAddress(host, 128), gateway, iface);
13459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
13559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
13659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
1370a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private boolean isHost() {
138fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti        return (mDestination.getAddress() instanceof Inet4Address &&
139fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti                mDestination.getNetworkPrefixLength() == 32) ||
140fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti               (mDestination.getAddress() instanceof Inet6Address &&
141fdadc4e242d987c09007df274e01fe678a82331fLorenzo Colitti                mDestination.getNetworkPrefixLength() == 128);
1420a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
1430a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
144aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private boolean isDefault() {
145aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        boolean val = false;
146aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway != null) {
147aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (mGateway instanceof Inet4Address) {
148f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
149aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            } else {
150f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
151aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
152aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
153aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return val;
154aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
155aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1560a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
157aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public LinkAddress getDestination() {
158aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mDestination;
159aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
160aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
161aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public InetAddress getGateway() {
162aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mGateway;
163aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
164aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
16545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public String getInterface() {
16645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return mInterface;
16745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
16845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
169aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public boolean isDefaultRoute() {
170aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mIsDefault;
171aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
172aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1730a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public boolean isHostRoute() {
1740a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return mIsHost;
1750a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
1760a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
177ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    public boolean hasGateway() {
178ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt        return mHasGateway;
179ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt    }
180ca441ee2f0d53c3d3a00b2a9aa96c064378fd535Robert Greenwalt
181aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public String toString() {
182aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        String val = "";
183aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mDestination != null) val = mDestination.toString();
184aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway != null) val += " -> " + mGateway.getHostAddress();
185aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return val;
186aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
187aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
188aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public int describeContents() {
189aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return 0;
190aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
191aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
192aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
193aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mDestination == null) {
194aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 0);
195aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        } else {
196aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 1);
197aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByteArray(mDestination.getAddress().getAddress());
198aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeInt(mDestination.getNetworkPrefixLength());
199aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
200aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
201aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway == null) {
202aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 0);
203aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        } else {
204aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 1);
205aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByteArray(mGateway.getAddress());
206aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
20745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
20845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        dest.writeString(mInterface);
209aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
210aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
211be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    @Override
212be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public boolean equals(Object obj) {
213be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (this == obj) return true;
214be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
215be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (!(obj instanceof RouteInfo)) return false;
216be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
217be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        RouteInfo target = (RouteInfo) obj;
218be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
219be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        boolean sameDestination = ( mDestination == null) ?
220be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                target.getDestination() == null
221be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                : mDestination.equals(target.getDestination());
222be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
223be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        boolean sameAddress = (mGateway == null) ?
224be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                target.getGateway() == null
225be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                : mGateway.equals(target.getGateway());
226be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
22745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        boolean sameInterface = (mInterface == null) ?
22845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                target.getInterface() == null
22945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                : mInterface.equals(target.getInterface());
23045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
23145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return sameDestination && sameAddress && sameInterface
232be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            && mIsDefault == target.mIsDefault;
233be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
234be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
235be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    @Override
236be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public int hashCode() {
23745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return (mDestination == null ? 0 : mDestination.hashCode() * 41)
23845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            + (mGateway == null ? 0 :mGateway.hashCode() * 47)
23945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            + (mInterface == null ? 0 :mInterface.hashCode() * 67)
240be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            + (mIsDefault ? 3 : 7);
241be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
242be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
243aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public static final Creator<RouteInfo> CREATOR =
244aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        new Creator<RouteInfo>() {
245aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo createFromParcel(Parcel in) {
246aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            InetAddress destAddr = null;
247aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            int prefix = 0;
248aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            InetAddress gateway = null;
249aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
250aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (in.readByte() == 1) {
251aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                byte[] addr = in.createByteArray();
252aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                prefix = in.readInt();
253aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
254aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                try {
255aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    destAddr = InetAddress.getByAddress(addr);
256aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } catch (UnknownHostException e) {}
257aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
258aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
259aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (in.readByte() == 1) {
260aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                byte[] addr = in.createByteArray();
261aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
262aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                try {
263aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    gateway = InetAddress.getByAddress(addr);
264aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } catch (UnknownHostException e) {}
265aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
266aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
26745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String iface = in.readString();
26845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
269aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            LinkAddress dest = null;
270aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
271aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (destAddr != null) {
272aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                dest = new LinkAddress(destAddr, prefix);
273aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
274aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
27545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            return new RouteInfo(dest, gateway, iface);
276aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
277aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
278aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo[] newArray(int size) {
279aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            return new RouteInfo[size];
280aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
281aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    };
282f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
28345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    protected boolean matches(InetAddress destination) {
284f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if (destination == null) return false;
285f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
286f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // match the route destination and destination with prefix length
287f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
288f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                mDestination.getNetworkPrefixLength());
289f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
290f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        return mDestination.getAddress().equals(dstNet);
291f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    }
292f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
293f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    /**
294f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * Find the route from a Collection of routes that best matches a given address.
295f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * May return null if no routes are applicable.
296f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @param routes a Collection of RouteInfos to chose from
297f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @param dest the InetAddress your trying to get to
298f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @return the RouteInfo from the Collection that best fits the given address
299f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     */
300f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
301f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if ((routes == null) || (dest == null)) return null;
302f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
303f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        RouteInfo bestRoute = null;
304f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // pick a longest prefix match under same address type
305f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        for (RouteInfo route : routes) {
306f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
307f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                if ((bestRoute != null) &&
308f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                        (bestRoute.mDestination.getNetworkPrefixLength() >=
309f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                        route.mDestination.getNetworkPrefixLength())) {
310f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                    continue;
311f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                }
312f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                if (route.matches(dest)) bestRoute = route;
313f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt            }
314f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        }
315f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        return bestRoute;
316f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    }
317aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt}
318