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