1 /* 2 * Copyright (C) 2019 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.shared; 18 19 import android.annotation.Nullable; 20 import android.net.INetd; 21 import android.net.Network; 22 import android.net.ProvisioningConfigurationParcelable; 23 import android.net.StaticIpConfiguration; 24 import android.net.apf.ApfCapabilities; 25 import android.net.ip.IIpClient; 26 27 import java.util.Objects; 28 import java.util.StringJoiner; 29 30 /** 31 * This class encapsulates parameters to be passed to 32 * IpClient#startProvisioning(). A defensive copy is made by IpClient 33 * and the values specified herein are in force until IpClient#stop() 34 * is called. 35 * 36 * Example use: 37 * 38 * final ProvisioningConfiguration config = 39 * new ProvisioningConfiguration.Builder() 40 * .withPreDhcpAction() 41 * .withProvisioningTimeoutMs(36 * 1000) 42 * .build(); 43 * mIpClient.startProvisioning(config.toStableParcelable()); 44 * ... 45 * mIpClient.stop(); 46 * 47 * The specified provisioning configuration will only be active until 48 * IIpClient#stop() is called. Future calls to IIpClient#startProvisioning() 49 * must specify the configuration again. 50 * @hide 51 */ 52 public class ProvisioningConfiguration { 53 // TODO: Delete this default timeout once those callers that care are 54 // fixed to pass in their preferred timeout. 55 // 56 // We pick 36 seconds so we can send DHCP requests at 57 // 58 // t=0, t=2, t=6, t=14, t=30 59 // 60 // allowing for 10% jitter. 61 private static final int DEFAULT_TIMEOUT_MS = 36 * 1000; 62 63 /** 64 * Builder to create a {@link ProvisioningConfiguration}. 65 */ 66 public static class Builder { 67 protected ProvisioningConfiguration mConfig = new ProvisioningConfiguration(); 68 69 /** 70 * Specify that the configuration should not enable IPv4. It is enabled by default. 71 */ withoutIPv4()72 public Builder withoutIPv4() { 73 mConfig.mEnableIPv4 = false; 74 return this; 75 } 76 77 /** 78 * Specify that the configuration should not enable IPv6. It is enabled by default. 79 */ withoutIPv6()80 public Builder withoutIPv6() { 81 mConfig.mEnableIPv6 = false; 82 return this; 83 } 84 85 /** 86 * Specify that the configuration should not use a MultinetworkPolicyTracker. It is used 87 * by default. 88 */ withoutMultinetworkPolicyTracker()89 public Builder withoutMultinetworkPolicyTracker() { 90 mConfig.mUsingMultinetworkPolicyTracker = false; 91 return this; 92 } 93 94 /** 95 * Specify that the configuration should not use a IpReachabilityMonitor. It is used by 96 * default. 97 */ withoutIpReachabilityMonitor()98 public Builder withoutIpReachabilityMonitor() { 99 mConfig.mUsingIpReachabilityMonitor = false; 100 return this; 101 } 102 103 /** 104 * Identical to {@link #withPreDhcpAction(int)}, using a default timeout. 105 * @see #withPreDhcpAction(int) 106 */ withPreDhcpAction()107 public Builder withPreDhcpAction() { 108 mConfig.mRequestedPreDhcpActionMs = DEFAULT_TIMEOUT_MS; 109 return this; 110 } 111 112 /** 113 * Specify that {@link IpClientCallbacks#onPreDhcpAction()} should be called. Clients must 114 * call {@link IIpClient#completedPreDhcpAction()} when the callback called. This behavior 115 * is disabled by default. 116 * @param dhcpActionTimeoutMs Timeout for clients to call completedPreDhcpAction(). 117 */ withPreDhcpAction(int dhcpActionTimeoutMs)118 public Builder withPreDhcpAction(int dhcpActionTimeoutMs) { 119 mConfig.mRequestedPreDhcpActionMs = dhcpActionTimeoutMs; 120 return this; 121 } 122 123 /** 124 * Specify the initial provisioning configuration. 125 */ withInitialConfiguration(InitialConfiguration initialConfig)126 public Builder withInitialConfiguration(InitialConfiguration initialConfig) { 127 mConfig.mInitialConfig = initialConfig; 128 return this; 129 } 130 131 /** 132 * Specify a static configuration for provisioning. 133 */ withStaticConfiguration(StaticIpConfiguration staticConfig)134 public Builder withStaticConfiguration(StaticIpConfiguration staticConfig) { 135 mConfig.mStaticIpConfig = staticConfig; 136 return this; 137 } 138 139 /** 140 * Specify ApfCapabilities. 141 */ withApfCapabilities(ApfCapabilities apfCapabilities)142 public Builder withApfCapabilities(ApfCapabilities apfCapabilities) { 143 mConfig.mApfCapabilities = apfCapabilities; 144 return this; 145 } 146 147 /** 148 * Specify the timeout to use for provisioning. 149 */ withProvisioningTimeoutMs(int timeoutMs)150 public Builder withProvisioningTimeoutMs(int timeoutMs) { 151 mConfig.mProvisioningTimeoutMs = timeoutMs; 152 return this; 153 } 154 155 /** 156 * Specify that IPv6 address generation should use a random MAC address. 157 */ withRandomMacAddress()158 public Builder withRandomMacAddress() { 159 mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64; 160 return this; 161 } 162 163 /** 164 * Specify that IPv6 address generation should use a stable MAC address. 165 */ withStableMacAddress()166 public Builder withStableMacAddress() { 167 mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY; 168 return this; 169 } 170 171 /** 172 * Specify the network to use for provisioning. 173 */ withNetwork(Network network)174 public Builder withNetwork(Network network) { 175 mConfig.mNetwork = network; 176 return this; 177 } 178 179 /** 180 * Specify the display name that the IpClient should use. 181 */ withDisplayName(String displayName)182 public Builder withDisplayName(String displayName) { 183 mConfig.mDisplayName = displayName; 184 return this; 185 } 186 187 /** 188 * Build the configuration using previously specified parameters. 189 */ build()190 public ProvisioningConfiguration build() { 191 return new ProvisioningConfiguration(mConfig); 192 } 193 } 194 195 public boolean mEnableIPv4 = true; 196 public boolean mEnableIPv6 = true; 197 public boolean mUsingMultinetworkPolicyTracker = true; 198 public boolean mUsingIpReachabilityMonitor = true; 199 public int mRequestedPreDhcpActionMs; 200 public InitialConfiguration mInitialConfig; 201 public StaticIpConfiguration mStaticIpConfig; 202 public ApfCapabilities mApfCapabilities; 203 public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS; 204 public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY; 205 public Network mNetwork = null; 206 public String mDisplayName = null; 207 ProvisioningConfiguration()208 public ProvisioningConfiguration() {} // used by Builder 209 ProvisioningConfiguration(ProvisioningConfiguration other)210 public ProvisioningConfiguration(ProvisioningConfiguration other) { 211 mEnableIPv4 = other.mEnableIPv4; 212 mEnableIPv6 = other.mEnableIPv6; 213 mUsingMultinetworkPolicyTracker = other.mUsingMultinetworkPolicyTracker; 214 mUsingIpReachabilityMonitor = other.mUsingIpReachabilityMonitor; 215 mRequestedPreDhcpActionMs = other.mRequestedPreDhcpActionMs; 216 mInitialConfig = InitialConfiguration.copy(other.mInitialConfig); 217 mStaticIpConfig = other.mStaticIpConfig == null 218 ? null 219 : new StaticIpConfiguration(other.mStaticIpConfig); 220 mApfCapabilities = other.mApfCapabilities; 221 mProvisioningTimeoutMs = other.mProvisioningTimeoutMs; 222 mIPv6AddrGenMode = other.mIPv6AddrGenMode; 223 mNetwork = other.mNetwork; 224 mDisplayName = other.mDisplayName; 225 } 226 227 /** 228 * Create a ProvisioningConfigurationParcelable from this ProvisioningConfiguration. 229 */ toStableParcelable()230 public ProvisioningConfigurationParcelable toStableParcelable() { 231 final ProvisioningConfigurationParcelable p = new ProvisioningConfigurationParcelable(); 232 p.enableIPv4 = mEnableIPv4; 233 p.enableIPv6 = mEnableIPv6; 234 p.usingMultinetworkPolicyTracker = mUsingMultinetworkPolicyTracker; 235 p.usingIpReachabilityMonitor = mUsingIpReachabilityMonitor; 236 p.requestedPreDhcpActionMs = mRequestedPreDhcpActionMs; 237 p.initialConfig = mInitialConfig == null ? null : mInitialConfig.toStableParcelable(); 238 p.staticIpConfig = mStaticIpConfig == null 239 ? null 240 : new StaticIpConfiguration(mStaticIpConfig); 241 p.apfCapabilities = mApfCapabilities; // ApfCapabilities is immutable 242 p.provisioningTimeoutMs = mProvisioningTimeoutMs; 243 p.ipv6AddrGenMode = mIPv6AddrGenMode; 244 p.network = mNetwork; 245 p.displayName = mDisplayName; 246 return p; 247 } 248 249 /** 250 * Create a ProvisioningConfiguration from a ProvisioningConfigurationParcelable. 251 */ fromStableParcelable( @ullable ProvisioningConfigurationParcelable p)252 public static ProvisioningConfiguration fromStableParcelable( 253 @Nullable ProvisioningConfigurationParcelable p) { 254 if (p == null) return null; 255 final ProvisioningConfiguration config = new ProvisioningConfiguration(); 256 config.mEnableIPv4 = p.enableIPv4; 257 config.mEnableIPv6 = p.enableIPv6; 258 config.mUsingMultinetworkPolicyTracker = p.usingMultinetworkPolicyTracker; 259 config.mUsingIpReachabilityMonitor = p.usingIpReachabilityMonitor; 260 config.mRequestedPreDhcpActionMs = p.requestedPreDhcpActionMs; 261 config.mInitialConfig = InitialConfiguration.fromStableParcelable(p.initialConfig); 262 config.mStaticIpConfig = p.staticIpConfig == null 263 ? null 264 : new StaticIpConfiguration(p.staticIpConfig); 265 config.mApfCapabilities = p.apfCapabilities; // ApfCapabilities is immutable 266 config.mProvisioningTimeoutMs = p.provisioningTimeoutMs; 267 config.mIPv6AddrGenMode = p.ipv6AddrGenMode; 268 config.mNetwork = p.network; 269 config.mDisplayName = p.displayName; 270 return config; 271 } 272 273 @Override toString()274 public String toString() { 275 return new StringJoiner(", ", getClass().getSimpleName() + "{", "}") 276 .add("mEnableIPv4: " + mEnableIPv4) 277 .add("mEnableIPv6: " + mEnableIPv6) 278 .add("mUsingMultinetworkPolicyTracker: " + mUsingMultinetworkPolicyTracker) 279 .add("mUsingIpReachabilityMonitor: " + mUsingIpReachabilityMonitor) 280 .add("mRequestedPreDhcpActionMs: " + mRequestedPreDhcpActionMs) 281 .add("mInitialConfig: " + mInitialConfig) 282 .add("mStaticIpConfig: " + mStaticIpConfig) 283 .add("mApfCapabilities: " + mApfCapabilities) 284 .add("mProvisioningTimeoutMs: " + mProvisioningTimeoutMs) 285 .add("mIPv6AddrGenMode: " + mIPv6AddrGenMode) 286 .add("mNetwork: " + mNetwork) 287 .add("mDisplayName: " + mDisplayName) 288 .toString(); 289 } 290 291 @Override equals(Object obj)292 public boolean equals(Object obj) { 293 if (!(obj instanceof ProvisioningConfiguration)) return false; 294 final ProvisioningConfiguration other = (ProvisioningConfiguration) obj; 295 return mEnableIPv4 == other.mEnableIPv4 296 && mEnableIPv6 == other.mEnableIPv6 297 && mUsingMultinetworkPolicyTracker == other.mUsingMultinetworkPolicyTracker 298 && mUsingIpReachabilityMonitor == other.mUsingIpReachabilityMonitor 299 && mRequestedPreDhcpActionMs == other.mRequestedPreDhcpActionMs 300 && Objects.equals(mInitialConfig, other.mInitialConfig) 301 && Objects.equals(mStaticIpConfig, other.mStaticIpConfig) 302 && Objects.equals(mApfCapabilities, other.mApfCapabilities) 303 && mProvisioningTimeoutMs == other.mProvisioningTimeoutMs 304 && mIPv6AddrGenMode == other.mIPv6AddrGenMode 305 && Objects.equals(mNetwork, other.mNetwork) 306 && Objects.equals(mDisplayName, other.mDisplayName); 307 } 308 isValid()309 public boolean isValid() { 310 return (mInitialConfig == null) || mInitialConfig.isValid(); 311 } 312 } 313