Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2014 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.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.annotation.SystemApi;
     22 import android.annotation.TestApi;
     23 import android.annotation.UnsupportedAppUsage;
     24 import android.net.shared.InetAddressUtils;
     25 import android.os.Parcel;
     26 import android.os.Parcelable;
     27 
     28 import java.net.InetAddress;
     29 import java.util.ArrayList;
     30 import java.util.List;
     31 import java.util.Objects;
     32 
     33 /**
     34  * Class that describes static IP configuration.
     35  *
     36  * <p>This class is different from {@link LinkProperties} because it represents
     37  * configuration intent. The general contract is that if we can represent
     38  * a configuration here, then we should be able to configure it on a network.
     39  * The intent is that it closely match the UI we have for configuring networks.
     40  *
     41  * <p>In contrast, {@link LinkProperties} represents current state. It is much more
     42  * expressive. For example, it supports multiple IP addresses, multiple routes,
     43  * stacked interfaces, and so on. Because LinkProperties is so expressive,
     44  * using it to represent configuration intent as well as current state causes
     45  * problems. For example, we could unknowingly save a configuration that we are
     46  * not in fact capable of applying, or we could save a configuration that the
     47  * UI cannot display, which has the potential for malicious code to hide
     48  * hostile or unexpected configuration from the user.
     49  *
     50  * @hide
     51  */
     52 @SystemApi
     53 @TestApi
     54 public final class StaticIpConfiguration implements Parcelable {
     55     /** @hide */
     56     @UnsupportedAppUsage
     57     @Nullable
     58     public LinkAddress ipAddress;
     59     /** @hide */
     60     @UnsupportedAppUsage
     61     @Nullable
     62     public InetAddress gateway;
     63     /** @hide */
     64     @UnsupportedAppUsage
     65     @NonNull
     66     public final ArrayList<InetAddress> dnsServers;
     67     /** @hide */
     68     @UnsupportedAppUsage
     69     @Nullable
     70     public String domains;
     71 
     72     public StaticIpConfiguration() {
     73         dnsServers = new ArrayList<>();
     74     }
     75 
     76     public StaticIpConfiguration(@Nullable StaticIpConfiguration source) {
     77         this();
     78         if (source != null) {
     79             // All of these except dnsServers are immutable, so no need to make copies.
     80             ipAddress = source.ipAddress;
     81             gateway = source.gateway;
     82             dnsServers.addAll(source.dnsServers);
     83             domains = source.domains;
     84         }
     85     }
     86 
     87     public void clear() {
     88         ipAddress = null;
     89         gateway = null;
     90         dnsServers.clear();
     91         domains = null;
     92     }
     93 
     94     /**
     95      * Get the static IP address included in the configuration.
     96      */
     97     public @Nullable LinkAddress getIpAddress() {
     98         return ipAddress;
     99     }
    100 
    101     /**
    102      * Get the gateway included in the configuration.
    103      */
    104     public @Nullable InetAddress getGateway() {
    105         return gateway;
    106     }
    107 
    108     /**
    109      * Get the DNS servers included in the configuration.
    110      */
    111     public @NonNull List<InetAddress> getDnsServers() {
    112         return dnsServers;
    113     }
    114 
    115     /**
    116      * Get a {@link String} listing in priority order of the comma separated domains to search when
    117      * resolving host names on the link.
    118      */
    119     public @Nullable String getDomains() {
    120         return domains;
    121     }
    122 
    123     /**
    124      * Helper class to build a new instance of {@link StaticIpConfiguration}.
    125      */
    126     public static final class Builder {
    127         private LinkAddress mIpAddress;
    128         private InetAddress mGateway;
    129         private Iterable<InetAddress> mDnsServers;
    130         private String mDomains;
    131 
    132         /**
    133          * Set the IP address to be included in the configuration; null by default.
    134          * @return The {@link Builder} for chaining.
    135          */
    136         public @NonNull Builder setIpAddress(@Nullable LinkAddress ipAddress) {
    137             mIpAddress = ipAddress;
    138             return this;
    139         }
    140 
    141         /**
    142          * Set the address of the gateway to be included in the configuration; null by default.
    143          * @return The {@link Builder} for chaining.
    144          */
    145         public @NonNull Builder setGateway(@Nullable InetAddress gateway) {
    146             mGateway = gateway;
    147             return this;
    148         }
    149 
    150         /**
    151          * Set the addresses of the DNS servers included in the configuration; empty by default.
    152          * @return The {@link Builder} for chaining.
    153          */
    154         public @NonNull Builder setDnsServers(@NonNull Iterable<InetAddress> dnsServers) {
    155             mDnsServers = dnsServers;
    156             return this;
    157         }
    158 
    159         /**
    160          * Sets the DNS domain search path to be used on the link; null by default.
    161          * @param newDomains A {@link String} containing the comma separated domains to search when
    162          *                   resolving host names on this link, in priority order.
    163          * @return The {@link Builder} for chaining.
    164          */
    165         public @NonNull Builder setDomains(@Nullable String newDomains) {
    166             mDomains = newDomains;
    167             return this;
    168         }
    169 
    170         /**
    171          * Create a {@link StaticIpConfiguration} from the parameters in this {@link Builder}.
    172          * @return The newly created StaticIpConfiguration.
    173          */
    174         public @NonNull StaticIpConfiguration build() {
    175             final StaticIpConfiguration config = new StaticIpConfiguration();
    176             config.ipAddress = mIpAddress;
    177             config.gateway = mGateway;
    178             for (InetAddress server : mDnsServers) {
    179                 config.dnsServers.add(server);
    180             }
    181             config.domains = mDomains;
    182             return config;
    183         }
    184     }
    185 
    186     /**
    187      * Add a DNS server to this configuration.
    188      */
    189     public void addDnsServer(@NonNull InetAddress server) {
    190         dnsServers.add(server);
    191     }
    192 
    193     /**
    194      * Returns the network routes specified by this object. Will typically include a
    195      * directly-connected route for the IP address's local subnet and a default route.
    196      * @param iface Interface to include in the routes.
    197      */
    198     public @NonNull List<RouteInfo> getRoutes(@Nullable String iface) {
    199         List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
    200         if (ipAddress != null) {
    201             RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
    202             routes.add(connectedRoute);
    203             // If the default gateway is not covered by the directly-connected route, also add a
    204             // host route to the gateway as well. This configuration is arguably invalid, but it
    205             // used to work in K and earlier, and other OSes appear to accept it.
    206             if (gateway != null && !connectedRoute.matches(gateway)) {
    207                 routes.add(RouteInfo.makeHostRoute(gateway, iface));
    208             }
    209         }
    210         if (gateway != null) {
    211             routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
    212         }
    213         return routes;
    214     }
    215 
    216     /**
    217      * Returns a LinkProperties object expressing the data in this object. Note that the information
    218      * contained in the LinkProperties will not be a complete picture of the link's configuration,
    219      * because any configuration information that is obtained dynamically by the network (e.g.,
    220      * IPv6 configuration) will not be included.
    221      * @hide
    222      */
    223     public @NonNull LinkProperties toLinkProperties(String iface) {
    224         LinkProperties lp = new LinkProperties();
    225         lp.setInterfaceName(iface);
    226         if (ipAddress != null) {
    227             lp.addLinkAddress(ipAddress);
    228         }
    229         for (RouteInfo route : getRoutes(iface)) {
    230             lp.addRoute(route);
    231         }
    232         for (InetAddress dns : dnsServers) {
    233             lp.addDnsServer(dns);
    234         }
    235         lp.setDomains(domains);
    236         return lp;
    237     }
    238 
    239     @Override
    240     public String toString() {
    241         StringBuffer str = new StringBuffer();
    242 
    243         str.append("IP address ");
    244         if (ipAddress != null ) str.append(ipAddress).append(" ");
    245 
    246         str.append("Gateway ");
    247         if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
    248 
    249         str.append(" DNS servers: [");
    250         for (InetAddress dnsServer : dnsServers) {
    251             str.append(" ").append(dnsServer.getHostAddress());
    252         }
    253 
    254         str.append(" ] Domains ");
    255         if (domains != null) str.append(domains);
    256         return str.toString();
    257     }
    258 
    259     @Override
    260     public int hashCode() {
    261         int result = 13;
    262         result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
    263         result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
    264         result = 47 * result + (domains == null ? 0 : domains.hashCode());
    265         result = 47 * result + dnsServers.hashCode();
    266         return result;
    267     }
    268 
    269     @Override
    270     public boolean equals(Object obj) {
    271         if (this == obj) return true;
    272 
    273         if (!(obj instanceof StaticIpConfiguration)) return false;
    274 
    275         StaticIpConfiguration other = (StaticIpConfiguration) obj;
    276 
    277         return other != null &&
    278                 Objects.equals(ipAddress, other.ipAddress) &&
    279                 Objects.equals(gateway, other.gateway) &&
    280                 dnsServers.equals(other.dnsServers) &&
    281                 Objects.equals(domains, other.domains);
    282     }
    283 
    284     /** Implement the Parcelable interface */
    285     public static final @android.annotation.NonNull Creator<StaticIpConfiguration> CREATOR =
    286         new Creator<StaticIpConfiguration>() {
    287             public StaticIpConfiguration createFromParcel(Parcel in) {
    288                 return readFromParcel(in);
    289             }
    290 
    291             public StaticIpConfiguration[] newArray(int size) {
    292                 return new StaticIpConfiguration[size];
    293             }
    294         };
    295 
    296     /** Implement the Parcelable interface */
    297     @Override
    298     public int describeContents() {
    299         return 0;
    300     }
    301 
    302     /** Implement the Parcelable interface */
    303     @Override
    304     public void writeToParcel(Parcel dest, int flags) {
    305         dest.writeParcelable(ipAddress, flags);
    306         InetAddressUtils.parcelInetAddress(dest, gateway, flags);
    307         dest.writeInt(dnsServers.size());
    308         for (InetAddress dnsServer : dnsServers) {
    309             InetAddressUtils.parcelInetAddress(dest, dnsServer, flags);
    310         }
    311         dest.writeString(domains);
    312     }
    313 
    314     /** @hide */
    315     public static StaticIpConfiguration readFromParcel(Parcel in) {
    316         final StaticIpConfiguration s = new StaticIpConfiguration();
    317         s.ipAddress = in.readParcelable(null);
    318         s.gateway = InetAddressUtils.unparcelInetAddress(in);
    319         s.dnsServers.clear();
    320         int size = in.readInt();
    321         for (int i = 0; i < size; i++) {
    322             s.dnsServers.add(InetAddressUtils.unparcelInetAddress(in));
    323         }
    324         s.domains = in.readString();
    325         return s;
    326     }
    327 }
    328