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