RouteInfo.java revision 45b9a5bb93569ca49bbd44f7a518091371687f96
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;
63aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
6445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    /**
6545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * Constructs a RouteInfo object.
6645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
6745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * If @destination is null, then @gateway must be specified and the
6845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * constructed route is either the IPv4 default route <code>0.0.0.0</code>
6945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * if @gateway is an instance of {@link Inet4Address}, or the IPv6 default
7045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * route <code>::/0</code> if @gateway is an instance of
7145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * {@link Inet6Address}.
7245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
7345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @destination and @gateway may not both be null.
7445b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     *
7545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param destination the destination prefix
7645b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param gateway the IP address to route packets through
7745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     * @param iface the interface name to send packets on
7845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti     */
7945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
80aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (destination == null) {
8159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            if (gateway != null) {
8259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                if (gateway instanceof Inet4Address) {
8359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    destination = new LinkAddress(Inet4Address.ANY, 0);
84aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } else {
8559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                    destination = new LinkAddress(Inet6Address.ANY, 0);
86aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                }
8759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            } else {
8859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt                // no destination, no gateway. invalid.
8945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," +
9045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                                                   destination);
9159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            }
92aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
938c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        if (gateway == null) {
948c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            if (destination.getAddress() instanceof Inet4Address) {
958c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet4Address.ANY;
968c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            } else {
978c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet6Address.ANY;
988c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            }
998c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        }
100f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
101f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
102aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        mGateway = gateway;
10345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        mInterface = iface;
104aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        mIsDefault = isDefault();
1050a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        mIsHost = isHost();
106aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
107aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
10845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public RouteInfo(LinkAddress destination, InetAddress gateway) {
10945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(destination, gateway, null);
11045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
11145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
112aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public RouteInfo(InetAddress gateway) {
11345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(null, gateway, null);
114aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
115aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1164717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    public RouteInfo(LinkAddress host) {
11745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        this(host, null, null);
1184717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt    }
1194717c261b2c670d5c0925e3527a864aa52db6ac0Robert Greenwalt
12059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public static RouteInfo makeHostRoute(InetAddress host) {
12159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        return makeHostRoute(host, null);
12259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
12359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
12459b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway) {
12559b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host == null) return null;
12659b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
12759b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        if (host instanceof Inet4Address) {
12859b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            return new RouteInfo(new LinkAddress(host, 32), gateway);
12959b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        } else {
13059b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt            return new RouteInfo(new LinkAddress(host, 128), gateway);
13159b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt        }
13259b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt    }
13359b1a4ede7032c1b4d897e13dd4ede09b5e14743Robert Greenwalt
1340a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    private boolean isHost() {
1350a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return (mGateway.equals(Inet4Address.ANY) || mGateway.equals(Inet6Address.ANY));
1360a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
1370a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
138aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private boolean isDefault() {
139aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        boolean val = false;
140aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway != null) {
141aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (mGateway instanceof Inet4Address) {
142f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
143aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            } else {
144f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
145aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
146aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
147aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return val;
148aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
149aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1500a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
151aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public LinkAddress getDestination() {
152aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mDestination;
153aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
154aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
155aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public InetAddress getGateway() {
156aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mGateway;
157aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
158aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
15945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    public String getInterface() {
16045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return mInterface;
16145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    }
16245b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
163aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public boolean isDefaultRoute() {
164aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mIsDefault;
165aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
166aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
1670a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    public boolean isHostRoute() {
1680a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt        return mIsHost;
1690a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt    }
1700a46db5d88461d9a6c85bb2e95982ac4c511d57eRobert Greenwalt
171aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public String toString() {
172aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        String val = "";
173aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mDestination != null) val = mDestination.toString();
174aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway != null) val += " -> " + mGateway.getHostAddress();
175aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return val;
176aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
177aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
178aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public int describeContents() {
179aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return 0;
180aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
181aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
182aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
183aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mDestination == null) {
184aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 0);
185aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        } else {
186aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 1);
187aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByteArray(mDestination.getAddress().getAddress());
188aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeInt(mDestination.getNetworkPrefixLength());
189aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
190aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
191aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway == null) {
192aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 0);
193aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        } else {
194aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 1);
195aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByteArray(mGateway.getAddress());
196aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
19745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
19845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        dest.writeString(mInterface);
199aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
200aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
201be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    @Override
202be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public boolean equals(Object obj) {
203be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (this == obj) return true;
204be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
205be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (!(obj instanceof RouteInfo)) return false;
206be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
207be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        RouteInfo target = (RouteInfo) obj;
208be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
209be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        boolean sameDestination = ( mDestination == null) ?
210be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                target.getDestination() == null
211be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                : mDestination.equals(target.getDestination());
212be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
213be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        boolean sameAddress = (mGateway == null) ?
214be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                target.getGateway() == null
215be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                : mGateway.equals(target.getGateway());
216be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
21745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        boolean sameInterface = (mInterface == null) ?
21845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                target.getInterface() == null
21945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti                : mInterface.equals(target.getInterface());
22045b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
22145b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return sameDestination && sameAddress && sameInterface
222be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            && mIsDefault == target.mIsDefault;
223be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
224be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
225be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    @Override
226be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public int hashCode() {
22745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti        return (mDestination == null ? 0 : mDestination.hashCode() * 41)
22845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            + (mGateway == null ? 0 :mGateway.hashCode() * 47)
22945b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            + (mInterface == null ? 0 :mInterface.hashCode() * 67)
230be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            + (mIsDefault ? 3 : 7);
231be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
232be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
233aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public static final Creator<RouteInfo> CREATOR =
234aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        new Creator<RouteInfo>() {
235aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo createFromParcel(Parcel in) {
236aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            InetAddress destAddr = null;
237aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            int prefix = 0;
238aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            InetAddress gateway = null;
239aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
240aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (in.readByte() == 1) {
241aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                byte[] addr = in.createByteArray();
242aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                prefix = in.readInt();
243aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
244aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                try {
245aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    destAddr = InetAddress.getByAddress(addr);
246aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } catch (UnknownHostException e) {}
247aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
248aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
249aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (in.readByte() == 1) {
250aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                byte[] addr = in.createByteArray();
251aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
252aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                try {
253aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    gateway = InetAddress.getByAddress(addr);
254aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } catch (UnknownHostException e) {}
255aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
256aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
25745b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            String iface = in.readString();
25845b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti
259aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            LinkAddress dest = null;
260aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
261aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (destAddr != null) {
262aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                dest = new LinkAddress(destAddr, prefix);
263aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
264aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
26545b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti            return new RouteInfo(dest, gateway, iface);
266aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
267aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
268aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo[] newArray(int size) {
269aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            return new RouteInfo[size];
270aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
271aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    };
272f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
27345b9a5bb93569ca49bbd44f7a518091371687f96Lorenzo Colitti    protected boolean matches(InetAddress destination) {
274f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if (destination == null) return false;
275f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
276f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // match the route destination and destination with prefix length
277f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
278f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                mDestination.getNetworkPrefixLength());
279f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
280f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        return mDestination.getAddress().equals(dstNet);
281f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    }
282f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
283f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    /**
284f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * Find the route from a Collection of routes that best matches a given address.
285f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * May return null if no routes are applicable.
286f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @param routes a Collection of RouteInfos to chose from
287f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @param dest the InetAddress your trying to get to
288f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @return the RouteInfo from the Collection that best fits the given address
289f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     */
290f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
291f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if ((routes == null) || (dest == null)) return null;
292f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
293f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        RouteInfo bestRoute = null;
294f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // pick a longest prefix match under same address type
295f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        for (RouteInfo route : routes) {
296f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
297f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                if ((bestRoute != null) &&
298f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                        (bestRoute.mDestination.getNetworkPrefixLength() >=
299f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                        route.mDestination.getNetworkPrefixLength())) {
300f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                    continue;
301f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                }
302f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                if (route.matches(dest)) bestRoute = route;
303f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt            }
304f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        }
305f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        return bestRoute;
306f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    }
307aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt}
308