RouteInfo.java revision be2b058ec1e11e1d33b6d03230c21e5d2d7ac40c
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 *
32aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt * @hide
33aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt */
34aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltpublic class RouteInfo implements Parcelable {
35aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    /**
36aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     * The IP destination address for this route.
37aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     */
38aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final LinkAddress mDestination;
39aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
40aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    /**
41aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     * The gateway address for this route.
42aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt     */
43aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final InetAddress mGateway;
44aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
45aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private final boolean mIsDefault;
46aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
47aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public RouteInfo(LinkAddress destination, InetAddress gateway) {
48aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (destination == null) {
49aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            try {
508c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                if (gateway != null) {
518c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                    if (gateway instanceof Inet4Address) {
528c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                        destination = new LinkAddress(Inet4Address.ANY, 0);
538c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                    } else {
548c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                        destination = new LinkAddress(Inet6Address.ANY, 0);
558c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                    }
56aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } else {
578c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                    // no destination, no gateway. invalid.
588c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                    throw new RuntimeException("Invalid arguments passed in.");
59aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                }
60aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            } catch (Exception e) {}
61aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
628c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        if (gateway == null) {
638c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            if (destination.getAddress() instanceof Inet4Address) {
648c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet4Address.ANY;
658c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            } else {
668c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo                gateway = Inet6Address.ANY;
678c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo            }
688c0b528a4746228461ead10f0d477345b607fef1Kazuhiro Ondo        }
69f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
70f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
71aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        mGateway = gateway;
72aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        mIsDefault = isDefault();
73aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
74aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
75aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public RouteInfo(InetAddress gateway) {
76f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        this(null, gateway);
77aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
78aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
79aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    private boolean isDefault() {
80aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        boolean val = false;
81aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway != null) {
82aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (mGateway instanceof Inet4Address) {
83f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
84aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            } else {
85f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
86aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
87aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
88aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return val;
89aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
90aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
91aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public LinkAddress getDestination() {
92aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mDestination;
93aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
94aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
95aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public InetAddress getGateway() {
96aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mGateway;
97aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
98aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
99aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public boolean isDefaultRoute() {
100aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return mIsDefault;
101aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
102aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
103aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public String toString() {
104aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        String val = "";
105aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mDestination != null) val = mDestination.toString();
106aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway != null) val += " -> " + mGateway.getHostAddress();
107aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return val;
108aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
109aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
110aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public int describeContents() {
111aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        return 0;
112aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
113aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
114aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public void writeToParcel(Parcel dest, int flags) {
115aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mDestination == null) {
116aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 0);
117aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        } else {
118aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 1);
119aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByteArray(mDestination.getAddress().getAddress());
120aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeInt(mDestination.getNetworkPrefixLength());
121aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
122aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
123aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        if (mGateway == null) {
124aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 0);
125aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        } else {
126aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByte((byte) 1);
127aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            dest.writeByteArray(mGateway.getAddress());
128aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
129aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    }
130aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
131be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    @Override
132be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public boolean equals(Object obj) {
133be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (this == obj) return true;
134be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
135be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        if (!(obj instanceof RouteInfo)) return false;
136be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
137be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        RouteInfo target = (RouteInfo) obj;
138be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
139be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        boolean sameDestination = ( mDestination == null) ?
140be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                target.getDestination() == null
141be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                : mDestination.equals(target.getDestination());
142be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
143be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        boolean sameAddress = (mGateway == null) ?
144be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                target.getGateway() == null
145be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville                : mGateway.equals(target.getGateway());
146be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
147be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        return sameDestination && sameAddress
148be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            && mIsDefault == target.mIsDefault;
149be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
150be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
151be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    @Override
152be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    public int hashCode() {
153be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville        return (mDestination == null ? 0 : mDestination.hashCode())
154be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            + (mGateway == null ? 0 :mGateway.hashCode())
155be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville            + (mIsDefault ? 3 : 7);
156be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville    }
157be2b058ec1e11e1d33b6d03230c21e5d2d7ac40cWink Saville
158aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    public static final Creator<RouteInfo> CREATOR =
159aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        new Creator<RouteInfo>() {
160aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo createFromParcel(Parcel in) {
161aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            InetAddress destAddr = null;
162aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            int prefix = 0;
163aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            InetAddress gateway = null;
164aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
165aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (in.readByte() == 1) {
166aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                byte[] addr = in.createByteArray();
167aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                prefix = in.readInt();
168aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
169aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                try {
170aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    destAddr = InetAddress.getByAddress(addr);
171aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } catch (UnknownHostException e) {}
172aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
173aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
174aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (in.readByte() == 1) {
175aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                byte[] addr = in.createByteArray();
176aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
177aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                try {
178aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                    gateway = InetAddress.getByAddress(addr);
179aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                } catch (UnknownHostException e) {}
180aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
181aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
182aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            LinkAddress dest = null;
183aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
184aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            if (destAddr != null) {
185aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt                dest = new LinkAddress(destAddr, prefix);
186aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            }
187aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
188aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            return new RouteInfo(dest, gateway);
189aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
190aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt
191aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        public RouteInfo[] newArray(int size) {
192aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt            return new RouteInfo[size];
193aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt        }
194aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt    };
195f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
196f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    private boolean matches(InetAddress destination) {
197f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if (destination == null) return false;
198f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
199f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // if the destination is present and the route is default.
200f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // return true
201f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if (isDefault()) return true;
202f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
203f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // match the route destination and destination with prefix length
204f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
205f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                mDestination.getNetworkPrefixLength());
206f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
207f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        return mDestination.getAddress().equals(dstNet);
208f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    }
209f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
210f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    /**
211f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * Find the route from a Collection of routes that best matches a given address.
212f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * May return null if no routes are applicable.
213f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @param routes a Collection of RouteInfos to chose from
214f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @param dest the InetAddress your trying to get to
215f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     * @return the RouteInfo from the Collection that best fits the given address
216f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt     */
217f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
218f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        if ((routes == null) || (dest == null)) return null;
219f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt
220f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        RouteInfo bestRoute = null;
221f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        // pick a longest prefix match under same address type
222f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        for (RouteInfo route : routes) {
223f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt            if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
224f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                if ((bestRoute != null) &&
225f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                        (bestRoute.mDestination.getNetworkPrefixLength() >=
226f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                        route.mDestination.getNetworkPrefixLength())) {
227f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                    continue;
228f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                }
229f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt                if (route.matches(dest)) bestRoute = route;
230f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt            }
231f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        }
232f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt        return bestRoute;
233f43396caaaae8f336bcf6fe9128a89dc7a7b0a5cRobert Greenwalt    }
234aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwalt}
235