• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 import java.net.UnknownHostException;
23 import java.net.InetAddress;
24 import java.net.Inet4Address;
25 import java.net.Inet6Address;
26 
27 import java.util.Collection;
28 
29 /**
30  * A simple container for route information.
31  *
32  * @hide
33  */
34 public class RouteInfo implements Parcelable {
35     /**
36      * The IP destination address for this route.
37      */
38     private final LinkAddress mDestination;
39 
40     /**
41      * The gateway address for this route.
42      */
43     private final InetAddress mGateway;
44 
45     private final boolean mIsDefault;
46     private final boolean mIsHost;
47 
RouteInfo(LinkAddress destination, InetAddress gateway)48     public RouteInfo(LinkAddress destination, InetAddress gateway) {
49         if (destination == null) {
50             if (gateway != null) {
51                 if (gateway instanceof Inet4Address) {
52                     destination = new LinkAddress(Inet4Address.ANY, 0);
53                 } else {
54                     destination = new LinkAddress(Inet6Address.ANY, 0);
55                 }
56             } else {
57                 // no destination, no gateway. invalid.
58                 throw new RuntimeException("Invalid arguments passed in.");
59             }
60         }
61         if (gateway == null) {
62             if (destination.getAddress() instanceof Inet4Address) {
63                 gateway = Inet4Address.ANY;
64             } else {
65                 gateway = Inet6Address.ANY;
66             }
67         }
68         mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
69                 destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
70         mGateway = gateway;
71         mIsDefault = isDefault();
72         mIsHost = isHost();
73     }
74 
RouteInfo(InetAddress gateway)75     public RouteInfo(InetAddress gateway) {
76         this(null, gateway);
77     }
78 
makeHostRoute(InetAddress host)79     public static RouteInfo makeHostRoute(InetAddress host) {
80         return makeHostRoute(host, null);
81     }
82 
makeHostRoute(InetAddress host, InetAddress gateway)83     public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway) {
84         if (host == null) return null;
85 
86         if (host instanceof Inet4Address) {
87             return new RouteInfo(new LinkAddress(host, 32), gateway);
88         } else {
89             return new RouteInfo(new LinkAddress(host, 128), gateway);
90         }
91     }
92 
isHost()93     private boolean isHost() {
94         return (mGateway.equals(Inet4Address.ANY) || mGateway.equals(Inet6Address.ANY));
95     }
96 
isDefault()97     private boolean isDefault() {
98         boolean val = false;
99         if (mGateway != null) {
100             if (mGateway instanceof Inet4Address) {
101                 val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
102             } else {
103                 val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
104             }
105         }
106         return val;
107     }
108 
109 
getDestination()110     public LinkAddress getDestination() {
111         return mDestination;
112     }
113 
getGateway()114     public InetAddress getGateway() {
115         return mGateway;
116     }
117 
isDefaultRoute()118     public boolean isDefaultRoute() {
119         return mIsDefault;
120     }
121 
isHostRoute()122     public boolean isHostRoute() {
123         return mIsHost;
124     }
125 
toString()126     public String toString() {
127         String val = "";
128         if (mDestination != null) val = mDestination.toString();
129         if (mGateway != null) val += " -> " + mGateway.getHostAddress();
130         return val;
131     }
132 
describeContents()133     public int describeContents() {
134         return 0;
135     }
136 
writeToParcel(Parcel dest, int flags)137     public void writeToParcel(Parcel dest, int flags) {
138         if (mDestination == null) {
139             dest.writeByte((byte) 0);
140         } else {
141             dest.writeByte((byte) 1);
142             dest.writeByteArray(mDestination.getAddress().getAddress());
143             dest.writeInt(mDestination.getNetworkPrefixLength());
144         }
145 
146         if (mGateway == null) {
147             dest.writeByte((byte) 0);
148         } else {
149             dest.writeByte((byte) 1);
150             dest.writeByteArray(mGateway.getAddress());
151         }
152     }
153 
154     @Override
equals(Object obj)155     public boolean equals(Object obj) {
156         if (this == obj) return true;
157 
158         if (!(obj instanceof RouteInfo)) return false;
159 
160         RouteInfo target = (RouteInfo) obj;
161 
162         boolean sameDestination = ( mDestination == null) ?
163                 target.getDestination() == null
164                 : mDestination.equals(target.getDestination());
165 
166         boolean sameAddress = (mGateway == null) ?
167                 target.getGateway() == null
168                 : mGateway.equals(target.getGateway());
169 
170         return sameDestination && sameAddress
171             && mIsDefault == target.mIsDefault;
172     }
173 
174     @Override
hashCode()175     public int hashCode() {
176         return (mDestination == null ? 0 : mDestination.hashCode())
177             + (mGateway == null ? 0 :mGateway.hashCode())
178             + (mIsDefault ? 3 : 7);
179     }
180 
181     public static final Creator<RouteInfo> CREATOR =
182         new Creator<RouteInfo>() {
183         public RouteInfo createFromParcel(Parcel in) {
184             InetAddress destAddr = null;
185             int prefix = 0;
186             InetAddress gateway = null;
187 
188             if (in.readByte() == 1) {
189                 byte[] addr = in.createByteArray();
190                 prefix = in.readInt();
191 
192                 try {
193                     destAddr = InetAddress.getByAddress(addr);
194                 } catch (UnknownHostException e) {}
195             }
196 
197             if (in.readByte() == 1) {
198                 byte[] addr = in.createByteArray();
199 
200                 try {
201                     gateway = InetAddress.getByAddress(addr);
202                 } catch (UnknownHostException e) {}
203             }
204 
205             LinkAddress dest = null;
206 
207             if (destAddr != null) {
208                 dest = new LinkAddress(destAddr, prefix);
209             }
210 
211             return new RouteInfo(dest, gateway);
212         }
213 
214         public RouteInfo[] newArray(int size) {
215             return new RouteInfo[size];
216         }
217     };
218 
matches(InetAddress destination)219     private boolean matches(InetAddress destination) {
220         if (destination == null) return false;
221 
222         // if the destination is present and the route is default.
223         // return true
224         if (isDefault()) return true;
225 
226         // match the route destination and destination with prefix length
227         InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
228                 mDestination.getNetworkPrefixLength());
229 
230         return mDestination.getAddress().equals(dstNet);
231     }
232 
233     /**
234      * Find the route from a Collection of routes that best matches a given address.
235      * May return null if no routes are applicable.
236      * @param routes a Collection of RouteInfos to chose from
237      * @param dest the InetAddress your trying to get to
238      * @return the RouteInfo from the Collection that best fits the given address
239      */
selectBestRoute(Collection<RouteInfo> routes, InetAddress dest)240     public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
241         if ((routes == null) || (dest == null)) return null;
242 
243         RouteInfo bestRoute = null;
244         // pick a longest prefix match under same address type
245         for (RouteInfo route : routes) {
246             if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
247                 if ((bestRoute != null) &&
248                         (bestRoute.mDestination.getNetworkPrefixLength() >=
249                         route.mDestination.getNetworkPrefixLength())) {
250                     continue;
251                 }
252                 if (route.matches(dest)) bestRoute = route;
253             }
254         }
255         return bestRoute;
256     }
257 }
258