10a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti/*
20a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * Copyright (C) 2014 The Android Open Source Project
30a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *
40a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
50a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * you may not use this file except in compliance with the License.
60a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * You may obtain a copy of the License at
70a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *
80a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *      http://www.apache.org/licenses/LICENSE-2.0
90a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *
100a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software
110a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
120a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * See the License for the specific language governing permissions and
140a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * limitations under the License.
150a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti */
160a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
170a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittipackage android.net;
180a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
190a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport android.net.LinkAddress;
200a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport android.os.Parcelable;
210a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport android.os.Parcel;
220a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
230a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport java.net.InetAddress;
240a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport java.util.ArrayList;
250a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport java.util.List;
260a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittiimport java.util.Objects;
270a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
280a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti/**
290a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * Class that describes static IP configuration.
300a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *
310a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * This class is different from LinkProperties because it represents
320a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * configuration intent. The general contract is that if we can represent
330a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * a configuration here, then we should be able to configure it on a network.
340a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * The intent is that it closely match the UI we have for configuring networks.
350a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *
360a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * In contrast, LinkProperties represents current state. It is much more
370a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * expressive. For example, it supports multiple IP addresses, multiple routes,
380a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * stacked interfaces, and so on. Because LinkProperties is so expressive,
390a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * using it to represent configuration intent as well as current state causes
400a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * problems. For example, we could unknowingly save a configuration that we are
410a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * not in fact capable of applying, or we could save a configuration that the
420a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * UI cannot display, which has the potential for malicious code to hide
430a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * hostile or unexpected configuration from the user: see, for example,
440a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * http://b/12663469 and http://b/16893413 .
450a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti *
460a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti * @hide
470a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti */
480a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colittipublic class StaticIpConfiguration implements Parcelable {
490a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public LinkAddress ipAddress;
500a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public InetAddress gateway;
510a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public final ArrayList<InetAddress> dnsServers;
520a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public String domains;
530a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
540a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public StaticIpConfiguration() {
550a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        dnsServers = new ArrayList<InetAddress>();
560a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
570a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
580a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public StaticIpConfiguration(StaticIpConfiguration source) {
590a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        this();
600a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (source != null) {
610a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            // All of these except dnsServers are immutable, so no need to make copies.
620a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            ipAddress = source.ipAddress;
630a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            gateway = source.gateway;
640a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            dnsServers.addAll(source.dnsServers);
650a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            domains = source.domains;
660a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
670a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
680a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
690a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public void clear() {
700a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        ipAddress = null;
710a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        gateway = null;
720a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        dnsServers.clear();
730a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        domains = null;
740a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
750a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
760a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    /**
770a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     * Returns the network routes specified by this object. Will typically include a
788316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti     * directly-connected route for the IP address's local subnet and a default route. If the
798316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti     * default gateway is not covered by the directly-connected route, it will also contain a host
808316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti     * route to the gateway as well. This configuration is arguably invalid, but it used to work
818316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti     * in K and earlier, and other OSes appear to accept it.
820a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     */
830a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public List<RouteInfo> getRoutes(String iface) {
848316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti        List<RouteInfo> routes = new ArrayList<RouteInfo>(3);
850a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (ipAddress != null) {
868316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti            RouteInfo connectedRoute = new RouteInfo(ipAddress, null, iface);
878316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti            routes.add(connectedRoute);
888316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti            if (gateway != null && !connectedRoute.matches(gateway)) {
898316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti                routes.add(RouteInfo.makeHostRoute(gateway, iface));
908316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti            }
910a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
920a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (gateway != null) {
938316b819b2837b6ad25957328ba7b2fdaf705fa9Lorenzo Colitti            routes.add(new RouteInfo((IpPrefix) null, gateway, iface));
940a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
950a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        return routes;
960a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
970a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
980a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    /**
990a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     * Returns a LinkProperties object expressing the data in this object. Note that the information
1000a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     * contained in the LinkProperties will not be a complete picture of the link's configuration,
1010a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     * because any configuration information that is obtained dynamically by the network (e.g.,
1020a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     * IPv6 configuration) will not be included.
1030a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti     */
1040a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public LinkProperties toLinkProperties(String iface) {
1050a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        LinkProperties lp = new LinkProperties();
1060a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        lp.setInterfaceName(iface);
1070a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (ipAddress != null) {
1080a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            lp.addLinkAddress(ipAddress);
1090a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
1100a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        for (RouteInfo route : getRoutes(iface)) {
1110a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            lp.addRoute(route);
1120a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
1130a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        for (InetAddress dns : dnsServers) {
1140a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            lp.addDnsServer(dns);
1150a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
116b3b70975d9b1d9969dc58ed880baa13509a8933dPaul Jensen        lp.setDomains(domains);
1170a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        return lp;
1180a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
1190a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1200a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public String toString() {
1210a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        StringBuffer str = new StringBuffer();
1220a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1230a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        str.append("IP address ");
1240a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (ipAddress != null ) str.append(ipAddress).append(" ");
1250a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1260a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        str.append("Gateway ");
1270a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (gateway != null) str.append(gateway.getHostAddress()).append(" ");
1280a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1290a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        str.append(" DNS servers: [");
1300a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        for (InetAddress dnsServer : dnsServers) {
1310a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            str.append(" ").append(dnsServer.getHostAddress());
1320a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
1330a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
134acda32c35fc6a30ce11abfddb26ec5052de063f4Erik Kline        str.append(" ] Domains ");
1350a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (domains != null) str.append(domains);
1360a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        return str.toString();
1370a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
1380a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1390a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public int hashCode() {
1400a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        int result = 13;
1410a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        result = 47 * result + (ipAddress == null ? 0 : ipAddress.hashCode());
1420a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        result = 47 * result + (gateway == null ? 0 : gateway.hashCode());
1430a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        result = 47 * result + (domains == null ? 0 : domains.hashCode());
1440a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        result = 47 * result + dnsServers.hashCode();
1450a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        return result;
1460a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
1470a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1480a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    @Override
1490a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public boolean equals(Object obj) {
1500a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (this == obj) return true;
1510a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1520a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        if (!(obj instanceof StaticIpConfiguration)) return false;
1530a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1540a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        StaticIpConfiguration other = (StaticIpConfiguration) obj;
1550a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1560a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        return other != null &&
1570a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                Objects.equals(ipAddress, other.ipAddress) &&
1580a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                Objects.equals(gateway, other.gateway) &&
1590a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                dnsServers.equals(other.dnsServers) &&
1600a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                Objects.equals(domains, other.domains);
1610a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
1620a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1630a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    /** Implement the Parcelable interface */
1640a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public static Creator<StaticIpConfiguration> CREATOR =
1650a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        new Creator<StaticIpConfiguration>() {
1660a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            public StaticIpConfiguration createFromParcel(Parcel in) {
1670a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                StaticIpConfiguration s = new StaticIpConfiguration();
1680a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                readFromParcel(s, in);
1690a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                return s;
1700a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            }
1710a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1720a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            public StaticIpConfiguration[] newArray(int size) {
1730a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti                return new StaticIpConfiguration[size];
1740a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            }
1750a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        };
1760a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1770a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    /** Implement the Parcelable interface */
1780a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public int describeContents() {
1790a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        return 0;
1800a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
1810a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1820a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    /** Implement the Parcelable interface */
1830a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    public void writeToParcel(Parcel dest, int flags) {
1840a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        dest.writeParcelable(ipAddress, flags);
1850a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        NetworkUtils.parcelInetAddress(dest, gateway, flags);
1860a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        dest.writeInt(dnsServers.size());
1870a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        for (InetAddress dnsServer : dnsServers) {
1880a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            NetworkUtils.parcelInetAddress(dest, dnsServer, flags);
1890a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
190d0cc544039ee7d35d0f1aa9fc9d0f57ef6dfbfb9Lorenzo Colitti        dest.writeString(domains);
1910a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
1920a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti
1930a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    protected static void readFromParcel(StaticIpConfiguration s, Parcel in) {
1940a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        s.ipAddress = in.readParcelable(null);
1950a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        s.gateway = NetworkUtils.unparcelInetAddress(in);
1960a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        s.dnsServers.clear();
1970a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        int size = in.readInt();
1980a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        for (int i = 0; i < size; i++) {
1990a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti            s.dnsServers.add(NetworkUtils.unparcelInetAddress(in));
2000a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti        }
201d0cc544039ee7d35d0f1aa9fc9d0f57ef6dfbfb9Lorenzo Colitti        s.domains = in.readString();
2020a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti    }
2030a82e80073e193725a9d4c84a93db8a04b2456b9Lorenzo Colitti}
204