blob: 05e899cf272281793b0ab9ca6ac474c78ae2fb65 [file] [log] [blame]
Joel Scherpelz08b84cd2017-05-22 13:11:54 +09001/*
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 <linux/netfilter/nfnetlink_log.h>
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
22#include "NetlinkManager.h"
23#include "WakeupController.h"
24
25using ::testing::StrictMock;
26using ::testing::Test;
27using ::testing::DoAll;
28using ::testing::SaveArg;
29using ::testing::Return;
30using ::testing::_;
31
32namespace android {
33namespace net {
34
35using netdutils::status::ok;
36
37class MockNetdEventListener {
38 public:
39 MOCK_METHOD4(onWakeupEvent,
40 void(const std::string& prefix, uid_t uid, gid_t gid, uint64_t timestampNs));
41};
42
43class MockIptablesRestore : public IptablesRestoreInterface {
44 public:
45 ~MockIptablesRestore() override = default;
46 MOCK_METHOD3(execute, int(const IptablesTarget target, const std::string& commands,
47 std::string* output));
48};
49
50class MockNFLogListener : public NFLogListenerInterface {
51 public:
52 ~MockNFLogListener() override = default;
53 MOCK_METHOD2(subscribe, netdutils::Status(uint16_t nfLogGroup, const DispatchFn& fn));
54 MOCK_METHOD1(unsubscribe, netdutils::Status(uint16_t nfLogGroup));
55};
56
57class WakeupControllerTest : public Test {
58 protected:
59 WakeupControllerTest() {
60 EXPECT_CALL(mListener, subscribe(NetlinkManager::NFLOG_WAKEUP_GROUP, _))
61 .WillOnce(DoAll(SaveArg<1>(&mMessageHandler), Return(ok)));
62 EXPECT_CALL(mListener, unsubscribe(NetlinkManager::NFLOG_WAKEUP_GROUP)).WillOnce(Return(ok));
63 mController.init(&mListener);
64 }
65
66 StrictMock<MockNetdEventListener> mEventListener;
67 StrictMock<MockIptablesRestore> mIptables;
68 StrictMock<MockNFLogListener> mListener;
69 WakeupController mController{
70 [this](const std::string& prefix, uid_t uid, gid_t gid, uint64_t timestampNs) {
71 mEventListener.onWakeupEvent(prefix, uid, gid, timestampNs);
72 },
73 &mIptables};
74 NFLogListenerInterface::DispatchFn mMessageHandler;
75};
76
77TEST_F(WakeupControllerTest, msgHandler) {
78 const char kPrefix[] = "test:prefix";
79 const uid_t kUid = 8734;
80 const gid_t kGid = 2222;
81 const uint64_t kNsPerS = 1000000000ULL;
82 const uint64_t kTsNs = 9999 + (34 * kNsPerS);
83
84 struct Msg {
85 nlmsghdr nlmsg;
86 nfgenmsg nfmsg;
87 nlattr uidAttr;
88 uid_t uid;
89 nlattr gidAttr;
90 gid_t gid;
91 nlattr tsAttr;
92 timespec ts;
93 nlattr prefixAttr;
94 char prefix[sizeof(kPrefix)];
95 } msg = {};
96
97 msg.uidAttr.nla_type = NFULA_UID;
98 msg.uidAttr.nla_len = sizeof(msg.uidAttr) + sizeof(msg.uid);
99 msg.uid = htobe32(kUid);
100
101 msg.gidAttr.nla_type = NFULA_GID;
102 msg.gidAttr.nla_len = sizeof(msg.gidAttr) + sizeof(msg.gid);
103 msg.gid = htobe32(kGid);
104
105 msg.tsAttr.nla_type = NFULA_TIMESTAMP;
106 msg.tsAttr.nla_len = sizeof(msg.tsAttr) + sizeof(msg.ts);
107 msg.ts.tv_sec = htobe32(kTsNs / kNsPerS);
108 msg.ts.tv_nsec = htobe32(kTsNs % kNsPerS);
109
110 msg.prefixAttr.nla_type = NFULA_PREFIX;
111 msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
112 memcpy(msg.prefix, kPrefix, sizeof(kPrefix));
113
114 auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, uidAttr));
115 EXPECT_CALL(mEventListener, onWakeupEvent(kPrefix, kUid, kGid, kTsNs));
116 mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
117}
118
119TEST_F(WakeupControllerTest, badAttr) {
120 const char kPrefix[] = "test:prefix";
121 const uid_t kUid = 8734;
122 const gid_t kGid = 2222;
123 const uint64_t kNsPerS = 1000000000ULL;
124 const uint64_t kTsNs = 9999 + (34 * kNsPerS);
125
126 struct Msg {
127 nlmsghdr nlmsg;
128 nfgenmsg nfmsg;
129 nlattr uidAttr;
130 uid_t uid;
131 nlattr invalid0;
132 nlattr invalid1;
133 nlattr gidAttr;
134 gid_t gid;
135 nlattr tsAttr;
136 timespec ts;
137 nlattr prefixAttr;
138 char prefix[sizeof(kPrefix)];
139 } msg = {};
140
141 msg.uidAttr.nla_type = 999;
142 msg.uidAttr.nla_len = sizeof(msg.uidAttr) + sizeof(msg.uid);
143 msg.uid = htobe32(kUid);
144
145 msg.invalid0.nla_type = 0;
146 msg.invalid0.nla_len = 0;
147 msg.invalid1.nla_type = 0;
148 msg.invalid1.nla_len = 1;
149
150 msg.gidAttr.nla_type = NFULA_GID;
151 msg.gidAttr.nla_len = sizeof(msg.gidAttr) + sizeof(msg.gid);
152 msg.gid = htobe32(kGid);
153
154 msg.tsAttr.nla_type = NFULA_TIMESTAMP;
155 msg.tsAttr.nla_len = sizeof(msg.tsAttr) - 2;
156 msg.ts.tv_sec = htobe32(kTsNs / kNsPerS);
157 msg.ts.tv_nsec = htobe32(kTsNs % kNsPerS);
158
159 msg.prefixAttr.nla_type = NFULA_UID;
160 msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
161 memcpy(msg.prefix, kPrefix, sizeof(kPrefix));
162
163 auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, uidAttr));
164 EXPECT_CALL(mEventListener, onWakeupEvent("", 1952805748, kGid, 0));
165 mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
166}
167
168TEST_F(WakeupControllerTest, unterminatedString) {
169 char ones[20] = {};
170 memset(ones, 1, sizeof(ones));
171
172 struct Msg {
173 nlmsghdr nlmsg;
174 nfgenmsg nfmsg;
175 nlattr prefixAttr;
176 char prefix[sizeof(ones)];
177 } msg = {};
178
179 msg.prefixAttr.nla_type = NFULA_PREFIX;
180 msg.prefixAttr.nla_len = sizeof(msg.prefixAttr) + sizeof(msg.prefix);
181 memcpy(msg.prefix, ones, sizeof(ones));
182
183 const auto expected = std::string(ones, sizeof(ones) - 1);
184 auto payload = drop(netdutils::makeSlice(msg), offsetof(Msg, prefixAttr));
185 EXPECT_CALL(mEventListener, onWakeupEvent(expected, -1, -1, -1));
186 mMessageHandler(msg.nlmsg, msg.nfmsg, payload);
187}
188
189TEST_F(WakeupControllerTest, addInterface) {
190 const char kPrefix[] = "test:prefix";
191 const char kIfName[] = "wlan8";
192 const uint32_t kMark = 0x12345678;
193 const uint32_t kMask = 0x0F0F0F0F;
194 const char kExpected[] =
195 "*mangle\n-A wakeupctrl_mangle_INPUT -i test:prefix"
196 " -j NFLOG --nflog-prefix wlan8 --nflog-group 3 --nflog-threshold 8"
197 " -m mark --mark 0x12345678/0x0f0f0f0f -m limit --limit 10/s\nCOMMIT\n";
198 EXPECT_CALL(mIptables, execute(V4V6, kExpected, _)).WillOnce(Return(0));
199 mController.addInterface(kPrefix, kIfName, kMark, kMask);
200}
201
202TEST_F(WakeupControllerTest, delInterface) {
203 const char kPrefix[] = "test:prefix";
204 const char kIfName[] = "wlan8";
205 const uint32_t kMark = 0x12345678;
206 const uint32_t kMask = 0xF0F0F0F0;
207 const char kExpected[] =
208 "*mangle\n-D wakeupctrl_mangle_INPUT -i test:prefix"
209 " -j NFLOG --nflog-prefix wlan8 --nflog-group 3 --nflog-threshold 8"
210 " -m mark --mark 0x12345678/0xf0f0f0f0 -m limit --limit 10/s\nCOMMIT\n";
211 EXPECT_CALL(mIptables, execute(V4V6, kExpected, _)).WillOnce(Return(0));
212 mController.delInterface(kPrefix, kIfName, kMark, kMask);
213}
214
215} // namespace net
216} // namespace android