1 /*
2  * Copyright (C) 2020 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 com.android.server.vcn;
18 
19 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
20 
21 import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
22 import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
23 import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
24 
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNull;
27 import static org.mockito.Matchers.any;
28 import static org.mockito.Matchers.eq;
29 import static org.mockito.Mockito.CALLS_REAL_METHODS;
30 import static org.mockito.Mockito.atLeastOnce;
31 import static org.mockito.Mockito.doReturn;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.times;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.verifyNoMoreInteractions;
37 
38 import android.annotation.NonNull;
39 import android.content.Context;
40 import android.net.ConnectivityDiagnosticsManager;
41 import android.net.ConnectivityManager;
42 import android.net.InetAddresses;
43 import android.net.IpSecConfig;
44 import android.net.IpSecManager;
45 import android.net.IpSecTransform;
46 import android.net.IpSecTunnelInterfaceResponse;
47 import android.net.LinkAddress;
48 import android.net.LinkProperties;
49 import android.net.Network;
50 import android.net.NetworkCapabilities;
51 import android.net.TelephonyNetworkSpecifier;
52 import android.net.ipsec.ike.ChildSessionCallback;
53 import android.net.ipsec.ike.IkeSessionCallback;
54 import android.net.ipsec.ike.IkeSessionConfiguration;
55 import android.net.ipsec.ike.IkeSessionConnectionInfo;
56 import android.net.vcn.FeatureFlags;
57 import android.net.vcn.VcnGatewayConnectionConfig;
58 import android.net.vcn.VcnGatewayConnectionConfigTest;
59 import android.os.ParcelUuid;
60 import android.os.PowerManager;
61 import android.os.test.TestLooper;
62 import android.telephony.SubscriptionInfo;
63 
64 import com.android.internal.util.State;
65 import com.android.internal.util.WakeupMessage;
66 import com.android.server.IpSecService;
67 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
68 import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
69 import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback;
70 import com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
71 import com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
72 import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock;
73 import com.android.server.vcn.routeselection.UnderlyingNetworkController;
74 import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
75 
76 import org.junit.Before;
77 import org.mockito.ArgumentCaptor;
78 
79 import java.net.InetAddress;
80 import java.util.Collections;
81 import java.util.UUID;
82 import java.util.concurrent.TimeUnit;
83 
84 public class VcnGatewayConnectionTestBase {
85     protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
86     protected static final SubscriptionInfo TEST_SUB_INFO = mock(SubscriptionInfo.class);
87 
88     static {
89         doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid();
90     }
91 
92     protected static final InetAddress TEST_ADDR = InetAddresses.parseNumericAddress("2001:db8::1");
93     protected static final InetAddress TEST_ADDR_2 =
94             InetAddresses.parseNumericAddress("2001:db8::2");
95     protected static final InetAddress TEST_ADDR_V4 =
96             InetAddresses.parseNumericAddress("192.0.2.1");
97     protected static final InetAddress TEST_ADDR_V4_2 =
98             InetAddresses.parseNumericAddress("192.0.2.2");
99     protected static final InetAddress TEST_DNS_ADDR =
100             InetAddresses.parseNumericAddress("2001:DB8:0:1::");
101     protected static final InetAddress TEST_DNS_ADDR_2 =
102             InetAddresses.parseNumericAddress("2001:DB8:0:2::");
103     protected static final LinkAddress TEST_INTERNAL_ADDR =
104             new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:1::"), 64);
105     protected static final LinkAddress TEST_INTERNAL_ADDR_2 =
106             new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:2::"), 64);
107     protected static final LinkAddress TEST_INTERNAL_ADDR_3 =
108             new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:1:3::"), 64);
109 
110     protected static final int TEST_IPSEC_SPI_VALUE = 0x1234;
111     protected static final int TEST_IPSEC_SPI_RESOURCE_ID = 1;
112     protected static final int TEST_IPSEC_TRANSFORM_RESOURCE_ID = 2;
113     protected static final int TEST_IPSEC_TUNNEL_RESOURCE_ID = 3;
114     protected static final int TEST_SUB_ID = 5;
115     protected static final long ELAPSED_REAL_TIME = 123456789L;
116     protected static final String TEST_IPSEC_TUNNEL_IFACE = "IPSEC_IFACE";
117 
getTestNetworkRecord( Network network, NetworkCapabilities networkCapabilities, LinkProperties linkProperties, boolean isBlocked)118     protected static UnderlyingNetworkRecord getTestNetworkRecord(
119             Network network,
120             NetworkCapabilities networkCapabilities,
121             LinkProperties linkProperties,
122             boolean isBlocked) {
123         return new UnderlyingNetworkRecord(network, networkCapabilities, linkProperties, isBlocked);
124     }
125 
126     protected static final String TEST_TCP_BUFFER_SIZES_1 = "1,2,3,4";
127     protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_1 =
128             getTestNetworkRecord(
129                     mock(Network.class, CALLS_REAL_METHODS),
130                     new NetworkCapabilities.Builder()
131                             .addTransportType(TRANSPORT_CELLULAR)
132                             .setNetworkSpecifier(new TelephonyNetworkSpecifier(TEST_SUB_ID))
133                             .build(),
134                     new LinkProperties(),
135                     false /* blocked */);
136 
137     static {
138         TEST_UNDERLYING_NETWORK_RECORD_1.linkProperties.setMtu(1500);
139         TEST_UNDERLYING_NETWORK_RECORD_1.linkProperties.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES_1);
140     }
141 
142     protected static final String TEST_TCP_BUFFER_SIZES_2 = "2,3,4,5";
143     protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_2 =
144             getTestNetworkRecord(
145                     mock(Network.class, CALLS_REAL_METHODS),
146                     new NetworkCapabilities(),
147                     new LinkProperties(),
148                     false /* blocked */);
149 
150     static {
151         TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.setMtu(1460);
152         TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.setTcpBufferSizes(TEST_TCP_BUFFER_SIZES_2);
153     }
154 
155     protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT =
156             new TelephonySubscriptionSnapshot(
157                     TEST_SUB_ID,
158                     Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO),
159                     Collections.EMPTY_MAP,
160                     Collections.EMPTY_MAP);
161 
162     @NonNull protected final Context mContext;
163     @NonNull protected final TestLooper mTestLooper;
164     @NonNull protected final VcnNetworkProvider mVcnNetworkProvider;
165     @NonNull protected final FeatureFlags mFeatureFlags;
166     @NonNull protected final VcnContext mVcnContext;
167     @NonNull protected final VcnGatewayConnectionConfig mConfig;
168     @NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback;
169     @NonNull protected final VcnGatewayConnection.Dependencies mDeps;
170     @NonNull protected final UnderlyingNetworkController mUnderlyingNetworkController;
171     @NonNull protected final VcnWakeLock mWakeLock;
172     @NonNull protected final WakeupMessage mTeardownTimeoutAlarm;
173     @NonNull protected final WakeupMessage mDisconnectRequestAlarm;
174     @NonNull protected final WakeupMessage mRetryTimeoutAlarm;
175     @NonNull protected final WakeupMessage mSafeModeTimeoutAlarm;
176 
177     @NonNull protected final IpSecService mIpSecSvc;
178     @NonNull protected final ConnectivityManager mConnMgr;
179     @NonNull protected final ConnectivityDiagnosticsManager mConnDiagMgr;
180 
181     @NonNull protected final IkeSessionConnectionInfo mIkeConnectionInfo;
182     @NonNull protected final IkeSessionConfiguration mIkeSessionConfiguration;
183 
184     protected VcnIkeSession mMockIkeSession;
185     protected VcnGatewayConnection mGatewayConnection;
186 
VcnGatewayConnectionTestBase()187     public VcnGatewayConnectionTestBase() {
188         mContext = mock(Context.class);
189         mTestLooper = new TestLooper();
190         mVcnNetworkProvider = mock(VcnNetworkProvider.class);
191         mFeatureFlags = mock(FeatureFlags.class);
192         mVcnContext = mock(VcnContext.class);
193         mConfig = VcnGatewayConnectionConfigTest.buildTestConfig();
194         mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class);
195         mDeps = mock(VcnGatewayConnection.Dependencies.class);
196         mUnderlyingNetworkController = mock(UnderlyingNetworkController.class);
197         mWakeLock = mock(VcnWakeLock.class);
198         mTeardownTimeoutAlarm = mock(WakeupMessage.class);
199         mDisconnectRequestAlarm = mock(WakeupMessage.class);
200         mRetryTimeoutAlarm = mock(WakeupMessage.class);
201         mSafeModeTimeoutAlarm = mock(WakeupMessage.class);
202 
203         mIpSecSvc = mock(IpSecService.class);
204         setupIpSecManager(mContext, mIpSecSvc);
205 
206         mConnMgr = mock(ConnectivityManager.class);
207         VcnTestUtils.setupSystemService(
208                 mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
209 
210         mConnDiagMgr = mock(ConnectivityDiagnosticsManager.class);
211         VcnTestUtils.setupSystemService(
212                 mContext,
213                 mConnDiagMgr,
214                 Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
215                 ConnectivityDiagnosticsManager.class);
216 
217         mIkeConnectionInfo =
218                 new IkeSessionConnectionInfo(TEST_ADDR, TEST_ADDR_2, mock(Network.class));
219         mIkeSessionConfiguration = new IkeSessionConfiguration.Builder(mIkeConnectionInfo).build();
220 
221         doReturn(mContext).when(mVcnContext).getContext();
222         doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper();
223         doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
224         doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags();
225         doReturn(true).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
226         doReturn(true).when(mVcnContext).isFlagIpSecTransformStateEnabled();
227         doReturn(true).when(mVcnContext).isFlagNetworkMetricMonitorEnabled();
228 
229         doReturn(mUnderlyingNetworkController)
230                 .when(mDeps)
231                 .newUnderlyingNetworkController(any(), any(), any(), any(), any());
232         doReturn(mWakeLock)
233                 .when(mDeps)
234                 .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());
235         doReturn(1)
236                 .when(mDeps)
237                 .getParallelTunnelCount(eq(TEST_SUBSCRIPTION_SNAPSHOT), eq(TEST_SUB_GRP));
238 
239         setUpWakeupMessage(mTeardownTimeoutAlarm, VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM);
240         setUpWakeupMessage(mDisconnectRequestAlarm, VcnGatewayConnection.DISCONNECT_REQUEST_ALARM);
241         setUpWakeupMessage(mRetryTimeoutAlarm, VcnGatewayConnection.RETRY_TIMEOUT_ALARM);
242         setUpWakeupMessage(mSafeModeTimeoutAlarm, VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM);
243 
244         doReturn(ELAPSED_REAL_TIME).when(mDeps).getElapsedRealTime();
245     }
246 
setUpWakeupMessage( @onNull WakeupMessage msg, @NonNull String cmdName, VcnGatewayConnection.Dependencies deps)247     protected void setUpWakeupMessage(
248             @NonNull WakeupMessage msg,
249             @NonNull String cmdName,
250             VcnGatewayConnection.Dependencies deps) {
251         doReturn(msg).when(deps).newWakeupMessage(eq(mVcnContext), any(), eq(cmdName), any());
252     }
253 
setUpWakeupMessage(@onNull WakeupMessage msg, @NonNull String cmdName)254     private void setUpWakeupMessage(@NonNull WakeupMessage msg, @NonNull String cmdName) {
255         setUpWakeupMessage(msg, cmdName, mDeps);
256     }
257 
258     @Before
setUp()259     public void setUp() throws Exception {
260         IpSecTunnelInterfaceResponse resp =
261                 new IpSecTunnelInterfaceResponse(
262                         IpSecManager.Status.OK,
263                         TEST_IPSEC_TUNNEL_RESOURCE_ID,
264                         TEST_IPSEC_TUNNEL_IFACE);
265         doReturn(resp).when(mIpSecSvc).createTunnelInterface(any(), any(), any(), any(), any());
266 
267         mMockIkeSession = mock(VcnIkeSession.class);
268         doReturn(mMockIkeSession).when(mDeps).newIkeSession(any(), any(), any(), any(), any());
269 
270         mGatewayConnection =
271                 new VcnGatewayConnection(
272                         mVcnContext,
273                         TEST_SUB_GRP,
274                         TEST_SUBSCRIPTION_SNAPSHOT,
275                         mConfig,
276                         mGatewayStatusCallback,
277                         true /* isMobileDataEnabled */,
278                         mDeps);
279     }
280 
makeDummyIpSecTransform()281     protected IpSecTransform makeDummyIpSecTransform() throws Exception {
282         return new IpSecTransform(mContext, new IpSecConfig());
283     }
284 
getIkeSessionCallback()285     protected IkeSessionCallback getIkeSessionCallback() {
286         ArgumentCaptor<IkeSessionCallback> captor =
287                 ArgumentCaptor.forClass(IkeSessionCallback.class);
288         verify(mDeps).newIkeSession(any(), any(), any(), captor.capture(), any());
289         return captor.getValue();
290     }
291 
getChildSessionCallback()292     protected VcnChildSessionCallback getChildSessionCallback() {
293         ArgumentCaptor<ChildSessionCallback> captor =
294                 ArgumentCaptor.forClass(ChildSessionCallback.class);
295         verify(mDeps, atLeastOnce()).newIkeSession(any(), any(), any(), any(), captor.capture());
296         return (VcnChildSessionCallback) captor.getValue();
297     }
298 
verifyWakeLockSetUp()299     protected void verifyWakeLockSetUp() {
300         verify(mDeps).newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());
301         verifyNoMoreInteractions(mWakeLock);
302     }
303 
verifyWakeLockAcquired()304     protected void verifyWakeLockAcquired() {
305         verify(mWakeLock).acquire();
306         verifyNoMoreInteractions(mWakeLock);
307     }
308 
verifyWakeLockReleased()309     protected void verifyWakeLockReleased() {
310         verify(mWakeLock).release();
311         verifyNoMoreInteractions(mWakeLock);
312     }
313 
verifyWakeupMessageSetUpAndGetCallback( @onNull String tag, @NonNull WakeupMessage msg, long delayInMillis, boolean expectCanceled)314     private Runnable verifyWakeupMessageSetUpAndGetCallback(
315             @NonNull String tag,
316             @NonNull WakeupMessage msg,
317             long delayInMillis,
318             boolean expectCanceled) {
319         ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
320         verify(mDeps).newWakeupMessage(eq(mVcnContext), any(), eq(tag), runnableCaptor.capture());
321 
322         verify(mDeps, atLeastOnce()).getElapsedRealTime();
323         verify(msg).schedule(ELAPSED_REAL_TIME + delayInMillis);
324         verify(msg, expectCanceled ? times(1) : never()).cancel();
325 
326         return runnableCaptor.getValue();
327     }
328 
verifyTeardownTimeoutAlarmAndGetCallback(boolean expectCanceled)329     protected Runnable verifyTeardownTimeoutAlarmAndGetCallback(boolean expectCanceled) {
330         return verifyWakeupMessageSetUpAndGetCallback(
331                 VcnGatewayConnection.TEARDOWN_TIMEOUT_ALARM,
332                 mTeardownTimeoutAlarm,
333                 TimeUnit.SECONDS.toMillis(VcnGatewayConnection.TEARDOWN_TIMEOUT_SECONDS),
334                 expectCanceled);
335     }
336 
verifyDisconnectRequestAlarmAndGetCallback(boolean expectCanceled)337     protected Runnable verifyDisconnectRequestAlarmAndGetCallback(boolean expectCanceled) {
338         return verifyWakeupMessageSetUpAndGetCallback(
339                 VcnGatewayConnection.DISCONNECT_REQUEST_ALARM,
340                 mDisconnectRequestAlarm,
341                 TimeUnit.SECONDS.toMillis(
342                         VcnGatewayConnection.NETWORK_LOSS_DISCONNECT_TIMEOUT_SECONDS),
343                 expectCanceled);
344     }
345 
verifyRetryTimeoutAlarmAndGetCallback( long delayInMillis, boolean expectCanceled)346     protected Runnable verifyRetryTimeoutAlarmAndGetCallback(
347             long delayInMillis, boolean expectCanceled) {
348         return verifyWakeupMessageSetUpAndGetCallback(
349                 VcnGatewayConnection.RETRY_TIMEOUT_ALARM,
350                 mRetryTimeoutAlarm,
351                 delayInMillis,
352                 expectCanceled);
353     }
354 
verifySafeModeTimeoutAlarmAndGetCallback(boolean expectCanceled)355     protected Runnable verifySafeModeTimeoutAlarmAndGetCallback(boolean expectCanceled) {
356         return verifyWakeupMessageSetUpAndGetCallback(
357                 VcnGatewayConnection.SAFEMODE_TIMEOUT_ALARM,
358                 mSafeModeTimeoutAlarm,
359                 TimeUnit.SECONDS.toMillis(VcnGatewayConnection.SAFEMODE_TIMEOUT_SECONDS),
360                 expectCanceled);
361     }
362 
verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode)363     protected void verifySafeModeStateAndCallbackFired(int invocationCount, boolean isInSafeMode) {
364         verify(mGatewayStatusCallback, times(invocationCount)).onSafeModeStatusChanged();
365         assertEquals(isInSafeMode, mGatewayConnection.isInSafeMode());
366     }
367 
verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent( @onNull State expectedState)368     protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
369             @NonNull State expectedState) {
370         // Set a VcnNetworkAgent, and expect it to be unregistered and cleared
371         final VcnNetworkAgent mockNetworkAgent = mock(VcnNetworkAgent.class);
372         mGatewayConnection.setNetworkAgent(mockNetworkAgent);
373 
374         // SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial
375         // state)
376         final Runnable delayedEvent =
377                 verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
378         delayedEvent.run();
379         mTestLooper.dispatchAll();
380 
381         assertEquals(expectedState, mGatewayConnection.getCurrentState());
382         verifySafeModeStateAndCallbackFired(1, true);
383 
384         verify(mockNetworkAgent).unregister();
385         assertNull(mGatewayConnection.getNetworkAgent());
386     }
387 }
388