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 17 package android.net; 18 19 import android.annotation.Nullable; 20 import android.annotation.SuppressLint; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.text.TextUtils; 24 import android.util.Log; 25 26 import com.android.net.module.util.InetAddressUtils; 27 28 import java.net.Inet4Address; 29 import java.net.InetAddress; 30 import java.util.ArrayList; 31 import java.util.List; 32 import java.util.Objects; 33 34 /** 35 * A simple object for retrieving the results of a DHCP request. 36 * Optimized (attempted) for that jni interface 37 * TODO: remove this class and replace with other existing constructs 38 * @hide 39 */ 40 public final class DhcpResults implements Parcelable { 41 private static final String TAG = "DhcpResults"; 42 43 public LinkAddress ipAddress; 44 45 public InetAddress gateway; 46 47 public final ArrayList<InetAddress> dnsServers = new ArrayList<>(); 48 49 public String domains; 50 51 public Inet4Address serverAddress; 52 53 /** Vendor specific information (from RFC 2132). */ 54 public String vendorInfo; 55 56 public int leaseDuration; 57 58 /** Link MTU option. 0 means unset. */ 59 public int mtu; 60 61 public String serverHostName; 62 63 @Nullable 64 public String captivePortalApiUrl; 65 DhcpResults()66 public DhcpResults() { 67 super(); 68 } 69 70 /** 71 * Create a {@link StaticIpConfiguration} based on the DhcpResults. 72 */ 73 @SuppressLint("NewApi") // TODO: b/193460475 remove once fixed toStaticIpConfiguration()74 public StaticIpConfiguration toStaticIpConfiguration() { 75 return new StaticIpConfiguration.Builder() 76 .setIpAddress(ipAddress) 77 .setGateway(gateway) 78 .setDnsServers(dnsServers) 79 .setDomains(domains) 80 .build(); 81 } 82 83 @SuppressLint("NewApi") // TODO: b/193460475 remove once fixed DhcpResults(StaticIpConfiguration source)84 public DhcpResults(StaticIpConfiguration source) { 85 if (source != null) { 86 ipAddress = source.getIpAddress(); 87 gateway = source.getGateway(); 88 dnsServers.addAll(source.getDnsServers()); 89 domains = source.getDomains(); 90 } 91 } 92 93 /** copy constructor */ DhcpResults(DhcpResults source)94 public DhcpResults(DhcpResults source) { 95 this(source == null ? null : source.toStaticIpConfiguration()); 96 if (source != null) { 97 serverAddress = source.serverAddress; 98 vendorInfo = source.vendorInfo; 99 leaseDuration = source.leaseDuration; 100 mtu = source.mtu; 101 serverHostName = source.serverHostName; 102 captivePortalApiUrl = source.captivePortalApiUrl; 103 } 104 } 105 106 /** 107 * @see StaticIpConfiguration#getRoutes(String) 108 * @hide 109 */ getRoutes(String iface)110 public List<RouteInfo> getRoutes(String iface) { 111 return toStaticIpConfiguration().getRoutes(iface); 112 } 113 114 /** 115 * Test if this DHCP lease includes vendor hint that network link is 116 * metered, and sensitive to heavy data transfers. 117 */ hasMeteredHint()118 public boolean hasMeteredHint() { 119 if (vendorInfo != null) { 120 return vendorInfo.contains("ANDROID_METERED"); 121 } else { 122 return false; 123 } 124 } 125 126 /** Clears all data and resets this object to its initial state. */ clear()127 public void clear() { 128 ipAddress = null; 129 gateway = null; 130 dnsServers.clear(); 131 domains = null; 132 serverAddress = null; 133 vendorInfo = null; 134 leaseDuration = 0; 135 mtu = 0; 136 serverHostName = null; 137 captivePortalApiUrl = null; 138 } 139 140 @Override toString()141 public String toString() { 142 StringBuilder str = new StringBuilder(super.toString()); 143 144 str.append(" DHCP server ").append(serverAddress); 145 str.append(" Vendor info ").append(vendorInfo); 146 str.append(" lease ").append(leaseDuration).append(" seconds"); 147 if (mtu != 0) str.append(" MTU ").append(mtu); 148 str.append(" Servername ").append(serverHostName); 149 if (captivePortalApiUrl != null) { 150 str.append(" CaptivePortalApiUrl ").append(captivePortalApiUrl); 151 } 152 153 return str.toString(); 154 } 155 156 @Override equals(@ullable Object obj)157 public boolean equals(@Nullable Object obj) { 158 if (this == obj) return true; 159 160 if (!(obj instanceof DhcpResults)) return false; 161 162 DhcpResults target = (DhcpResults) obj; 163 164 return toStaticIpConfiguration().equals(target.toStaticIpConfiguration()) 165 && Objects.equals(serverAddress, target.serverAddress) 166 && Objects.equals(vendorInfo, target.vendorInfo) 167 && Objects.equals(serverHostName, target.serverHostName) 168 && leaseDuration == target.leaseDuration 169 && mtu == target.mtu 170 && Objects.equals(captivePortalApiUrl, target.captivePortalApiUrl); 171 } 172 173 @Override hashCode()174 public int hashCode() { 175 return Objects.hash(ipAddress, gateway, dnsServers, domains, serverAddress, vendorInfo, 176 serverHostName, captivePortalApiUrl) + 43 * leaseDuration + 67 * mtu; 177 } 178 179 /** 180 * Implement the Parcelable interface 181 */ 182 @SuppressLint("NewApi") // TODO: b/193460475 remove once fixed 183 public static final @android.annotation.NonNull Creator<DhcpResults> CREATOR = 184 new Creator<DhcpResults>() { 185 public DhcpResults createFromParcel(Parcel in) { 186 return readFromParcel(in); 187 } 188 189 public DhcpResults[] newArray(int size) { 190 return new DhcpResults[size]; 191 } 192 }; 193 194 /** Implement the Parcelable interface */ writeToParcel(Parcel dest, int flags)195 public void writeToParcel(Parcel dest, int flags) { 196 toStaticIpConfiguration().writeToParcel(dest, flags); 197 dest.writeInt(leaseDuration); 198 dest.writeInt(mtu); 199 InetAddressUtils.parcelInetAddress(dest, serverAddress, flags); 200 dest.writeString(vendorInfo); 201 dest.writeString(serverHostName); 202 dest.writeString(captivePortalApiUrl); 203 } 204 205 @Override describeContents()206 public int describeContents() { 207 return 0; 208 } 209 210 @SuppressLint("NewApi") // TODO: b/193460475 remove once fixed readFromParcel(Parcel in)211 private static DhcpResults readFromParcel(Parcel in) { 212 final StaticIpConfiguration s = StaticIpConfiguration.CREATOR.createFromParcel(in); 213 final DhcpResults dhcpResults = new DhcpResults(s); 214 dhcpResults.leaseDuration = in.readInt(); 215 dhcpResults.mtu = in.readInt(); 216 dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in); 217 dhcpResults.vendorInfo = in.readString(); 218 dhcpResults.serverHostName = in.readString(); 219 dhcpResults.captivePortalApiUrl = in.readString(); 220 return dhcpResults; 221 } 222 223 /** 224 * Sets the IPv4 address. 225 * 226 * @param addrString the string representation of the IPv4 address 227 * @param prefixLength the prefix length. 228 * @return false on success, true on failure 229 */ setIpAddress(String addrString, int prefixLength)230 public boolean setIpAddress(String addrString, int prefixLength) { 231 try { 232 Inet4Address addr = (Inet4Address) InetAddresses.parseNumericAddress(addrString); 233 ipAddress = new LinkAddress(addr, prefixLength); 234 } catch (IllegalArgumentException | ClassCastException e) { 235 Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength); 236 return true; 237 } 238 return false; 239 } 240 241 /** 242 * Sets the gateway IPv4 address. 243 * 244 * @param addrString the string representation of the gateway IPv4 address 245 * @return false on success, true on failure 246 */ setGateway(String addrString)247 public boolean setGateway(String addrString) { 248 try { 249 gateway = InetAddresses.parseNumericAddress(addrString); 250 } catch (IllegalArgumentException e) { 251 Log.e(TAG, "setGateway failed with addrString " + addrString); 252 return true; 253 } 254 return false; 255 } 256 257 /** 258 * Adds a DNS server to the list. 259 * 260 * @param addrString the string representation of the DNS server IPv4 address 261 * @return false on success, true on failure 262 */ addDns(String addrString)263 public boolean addDns(String addrString) { 264 if (TextUtils.isEmpty(addrString)) return false; 265 try { 266 dnsServers.add(InetAddresses.parseNumericAddress(addrString)); 267 return false; 268 } catch (IllegalArgumentException e) { 269 Log.e(TAG, "addDns failed with addrString " + addrString); 270 return true; 271 } 272 } 273 getIpAddress()274 public LinkAddress getIpAddress() { 275 return ipAddress; 276 } 277 setIpAddress(LinkAddress ipAddress)278 public void setIpAddress(LinkAddress ipAddress) { 279 this.ipAddress = ipAddress; 280 } 281 getGateway()282 public InetAddress getGateway() { 283 return gateway; 284 } 285 setGateway(InetAddress gateway)286 public void setGateway(InetAddress gateway) { 287 this.gateway = gateway; 288 } 289 getDnsServers()290 public List<InetAddress> getDnsServers() { 291 return dnsServers; 292 } 293 294 /** 295 * Add a DNS server to this configuration. 296 */ addDnsServer(InetAddress server)297 public void addDnsServer(InetAddress server) { 298 dnsServers.add(server); 299 } 300 getDomains()301 public String getDomains() { 302 return domains; 303 } 304 setDomains(String domains)305 public void setDomains(String domains) { 306 this.domains = domains; 307 } 308 getServerAddress()309 public Inet4Address getServerAddress() { 310 return serverAddress; 311 } 312 setServerAddress(Inet4Address addr)313 public void setServerAddress(Inet4Address addr) { 314 serverAddress = addr; 315 } 316 getLeaseDuration()317 public int getLeaseDuration() { 318 return leaseDuration; 319 } 320 setLeaseDuration(int duration)321 public void setLeaseDuration(int duration) { 322 leaseDuration = duration; 323 } 324 getVendorInfo()325 public String getVendorInfo() { 326 return vendorInfo; 327 } 328 setVendorInfo(String info)329 public void setVendorInfo(String info) { 330 vendorInfo = info; 331 } 332 getMtu()333 public int getMtu() { 334 return mtu; 335 } 336 setMtu(int mtu)337 public void setMtu(int mtu) { 338 this.mtu = mtu; 339 } 340 getCaptivePortalApiUrl()341 public String getCaptivePortalApiUrl() { 342 return captivePortalApiUrl; 343 } 344 setCaptivePortalApiUrl(String url)345 public void setCaptivePortalApiUrl(String url) { 346 captivePortalApiUrl = url; 347 } 348 } 349