1/*
2 * Copyright (C) 2012 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
17package android.net;
18
19import android.net.NetworkUtils;
20import android.os.Parcelable;
21import android.os.Parcel;
22import android.text.TextUtils;
23import android.util.Log;
24
25import java.net.InetAddress;
26import java.net.Inet4Address;
27import java.util.Objects;
28
29/**
30 * A simple object for retrieving the results of a DHCP request.
31 * Optimized (attempted) for that jni interface
32 * TODO - remove when DhcpInfo is deprecated.  Move the remaining api to LinkProperties.
33 * @hide
34 */
35public class DhcpResults extends StaticIpConfiguration {
36    private static final String TAG = "DhcpResults";
37
38    public InetAddress serverAddress;
39
40    /** Vendor specific information (from RFC 2132). */
41    public String vendorInfo;
42
43    public int leaseDuration;
44
45    public DhcpResults() {
46        super();
47    }
48
49    public DhcpResults(StaticIpConfiguration source) {
50        super(source);
51    }
52
53    /** copy constructor */
54    public DhcpResults(DhcpResults source) {
55        super(source);
56
57        if (source != null) {
58            // All these are immutable, so no need to make copies.
59            serverAddress = source.serverAddress;
60            vendorInfo = source.vendorInfo;
61            leaseDuration = source.leaseDuration;
62        }
63    }
64
65    /**
66     * Updates the DHCP fields that need to be retained from
67     * original DHCP request if the current renewal shows them
68     * being empty.
69     */
70    public void updateFromDhcpRequest(DhcpResults orig) {
71        if (orig == null) return;
72        if (gateway == null) gateway = orig.gateway;
73        if (dnsServers.size() == 0) {
74            dnsServers.addAll(orig.dnsServers);
75        }
76    }
77
78    /**
79     * Test if this DHCP lease includes vendor hint that network link is
80     * metered, and sensitive to heavy data transfers.
81     */
82    public boolean hasMeteredHint() {
83        if (vendorInfo != null) {
84            return vendorInfo.contains("ANDROID_METERED");
85        } else {
86            return false;
87        }
88    }
89
90    public void clear() {
91        super.clear();
92        vendorInfo = null;
93        leaseDuration = 0;
94    }
95
96    @Override
97    public String toString() {
98        StringBuffer str = new StringBuffer(super.toString());
99
100        str.append(" DHCP server ").append(serverAddress);
101        str.append(" Vendor info ").append(vendorInfo);
102        str.append(" lease ").append(leaseDuration).append(" seconds");
103
104        return str.toString();
105    }
106
107    @Override
108    public boolean equals(Object obj) {
109        if (this == obj) return true;
110
111        if (!(obj instanceof DhcpResults)) return false;
112
113        DhcpResults target = (DhcpResults)obj;
114
115        return super.equals((StaticIpConfiguration) obj) &&
116                Objects.equals(serverAddress, target.serverAddress) &&
117                Objects.equals(vendorInfo, target.vendorInfo) &&
118                leaseDuration == target.leaseDuration;
119    }
120
121    /** Implement the Parcelable interface */
122    public static final Creator<DhcpResults> CREATOR =
123        new Creator<DhcpResults>() {
124            public DhcpResults createFromParcel(Parcel in) {
125                DhcpResults dhcpResults = new DhcpResults();
126                readFromParcel(dhcpResults, in);
127                return dhcpResults;
128            }
129
130            public DhcpResults[] newArray(int size) {
131                return new DhcpResults[size];
132            }
133        };
134
135    /** Implement the Parcelable interface */
136    public void writeToParcel(Parcel dest, int flags) {
137        super.writeToParcel(dest, flags);
138        dest.writeInt(leaseDuration);
139        NetworkUtils.parcelInetAddress(dest, serverAddress, flags);
140        dest.writeString(vendorInfo);
141    }
142
143    private static void readFromParcel(DhcpResults dhcpResults, Parcel in) {
144        StaticIpConfiguration.readFromParcel(dhcpResults, in);
145        dhcpResults.leaseDuration = in.readInt();
146        dhcpResults.serverAddress = NetworkUtils.unparcelInetAddress(in);
147        dhcpResults.vendorInfo = in.readString();
148    }
149
150    // Utils for jni population - false on success
151    // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
152    public boolean setIpAddress(String addrString, int prefixLength) {
153        try {
154            Inet4Address addr = (Inet4Address) NetworkUtils.numericToInetAddress(addrString);
155            ipAddress = new LinkAddress(addr, prefixLength);
156        } catch (IllegalArgumentException|ClassCastException e) {
157            Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
158            return true;
159        }
160        return false;
161    }
162
163    public boolean setGateway(String addrString) {
164        try {
165            gateway = NetworkUtils.numericToInetAddress(addrString);
166        } catch (IllegalArgumentException e) {
167            Log.e(TAG, "setGateway failed with addrString " + addrString);
168            return true;
169        }
170        return false;
171    }
172
173    public boolean addDns(String addrString) {
174        if (TextUtils.isEmpty(addrString) == false) {
175            try {
176                dnsServers.add(NetworkUtils.numericToInetAddress(addrString));
177            } catch (IllegalArgumentException e) {
178                Log.e(TAG, "addDns failed with addrString " + addrString);
179                return true;
180            }
181        }
182        return false;
183    }
184
185    public boolean setServerAddress(String addrString) {
186        try {
187            serverAddress = NetworkUtils.numericToInetAddress(addrString);
188        } catch (IllegalArgumentException e) {
189            Log.e(TAG, "setServerAddress failed with addrString " + addrString);
190            return true;
191        }
192        return false;
193    }
194
195    public void setLeaseDuration(int duration) {
196        leaseDuration = duration;
197    }
198
199    public void setVendorInfo(String info) {
200        vendorInfo = info;
201    }
202
203    public void setDomains(String newDomains) {
204        domains = newDomains;
205    }
206}
207