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