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