xref: /aosp_15_r20/system/netd/server/InterfaceControllerTest.cpp (revision 8542734a0dd1db395a4d42aae09c37f3c3c3e7a1)
1 /*
2  * Copyright (C) 2017 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 <ifaddrs.h>
18 #include <net/if.h>
19 #include <sys/types.h>
20 
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 
24 #include <netdutils/MockSyscalls.h>
25 #include <netdutils/NetNativeTestBase.h>
26 #include <netdutils/Utils.h>
27 
28 #include "InterfaceController.h"
29 
30 using testing::ByMove;
31 using testing::Invoke;
32 using testing::Return;
33 using testing::StrictMock;
34 using testing::_;
35 
36 namespace android {
37 namespace net {
38 namespace {
39 
40 using netdutils::Fd;
41 using netdutils::getIfaceList;
42 using netdutils::getIfaceNames;
43 using netdutils::makeSlice;
44 using netdutils::ScopedMockSyscalls;
45 using netdutils::Slice;
46 using netdutils::Status;
47 using netdutils::statusFromErrno;
48 using netdutils::StatusOr;
49 using netdutils::UniqueFd;
50 using netdutils::status::ok;
51 
52 constexpr Fd kDevRandomFd(777);
53 constexpr Fd kStableSecretFd(9999);
54 const char kDevRandomPath[] = "/dev/random";
55 const char kTestIface[] = "wlan5";
56 const char kStableSecretProperty[] = "persist.netd.stable_secret";
57 const char kStableSecretPath[] = "/proc/sys/net/ipv6/conf/wlan5/stable_secret";
58 const char kTestIPv6Address[] = "\x20\x01\x0d\xb8\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10";
59 const char kTestIPv6AddressString[] = "2001:db8:506:708:90a:b0c:d0e:f10";
60 
61 // getProperty() and setProperty() are forwarded to this mock
62 class MockProperties {
63   public:
64     MOCK_CONST_METHOD2(get, std::string(const std::string& key, const std::string& dflt));
65     MOCK_CONST_METHOD2(set, Status(const std::string& key, const std::string& val));
66 };
67 
68 }  // namespace
69 
70 class StablePrivacyTest : public NetNativeTestBase {
71   protected:
expectOpenFile(const std::string & path,const Fd fd,int err)72     void expectOpenFile(const std::string& path, const Fd fd, int err) {
73         if (err == 0) {
74             EXPECT_CALL(mSyscalls, open(path, _, _)).WillOnce(Return(ByMove(UniqueFd(fd))));
75             EXPECT_CALL(mSyscalls, close(fd)).WillOnce(Return(ok));
76         } else {
77             EXPECT_CALL(mSyscalls, open(path, _, _))
78                 .WillOnce(Return(ByMove(statusFromErrno(err, "open() failed"))));
79         }
80     }
81 
expectReadFromDevRandom(const std::string & data)82     void expectReadFromDevRandom(const std::string& data) {
83         expectOpenFile(kDevRandomPath, kDevRandomFd, 0);
84         EXPECT_CALL(mSyscalls, read(kDevRandomFd, _)).WillOnce(Invoke([data](Fd, const Slice buf) {
85             EXPECT_EQ(data.size(), buf.size());
86             return take(buf, copy(buf, makeSlice(data)));
87         }));
88     }
89 
expectGetPropertyDefault(const std::string & key)90     void expectGetPropertyDefault(const std::string& key) {
91         EXPECT_CALL(mProperties, get(key, _))
92             .WillOnce(Invoke([](const std::string&, const std::string& dflt) { return dflt; }));
93     }
94 
expectGetProperty(const std::string & key,const std::string & val)95     void expectGetProperty(const std::string& key, const std::string& val) {
96         EXPECT_CALL(mProperties, get(key, _))
97             .WillOnce(Invoke([val](const std::string&, const std::string&) { return val; }));
98     }
99 
expectSetProperty(const std::string & key,const std::string & val,Status status)100     void expectSetProperty(const std::string& key, const std::string& val, Status status) {
101         EXPECT_CALL(mProperties, set(key, val)).WillOnce(Return(std::move(status)));
102     }
103 
expectWriteToFile(const Fd fd,const std::string & val,int err)104     void expectWriteToFile(const Fd fd, const std::string& val, int err) {
105         EXPECT_CALL(mSyscalls, write(fd, _))
106             .WillOnce(Invoke([val, err](Fd, const Slice buf) -> StatusOr<size_t> {
107                 EXPECT_EQ(val, toString(buf));
108                 if (err) {
109                     return statusFromErrno(err, "write() failed");
110                 }
111                 return val.size();
112             }));
113     }
114 
enableStablePrivacyAddresses(const std::string & iface)115     Status enableStablePrivacyAddresses(const std::string& iface) {
116         return InterfaceController::enableStablePrivacyAddresses(iface, mGet, mSet);
117     }
118 
119     StrictMock<ScopedMockSyscalls> mSyscalls;
120     StrictMock<MockProperties> mProperties;
121 
122     const std::function<std::string(const std::string&, const std::string&)> mGet =
__anon901cf00f0602(const std::string& key, const std::string& dflt) 123         [this](const std::string& key, const std::string& dflt) {
124             return mProperties.get(key, dflt);
125         };
126     const std::function<Status(const std::string&, const std::string&)> mSet =
__anon901cf00f0702(const std::string& key, const std::string& val) 127         [this](const std::string& key, const std::string& val) {
128             return mProperties.set(key, val);
129         };
130 };
131 
TEST_F(StablePrivacyTest,PropertyOpenEnoent)132 TEST_F(StablePrivacyTest, PropertyOpenEnoent) {
133     expectOpenFile(kStableSecretPath, kStableSecretFd, ENOENT);
134     EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
135 }
136 
TEST_F(StablePrivacyTest,PropertyOpenEaccess)137 TEST_F(StablePrivacyTest, PropertyOpenEaccess) {
138     expectOpenFile(kStableSecretPath, kStableSecretFd, EACCES);
139     EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
140 }
141 
TEST_F(StablePrivacyTest,FirstBootWriteOkSetPropertyOk)142 TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyOk) {
143     expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
144     expectGetPropertyDefault(kStableSecretProperty);
145     expectReadFromDevRandom(kTestIPv6Address);
146     expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
147     expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, ok);
148     EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface));
149 }
150 
TEST_F(StablePrivacyTest,FirstBootWriteOkSetPropertyFail)151 TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyFail) {
152     const auto kError = statusFromErrno(EINVAL, "");
153     expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
154     expectGetPropertyDefault(kStableSecretProperty);
155     expectReadFromDevRandom(kTestIPv6Address);
156     expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
157     expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, kError);
158     EXPECT_EQ(kError, enableStablePrivacyAddresses(kTestIface));
159 }
160 
TEST_F(StablePrivacyTest,FirstBootWriteFail)161 TEST_F(StablePrivacyTest, FirstBootWriteFail) {
162     expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
163     expectGetPropertyDefault(kStableSecretProperty);
164     expectReadFromDevRandom(kTestIPv6Address);
165     expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, ENOSPC);
166     EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
167 }
168 
TEST_F(StablePrivacyTest,ExistingPropertyWriteOk)169 TEST_F(StablePrivacyTest, ExistingPropertyWriteOk) {
170     expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
171     expectGetProperty(kStableSecretProperty, kTestIPv6AddressString);
172     expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0);
173     EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface));
174 }
175 
TEST_F(StablePrivacyTest,ExistingPropertyWriteFail)176 TEST_F(StablePrivacyTest, ExistingPropertyWriteFail) {
177     expectOpenFile(kStableSecretPath, kStableSecretFd, 0);
178     expectGetProperty(kStableSecretProperty, kTestIPv6AddressString);
179     expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, EACCES);
180     EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface));
181 }
182 
183 class GetIfaceListTest : public NetNativeTestBase {};
184 
TEST_F(GetIfaceListTest,IfaceNames)185 TEST_F(GetIfaceListTest, IfaceNames) {
186     StatusOr<std::vector<std::string>> ifaceNames = getIfaceNames();
187     EXPECT_EQ(ok, ifaceNames.status());
188     struct ifaddrs *ifaddr, *ifa;
189     EXPECT_EQ(0, getifaddrs(&ifaddr));
190     for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
191         const auto val = std::find(
192                 ifaceNames.value().begin(), ifaceNames.value().end(), ifa->ifa_name);
193         EXPECT_NE(ifaceNames.value().end(), val);
194     }
195     freeifaddrs(ifaddr);
196 }
197 
TEST_F(GetIfaceListTest,IfaceExist)198 TEST_F(GetIfaceListTest, IfaceExist) {
199     StatusOr<std::map<std::string, uint32_t>> ifaceMap = getIfaceList();
200     EXPECT_EQ(ok, ifaceMap.status());
201     struct ifaddrs *ifaddr, *ifa;
202     EXPECT_EQ(0, getifaddrs(&ifaddr));
203     for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
204         char* ifa_name = ifa->ifa_name;
205         EXPECT_NE(ifa_name, nullptr);
206         uint32_t ifaceIndex = if_nametoindex(ifa_name);
207         const auto ifacePair = ifaceMap.value().find(ifa->ifa_name);
208         EXPECT_NE(ifaceMap.value().end(), ifacePair);
209         EXPECT_EQ(ifaceIndex, ifacePair->second);
210     }
211     freeifaddrs(ifaddr);
212 }
213 
214 }  // namespace net
215 }  // namespace android
216