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 <gmock/gmock.h> 18#include <gtest/gtest.h> 19 20#include <netdutils/MockSyscalls.h> 21 22#include "InterfaceController.h" 23 24using testing::ByMove; 25using testing::Invoke; 26using testing::Return; 27using testing::StrictMock; 28using testing::_; 29 30namespace android { 31namespace net { 32namespace { 33 34using netdutils::Fd; 35using netdutils::ScopedMockSyscalls; 36using netdutils::Slice; 37using netdutils::Status; 38using netdutils::StatusOr; 39using netdutils::UniqueFd; 40using netdutils::makeSlice; 41using netdutils::status::ok; 42using netdutils::statusFromErrno; 43 44constexpr Fd kDevRandomFd(777); 45constexpr Fd kStableSecretFd(9999); 46const char kDevRandomPath[] = "/dev/random"; 47const char kTestIface[] = "wlan5"; 48const char kStableSecretProperty[] = "persist.netd.stable_secret"; 49const char kStableSecretPath[] = "/proc/sys/net/ipv6/conf/wlan5/stable_secret"; 50const char kTestIPv6Address[] = "\x20\x01\x0d\xb8\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"; 51const char kTestIPv6AddressString[] = "2001:db8:506:708:90a:b0c:d0e:f10"; 52 53// getProperty() and setProperty() are forwarded to this mock 54class MockProperties { 55 public: 56 MOCK_CONST_METHOD2(get, std::string(const std::string& key, const std::string& dflt)); 57 MOCK_CONST_METHOD2(set, Status(const std::string& key, const std::string& val)); 58}; 59 60} // namespace 61 62class StablePrivacyTest : public testing::Test { 63 protected: 64 void expectOpenFile(const std::string& path, const Fd fd, int err) { 65 if (err == 0) { 66 EXPECT_CALL(mSyscalls, open(path, _, _)).WillOnce(Return(ByMove(UniqueFd(fd)))); 67 EXPECT_CALL(mSyscalls, close(fd)).WillOnce(Return(ok)); 68 } else { 69 EXPECT_CALL(mSyscalls, open(path, _, _)) 70 .WillOnce(Return(ByMove(statusFromErrno(err, "open() failed")))); 71 } 72 } 73 74 void expectReadFromDevRandom(const std::string& data) { 75 expectOpenFile(kDevRandomPath, kDevRandomFd, 0); 76 EXPECT_CALL(mSyscalls, read(kDevRandomFd, _)).WillOnce(Invoke([data](Fd, const Slice buf) { 77 EXPECT_EQ(data.size(), buf.size()); 78 return take(buf, copy(buf, makeSlice(data))); 79 })); 80 } 81 82 void expectGetPropertyDefault(const std::string& key) { 83 EXPECT_CALL(mProperties, get(key, _)) 84 .WillOnce(Invoke([](const std::string&, const std::string& dflt) { return dflt; })); 85 } 86 87 void expectGetProperty(const std::string& key, const std::string& val) { 88 EXPECT_CALL(mProperties, get(key, _)) 89 .WillOnce(Invoke([val](const std::string&, const std::string&) { return val; })); 90 } 91 92 void expectSetProperty(const std::string& key, const std::string& val, Status status) { 93 EXPECT_CALL(mProperties, set(key, val)).WillOnce(Return(status)); 94 } 95 96 void expectWriteToFile(const Fd fd, const std::string& val, int err) { 97 EXPECT_CALL(mSyscalls, write(fd, _)) 98 .WillOnce(Invoke([val, err](Fd, const Slice buf) -> StatusOr<size_t> { 99 EXPECT_EQ(val, toString(buf)); 100 if (err) { 101 return statusFromErrno(err, "write() failed"); 102 } 103 return val.size(); 104 })); 105 } 106 107 Status enableStablePrivacyAddresses(const std::string& iface) { 108 return InterfaceController::enableStablePrivacyAddresses(iface, mGet, mSet); 109 } 110 111 StrictMock<ScopedMockSyscalls> mSyscalls; 112 StrictMock<MockProperties> mProperties; 113 114 const std::function<std::string(const std::string&, const std::string&)> mGet = 115 [this](const std::string& key, const std::string& dflt) { 116 return mProperties.get(key, dflt); 117 }; 118 const std::function<Status(const std::string&, const std::string&)> mSet = 119 [this](const std::string& key, const std::string& val) { 120 return mProperties.set(key, val); 121 }; 122}; 123 124TEST_F(StablePrivacyTest, PropertyOpenEnoent) { 125 expectOpenFile(kStableSecretPath, kStableSecretFd, ENOENT); 126 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface)); 127} 128 129TEST_F(StablePrivacyTest, PropertyOpenEaccess) { 130 expectOpenFile(kStableSecretPath, kStableSecretFd, EACCES); 131 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface)); 132} 133 134TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyOk) { 135 expectOpenFile(kStableSecretPath, kStableSecretFd, 0); 136 expectGetPropertyDefault(kStableSecretProperty); 137 expectReadFromDevRandom(kTestIPv6Address); 138 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0); 139 expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, ok); 140 EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface)); 141} 142 143TEST_F(StablePrivacyTest, FirstBootWriteOkSetPropertyFail) { 144 const auto kError = statusFromErrno(EINVAL, ""); 145 expectOpenFile(kStableSecretPath, kStableSecretFd, 0); 146 expectGetPropertyDefault(kStableSecretProperty); 147 expectReadFromDevRandom(kTestIPv6Address); 148 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0); 149 expectSetProperty(kStableSecretProperty, kTestIPv6AddressString, kError); 150 EXPECT_EQ(kError, enableStablePrivacyAddresses(kTestIface)); 151} 152 153TEST_F(StablePrivacyTest, FirstBootWriteFail) { 154 expectOpenFile(kStableSecretPath, kStableSecretFd, 0); 155 expectGetPropertyDefault(kStableSecretProperty); 156 expectReadFromDevRandom(kTestIPv6Address); 157 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, ENOSPC); 158 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface)); 159} 160 161TEST_F(StablePrivacyTest, ExistingPropertyWriteOk) { 162 expectOpenFile(kStableSecretPath, kStableSecretFd, 0); 163 expectGetProperty(kStableSecretProperty, kTestIPv6AddressString); 164 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, 0); 165 EXPECT_EQ(ok, enableStablePrivacyAddresses(kTestIface)); 166} 167 168TEST_F(StablePrivacyTest, ExistingPropertyWriteFail) { 169 expectOpenFile(kStableSecretPath, kStableSecretFd, 0); 170 expectGetProperty(kStableSecretProperty, kTestIPv6AddressString); 171 expectWriteToFile(kStableSecretFd, kTestIPv6AddressString, EACCES); 172 EXPECT_NE(ok, enableStablePrivacyAddresses(kTestIface)); 173} 174 175} // namespace net 176} // namespace android 177