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