Home | History | Annotate | Download | only in net
      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 
     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 
     75     public RouteInfo(InetAddress gateway) {
     76         this(null, gateway);
     77     }
     78 
     79     public static RouteInfo makeHostRoute(InetAddress host) {
     80         return makeHostRoute(host, null);
     81     }
     82 
     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 
     93     private boolean isHost() {
     94         return (mGateway.equals(Inet4Address.ANY) || mGateway.equals(Inet6Address.ANY));
     95     }
     96 
     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 
    110     public LinkAddress getDestination() {
    111         return mDestination;
    112     }
    113 
    114     public InetAddress getGateway() {
    115         return mGateway;
    116     }
    117 
    118     public boolean isDefaultRoute() {
    119         return mIsDefault;
    120     }
    121 
    122     public boolean isHostRoute() {
    123         return mIsHost;
    124     }
    125 
    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 
    133     public int describeContents() {
    134         return 0;
    135     }
    136 
    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
    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
    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 
    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      */
    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