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 #include <VtsCoreUtil.h>
18 
19 #include <android-base/logging.h>
20 #include <cutils/properties.h>
21 
22 #include <gtest/gtest.h>
23 #include <hidl/GtestPrinter.h>
24 #include <hidl/ServiceManagement.h>
25 
26 #include <android/hardware/wifi/1.0/IWifi.h>
27 #include <android/hardware/wifi/hostapd/1.2/IHostapd.h>
28 
29 #include "hostapd_hidl_call_util.h"
30 #include "hostapd_hidl_test_utils.h"
31 
32 using ::android::sp;
33 using ::android::hardware::hidl_string;
34 using ::android::hardware::Return;
35 using ::android::hardware::Void;
36 using ::android::hardware::wifi::hostapd::V1_2::DebugLevel;
37 using ::android::hardware::wifi::hostapd::V1_2::HostapdStatusCode;
38 using ::android::hardware::wifi::hostapd::V1_2::Ieee80211ReasonCode;
39 using ::android::hardware::wifi::hostapd::V1_2::IHostapd;
40 using ::android::hardware::wifi::V1_0::IWifi;
41 
42 namespace {
43 constexpr unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1',
44                                      '2', '3', '4', '5'};
45 constexpr char kNwPassphrase[] = "test12345";
46 constexpr char kInvalidMaxPskNwPassphrase[] =
47     "0123456789012345678901234567890123456789012345678901234567890123456789";
48 constexpr char kInvalidMinPskNwPassphrase[] = "test";
49 constexpr int kIfaceChannel = 6;
50 constexpr int kIfaceInvalidChannel = 567;
51 constexpr uint8_t kTestZeroMacAddr[] = {[0 ... 5] = 0x0};
52 constexpr Ieee80211ReasonCode kTestDisconnectReasonCode =
53     Ieee80211ReasonCode::WLAN_REASON_UNSPECIFIED;
54 }  // namespace
55 
56 class HostapdHidlTest
57     : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
58    public:
SetUp()59     virtual void SetUp() override {
60         wifi_instance_name_ = std::get<0>(GetParam());
61         hostapd_instance_name_ = std::get<1>(GetParam());
62         stopSupplicantIfNeeded(wifi_instance_name_);
63         startHostapdAndWaitForHidlService(wifi_instance_name_,
64                                           hostapd_instance_name_);
65         hostapd_ = IHostapd::getService(hostapd_instance_name_);
66         ASSERT_NE(hostapd_.get(), nullptr);
67         isAcsSupport_ = testing::checkSubstringInCommandOutput(
68             "/system/bin/cmd wifi get-softap-supported-features",
69             "wifi_softap_acs_supported");
70         isWpa3SaeSupport_ = testing::checkSubstringInCommandOutput(
71             "/system/bin/cmd wifi get-softap-supported-features",
72             "wifi_softap_wpa3_sae_supported");
73     }
74 
TearDown()75     virtual void TearDown() override { stopHostapd(hostapd_instance_name_); }
76 
77    protected:
78     bool isWpa3SaeSupport_ = false;
79     bool isAcsSupport_ = false;
getPrimaryWlanIfaceName()80     std::string getPrimaryWlanIfaceName() {
81         std::array<char, PROPERTY_VALUE_MAX> buffer;
82         auto res = property_get("ro.vendor.wifi.sap.interface", buffer.data(),
83                                 nullptr);
84         if (res > 0) return buffer.data();
85         property_get("wifi.interface", buffer.data(), "wlan0");
86         return buffer.data();
87     }
88 
getIfaceParamsWithoutAcs()89     IHostapd::IfaceParams getIfaceParamsWithoutAcs() {
90         ::android::hardware::wifi::hostapd::V1_0::IHostapd::IfaceParams
91             iface_params;
92         ::android::hardware::wifi::hostapd::V1_1::IHostapd::IfaceParams
93             iface_params_1_1;
94         IHostapd::IfaceParams iface_params_1_2;
95 
96         iface_params.ifaceName = getPrimaryWlanIfaceName();
97         iface_params.hwModeParams.enable80211N = true;
98         iface_params.hwModeParams.enable80211AC = false;
99         iface_params.channelParams.enableAcs = false;
100         iface_params.channelParams.acsShouldExcludeDfs = false;
101         iface_params.channelParams.channel = kIfaceChannel;
102         iface_params_1_1.V1_0 = iface_params;
103         iface_params_1_2.V1_1 = iface_params_1_1;
104         // Newly added attributes in V1_2
105         iface_params_1_2.hwModeParams.enable80211AX = false;
106         iface_params_1_2.hwModeParams.enable6GhzBand = false;
107         iface_params_1_2.channelParams.bandMask = 0;
108         iface_params_1_2.channelParams.bandMask |=
109             IHostapd::BandMask::BAND_2_GHZ;
110         return iface_params_1_2;
111     }
112 
getIfaceParamsWithAcs()113     IHostapd::IfaceParams getIfaceParamsWithAcs() {
114         // First get the settings for WithoutAcs and then make changes
115         IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs();
116         iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = true;
117         iface_params_1_2.V1_1.V1_0.channelParams.acsShouldExcludeDfs = true;
118         iface_params_1_2.V1_1.V1_0.channelParams.channel = 0;
119         iface_params_1_2.channelParams.bandMask |=
120             IHostapd::BandMask::BAND_5_GHZ;
121 
122         return iface_params_1_2;
123     }
124 
getIfaceParamsWithAcsAndFreqRange()125     IHostapd::IfaceParams getIfaceParamsWithAcsAndFreqRange() {
126         IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithAcs();
127         ::android::hardware::wifi::hostapd::V1_2::IHostapd::AcsFrequencyRange
128             acsFrequencyRange;
129         acsFrequencyRange.start = 2412;
130         acsFrequencyRange.end = 2462;
131         std::vector<::android::hardware::wifi::hostapd::V1_2::IHostapd::
132                         AcsFrequencyRange>
133             vec_acsFrequencyRange;
134         vec_acsFrequencyRange.push_back(acsFrequencyRange);
135         iface_params_1_2.channelParams.acsChannelFreqRangesMhz =
136             vec_acsFrequencyRange;
137         return iface_params_1_2;
138     }
139 
getIfaceParamsWithAcsAndInvalidFreqRange()140     IHostapd::IfaceParams getIfaceParamsWithAcsAndInvalidFreqRange() {
141         IHostapd::IfaceParams iface_params_1_2 =
142             getIfaceParamsWithAcsAndFreqRange();
143         iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].start = 222;
144         iface_params_1_2.channelParams.acsChannelFreqRangesMhz[0].end = 999;
145         return iface_params_1_2;
146     }
147 
getOpenNwParams()148     IHostapd::NetworkParams getOpenNwParams() {
149         IHostapd::NetworkParams nw_params_1_2;
150         ::android::hardware::wifi::hostapd::V1_0::IHostapd::NetworkParams
151             nw_params_1_0;
152         nw_params_1_0.ssid =
153             std::vector<uint8_t>(kNwSsid, kNwSsid + sizeof(kNwSsid));
154         nw_params_1_0.isHidden = false;
155         nw_params_1_2.V1_0 = nw_params_1_0;
156         nw_params_1_2.encryptionType = IHostapd::EncryptionType::NONE;
157         return nw_params_1_2;
158     }
159 
getPskNwParams()160     IHostapd::NetworkParams getPskNwParams() {
161         IHostapd::NetworkParams nw_params_1_2 = getOpenNwParams();
162         nw_params_1_2.encryptionType = IHostapd::EncryptionType::WPA2;
163         nw_params_1_2.passphrase = kNwPassphrase;
164         return nw_params_1_2;
165     }
166 
getInvalidPskNwParams()167     IHostapd::NetworkParams getInvalidPskNwParams() {
168         IHostapd::NetworkParams nw_params_1_2 = getOpenNwParams();
169         nw_params_1_2.encryptionType = IHostapd::EncryptionType::WPA2;
170         nw_params_1_2.passphrase = kInvalidMaxPskNwPassphrase;
171 
172         return nw_params_1_2;
173     }
174 
getSaeTransitionNwParams()175     IHostapd::NetworkParams getSaeTransitionNwParams() {
176         IHostapd::NetworkParams nw_params_1_2 = getOpenNwParams();
177         nw_params_1_2.encryptionType =
178             IHostapd::EncryptionType::WPA3_SAE_TRANSITION;
179         nw_params_1_2.passphrase = kNwPassphrase;
180         return nw_params_1_2;
181     }
182 
getInvalidSaeTransitionNwParams()183     IHostapd::NetworkParams getInvalidSaeTransitionNwParams() {
184         IHostapd::NetworkParams nw_params_1_2 = getOpenNwParams();
185         nw_params_1_2.encryptionType = IHostapd::EncryptionType::WPA2;
186         nw_params_1_2.passphrase = kInvalidMinPskNwPassphrase;
187         return nw_params_1_2;
188     }
189 
getSaeNwParams()190     IHostapd::NetworkParams getSaeNwParams() {
191         IHostapd::NetworkParams nw_params_1_2 = getOpenNwParams();
192         nw_params_1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE;
193         nw_params_1_2.passphrase = kNwPassphrase;
194         return nw_params_1_2;
195     }
196 
getInvalidSaeNwParams()197     IHostapd::NetworkParams getInvalidSaeNwParams() {
198         IHostapd::NetworkParams nw_params_1_2 = getOpenNwParams();
199         nw_params_1_2.encryptionType = IHostapd::EncryptionType::WPA3_SAE;
200         nw_params_1_2.passphrase = "";
201         return nw_params_1_2;
202     }
203 
getIfaceParamsWithInvalidChannel()204     IHostapd::IfaceParams getIfaceParamsWithInvalidChannel() {
205         IHostapd::IfaceParams iface_params_1_2 = getIfaceParamsWithoutAcs();
206         iface_params_1_2.V1_1.V1_0.channelParams.channel = kIfaceInvalidChannel;
207         return iface_params_1_2;
208     }
209 
210     // IHostapd object used for all tests in this fixture.
211     sp<IHostapd> hostapd_;
212     std::string wifi_instance_name_;
213     std::string hostapd_instance_name_;
214 };
215 
216 /**
217  * Adds an access point with PSK network config & ACS enabled.
218  * Access point creation should pass.
219  */
TEST_P(HostapdHidlTest,AddPskAccessPointWithAcs)220 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcs) {
221     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
222     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
223                               getIfaceParamsWithAcs(), getPskNwParams());
224     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
225 }
226 
227 /**
228  * Adds an access point with PSK network config, ACS enabled & frequency Range.
229  * Access point creation should pass.
230  */
TEST_P(HostapdHidlTest,AddPskAccessPointWithAcsAndFreqRange)231 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndFreqRange) {
232     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
233     auto status =
234         HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
235                     getIfaceParamsWithAcsAndFreqRange(), getPskNwParams());
236     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
237 }
238 
239 /**
240  * Adds an access point with invalid channel range.
241  * Access point creation should fail.
242  */
TEST_P(HostapdHidlTest,AddPskAccessPointWithAcsAndInvalidFreqRange)243 TEST_P(HostapdHidlTest, AddPskAccessPointWithAcsAndInvalidFreqRange) {
244     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
245     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
246                               getIfaceParamsWithAcsAndInvalidFreqRange(),
247                               getPskNwParams());
248     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
249 }
250 
251 /**
252  * Adds an access point with Open network config & ACS enabled.
253  * Access point creation should pass.
254  */
TEST_P(HostapdHidlTest,AddOpenAccessPointWithAcs)255 TEST_P(HostapdHidlTest, AddOpenAccessPointWithAcs) {
256     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
257     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
258                               getIfaceParamsWithAcs(), getOpenNwParams());
259     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
260 }
261 
262 /**
263  * Adds an access point with PSK network config & ACS disabled.
264  * Access point creation should pass.
265  */
TEST_P(HostapdHidlTest,AddPskAccessPointWithoutAcs)266 TEST_P(HostapdHidlTest, AddPskAccessPointWithoutAcs) {
267     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
268                               getIfaceParamsWithoutAcs(), getPskNwParams());
269     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
270 }
271 
272 /**
273  * Adds an access point with Open network config & ACS disabled.
274  * Access point creation should pass.
275  */
TEST_P(HostapdHidlTest,AddOpenAccessPointWithoutAcs)276 TEST_P(HostapdHidlTest, AddOpenAccessPointWithoutAcs) {
277     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
278                               getIfaceParamsWithoutAcs(), getOpenNwParams());
279     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
280 }
281 
282 /**
283  * Adds an access point with SAE Transition network config & ACS disabled.
284  * Access point creation should pass.
285  */
TEST_P(HostapdHidlTest,AddSaeTransitionAccessPointWithoutAcs)286 TEST_P(HostapdHidlTest, AddSaeTransitionAccessPointWithoutAcs) {
287     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
288     auto status =
289         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
290                     getSaeTransitionNwParams());
291     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
292 }
293 
294 /**
295  * Adds an access point with SAE network config & ACS disabled.
296  * Access point creation should pass.
297  */
TEST_P(HostapdHidlTest,AddSAEAccessPointWithoutAcs)298 TEST_P(HostapdHidlTest, AddSAEAccessPointWithoutAcs) {
299     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
300     auto status = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
301                               getIfaceParamsWithoutAcs(), getSaeNwParams());
302     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
303 }
304 
305 /**
306  * Adds & then removes an access point with PSK network config & ACS enabled.
307  * Access point creation & removal should pass.
308  */
TEST_P(HostapdHidlTest,RemoveAccessPointWithAcs)309 TEST_P(HostapdHidlTest, RemoveAccessPointWithAcs) {
310     if (!isAcsSupport_) GTEST_SKIP() << "Missing ACS support";
311     auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
312                                   getIfaceParamsWithAcs(), getPskNwParams());
313     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
314     auto status =
315         HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
316     EXPECT_EQ(
317         android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
318         status.code);
319 }
320 
321 /**
322  * Adds & then removes an access point with PSK network config & ACS disabled.
323  * Access point creation & removal should pass.
324  */
TEST_P(HostapdHidlTest,RemoveAccessPointWithoutAcs)325 TEST_P(HostapdHidlTest, RemoveAccessPointWithoutAcs) {
326     auto status_1_2 = HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
327                                   getIfaceParamsWithoutAcs(), getPskNwParams());
328     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
329     auto status =
330         HIDL_INVOKE(hostapd_, removeAccessPoint, getPrimaryWlanIfaceName());
331     EXPECT_EQ(
332         android::hardware::wifi::hostapd::V1_0::HostapdStatusCode::SUCCESS,
333         status.code);
334 }
335 
336 /**
337  * Adds an access point with invalid channel.
338  * Access point creation should fail.
339  */
TEST_P(HostapdHidlTest,AddPskAccessPointWithInvalidChannel)340 TEST_P(HostapdHidlTest, AddPskAccessPointWithInvalidChannel) {
341     auto status =
342         HIDL_INVOKE(hostapd_, addAccessPoint_1_2,
343                     getIfaceParamsWithInvalidChannel(), getPskNwParams());
344     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
345 }
346 
347 /**
348  * Adds an access point with invalid PSK network config.
349  * Access point creation should fail.
350  */
TEST_P(HostapdHidlTest,AddInvalidPskAccessPointWithoutAcs)351 TEST_P(HostapdHidlTest, AddInvalidPskAccessPointWithoutAcs) {
352     auto status =
353         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
354                     getInvalidPskNwParams());
355     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
356 }
357 
358 /**
359  * Adds an access point with invalid SAE transition network config.
360  * Access point creation should fail.
361  */
TEST_P(HostapdHidlTest,AddInvalidSaeTransitionAccessPointWithoutAcs)362 TEST_P(HostapdHidlTest, AddInvalidSaeTransitionAccessPointWithoutAcs) {
363     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
364     auto status =
365         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
366                     getInvalidSaeTransitionNwParams());
367     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
368 }
369 
370 /**
371  * Adds an access point with invalid SAE network config.
372  * Access point creation should fail.
373  */
TEST_P(HostapdHidlTest,AddInvalidSaeAccessPointWithoutAcs)374 TEST_P(HostapdHidlTest, AddInvalidSaeAccessPointWithoutAcs) {
375     if (!isWpa3SaeSupport_) GTEST_SKIP() << "Missing SAE support";
376     auto status =
377         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
378                     getInvalidSaeNwParams());
379     EXPECT_NE(HostapdStatusCode::SUCCESS, status.code);
380 }
381 
382 /**
383  * forceClientDisconnect should return FAILURE_IFACE_UNKNOWN
384  * when hotspot interface doesn't init..
385  */
TEST_P(HostapdHidlTest,DisconnectClientWhenIfaceNotAvailable)386 TEST_P(HostapdHidlTest, DisconnectClientWhenIfaceNotAvailable) {
387     auto status =
388         HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
389                     kTestZeroMacAddr, kTestDisconnectReasonCode);
390     EXPECT_EQ(HostapdStatusCode::FAILURE_IFACE_UNKNOWN, status.code);
391 }
392 
393 /**
394  * forceClientDisconnect should return FAILURE_CLIENT_UNKNOWN
395  * when hotspot interface available.
396  */
TEST_P(HostapdHidlTest,DisconnectClientWhenIfacAvailable)397 TEST_P(HostapdHidlTest, DisconnectClientWhenIfacAvailable) {
398     auto status_1_2 =
399         HIDL_INVOKE(hostapd_, addAccessPoint_1_2, getIfaceParamsWithoutAcs(),
400                     getOpenNwParams());
401     EXPECT_EQ(HostapdStatusCode::SUCCESS, status_1_2.code);
402 
403     status_1_2 =
404         HIDL_INVOKE(hostapd_, forceClientDisconnect, getPrimaryWlanIfaceName(),
405                     kTestZeroMacAddr, kTestDisconnectReasonCode);
406     EXPECT_EQ(HostapdStatusCode::FAILURE_CLIENT_UNKNOWN, status_1_2.code);
407 }
408 
409 /*
410  * SetDebugParams
411  */
TEST_P(HostapdHidlTest,SetDebugParams)412 TEST_P(HostapdHidlTest, SetDebugParams) {
413     auto status = HIDL_INVOKE(hostapd_, setDebugParams, DebugLevel::EXCESSIVE);
414     EXPECT_EQ(HostapdStatusCode::SUCCESS, status.code);
415 }
416 
417 INSTANTIATE_TEST_CASE_P(
418     PerInstance, HostapdHidlTest,
419     testing::Combine(
420         testing::ValuesIn(
421             android::hardware::getAllHalInstanceNames(IWifi::descriptor)),
422         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
423             android::hardware::wifi::hostapd::V1_2::IHostapd::descriptor))),
424     android::hardware::PrintInstanceTupleNameToString<>);
425