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