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