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