blob: 2c1780457b79fe4e0f22dbeab0bce623ed05e741 [file] [log] [blame]
Garrick Evansf0ab7132019-06-18 14:50:42 +09001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Garrick Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/datapath.h"
Garrick Evansf0ab7132019-06-18 14:50:42 +09006
Garrick Evansc7ae82c2019-09-04 16:25:10 +09007#include <linux/if_tun.h>
Taoyu Li90c13912019-11-26 17:56:54 +09008#include <net/if.h>
Garrick Evansc7ae82c2019-09-04 16:25:10 +09009#include <sys/ioctl.h>
10
Garrick Evansf0ab7132019-06-18 14:50:42 +090011#include <utility>
12#include <vector>
13
Garrick Evansc7ae82c2019-09-04 16:25:10 +090014#include <base/bind.h>
Qijiang Fane90b8792020-03-09 16:15:41 +090015#include <base/bind_helpers.h>
Garrick Evansf0ab7132019-06-18 14:50:42 +090016#include <base/strings/string_util.h>
Garrick Evans8e8e3472020-01-23 14:03:50 +090017#include <gmock/gmock.h>
Garrick Evansf0ab7132019-06-18 14:50:42 +090018#include <gtest/gtest.h>
19
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090020#include "patchpanel/mock_firewall.h"
Garrick Evans3388a032020-03-24 11:25:55 +090021#include "patchpanel/net_util.h"
Garrick Evansf0ab7132019-06-18 14:50:42 +090022
Garrick Evans8e8e3472020-01-23 14:03:50 +090023using testing::_;
24using testing::ElementsAre;
25using testing::Return;
26using testing::StrEq;
27
Garrick Evans3388a032020-03-24 11:25:55 +090028namespace patchpanel {
Garrick Evansc7ae82c2019-09-04 16:25:10 +090029namespace {
30
Hugo Benichi76675592020-04-08 14:29:57 +090031// TODO(hugobenichi) Centralize this constant definition
32constexpr pid_t kTestPID = -2;
33
Hugo Benichie8758b52020-04-03 14:49:01 +090034std::vector<ioctl_req_t> ioctl_reqs;
35std::vector<std::pair<std::string, struct rtentry>> ioctl_rtentry_args;
Garrick Evansc7ae82c2019-09-04 16:25:10 +090036
37// Capture all ioctls and succeed.
Taoyu Li90c13912019-11-26 17:56:54 +090038int ioctl_req_cap(int fd, ioctl_req_t req, ...) {
Hugo Benichie8758b52020-04-03 14:49:01 +090039 ioctl_reqs.push_back(req);
40 return 0;
41}
42
43// Capture ioctls for SIOCADDRT and SIOCDELRT and succeed.
44int ioctl_rtentry_cap(int fd, ioctl_req_t req, struct rtentry* arg) {
45 ioctl_reqs.push_back(req);
46 ioctl_rtentry_args.push_back({"", *arg});
47 // Copy the string poited by rtentry.rt_dev because Add/DeleteIPv4Route pass
48 // this value to ioctl() on the stack.
49 if (arg->rt_dev) {
50 auto& cap = ioctl_rtentry_args.back();
51 cap.first = std::string(arg->rt_dev);
52 cap.second.rt_dev = (char*)cap.first.c_str();
53 }
Garrick Evansc7ae82c2019-09-04 16:25:10 +090054 return 0;
55}
56
57} // namespace
58
Garrick Evans8e8e3472020-01-23 14:03:50 +090059class MockProcessRunner : public MinijailedProcessRunner {
60 public:
61 MockProcessRunner() = default;
62 ~MockProcessRunner() = default;
63
Garrick Evans2470caa2020-03-04 14:15:41 +090064 MOCK_METHOD1(WriteSentinelToContainer, int(pid_t pid));
Garrick Evans8e8e3472020-01-23 14:03:50 +090065 MOCK_METHOD3(brctl,
66 int(const std::string& cmd,
67 const std::vector<std::string>& argv,
68 bool log_failures));
69 MOCK_METHOD4(chown,
70 int(const std::string& uid,
71 const std::string& gid,
72 const std::string& file,
73 bool log_failures));
Garrick Evans8e8e3472020-01-23 14:03:50 +090074 MOCK_METHOD4(ip,
75 int(const std::string& obj,
76 const std::string& cmd,
77 const std::vector<std::string>& args,
78 bool log_failures));
79 MOCK_METHOD4(ip6,
80 int(const std::string& obj,
81 const std::string& cmd,
82 const std::vector<std::string>& args,
83 bool log_failures));
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090084 MOCK_METHOD4(iptables,
Garrick Evans8e8e3472020-01-23 14:03:50 +090085 int(const std::string& table,
86 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090087 bool log_failures,
88 std::string* output));
89 MOCK_METHOD4(ip6tables,
Garrick Evans8e8e3472020-01-23 14:03:50 +090090 int(const std::string& table,
91 const std::vector<std::string>& argv,
Jie Jiangcf5ce9c2020-07-14 17:22:03 +090092 bool log_failures,
93 std::string* output));
Garrick Evans8e8e3472020-01-23 14:03:50 +090094 MOCK_METHOD2(modprobe_all,
95 int(const std::vector<std::string>& modules, bool log_failures));
96 MOCK_METHOD3(sysctl_w,
97 int(const std::string& key,
98 const std::string& value,
99 bool log_failures));
Hugo Benichi33860d72020-07-09 16:34:01 +0900100 MOCK_METHOD3(ip_netns_attach,
101 int(const std::string& netns_name,
102 pid_t netns_pid,
103 bool log_failures));
104 MOCK_METHOD2(ip_netns_delete,
105 int(const std::string& netns_name, bool log_failures));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900106};
107
Hugo Benichid82d8832020-08-14 10:05:03 +0900108TEST(DatapathTest, IpFamily) {
109 EXPECT_EQ(IpFamily::Dual, IpFamily::IPv4 | IpFamily::IPv6);
110 EXPECT_EQ(IpFamily::Dual & IpFamily::IPv4, IpFamily::IPv4);
111 EXPECT_EQ(IpFamily::Dual & IpFamily::IPv6, IpFamily::IPv6);
112 EXPECT_NE(IpFamily::Dual, IpFamily::IPv4);
113 EXPECT_NE(IpFamily::Dual, IpFamily::IPv6);
114 EXPECT_NE(IpFamily::IPv4, IpFamily::IPv6);
115}
116
Hugo Benichibf811c62020-09-07 17:30:45 +0900117TEST(DatapathTest, Start) {
118 MockProcessRunner runner;
119 MockFirewall firewall;
120 // Asserts for sysctl modifications
121 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_forward"), StrEq("1"), true));
122 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_local_port_range"),
123 StrEq("32768 47103"), true));
124 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv6.conf.all.forwarding"),
125 StrEq("1"), true));
126 // Asserts for AddSNATMarkRules
127 EXPECT_CALL(
128 runner,
129 iptables(StrEq("filter"),
130 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
131 "state", "--state", "INVALID", "-j", "DROP", "-w"),
132 true, nullptr));
133 EXPECT_CALL(runner,
134 iptables(StrEq("filter"),
135 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
136 "1/1", "-j", "ACCEPT", "-w"),
137 true, nullptr));
138 EXPECT_CALL(runner,
139 iptables(StrEq("nat"),
140 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
141 "1/1", "-j", "MASQUERADE", "-w"),
142 true, nullptr));
143 // Asserts for AddForwardEstablishedRule
144 EXPECT_CALL(runner,
145 iptables(StrEq("filter"),
146 ElementsAre("-A", "FORWARD", "-m", "state", "--state",
147 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
148 true, nullptr));
149 // Asserts for AddSourceIPv4DropRule() calls.
150 EXPECT_CALL(runner,
151 iptables(StrEq("filter"),
152 ElementsAre("-I", "OUTPUT", "-o", "eth+", "-s",
153 "100.115.92.0/23", "-j", "DROP", "-w"),
154 true, nullptr));
155 EXPECT_CALL(runner,
156 iptables(StrEq("filter"),
157 ElementsAre("-I", "OUTPUT", "-o", "wlan+", "-s",
158 "100.115.92.0/23", "-j", "DROP", "-w"),
159 true, nullptr));
160 EXPECT_CALL(runner,
161 iptables(StrEq("filter"),
162 ElementsAre("-I", "OUTPUT", "-o", "mlan+", "-s",
163 "100.115.92.0/23", "-j", "DROP", "-w"),
164 true, nullptr));
165 EXPECT_CALL(runner,
166 iptables(StrEq("filter"),
167 ElementsAre("-I", "OUTPUT", "-o", "usb+", "-s",
168 "100.115.92.0/23", "-j", "DROP", "-w"),
169 true, nullptr));
170 EXPECT_CALL(runner,
171 iptables(StrEq("filter"),
172 ElementsAre("-I", "OUTPUT", "-o", "wwan+", "-s",
173 "100.115.92.0/23", "-j", "DROP", "-w"),
174 true, nullptr));
175 EXPECT_CALL(runner,
176 iptables(StrEq("filter"),
177 ElementsAre("-I", "OUTPUT", "-o", "rmnet+", "-s",
178 "100.115.92.0/23", "-j", "DROP", "-w"),
179 true, nullptr));
180 // Asserts for AddOutboundIPv4SNATMark("vmtap+")
181 EXPECT_CALL(runner,
182 iptables(StrEq("mangle"),
183 ElementsAre("-A", "PREROUTING", "-i", "vmtap+", "-j",
184 "MARK", "--set-mark", "1/1", "-w"),
185 true, nullptr));
186
187 Datapath datapath(&runner, &firewall);
188 datapath.Start();
189}
190
191TEST(DatapathTest, Stop) {
192 MockProcessRunner runner;
193 MockFirewall firewall;
194 // Asserts for sysctl modifications
195 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_local_port_range"),
196 StrEq("32768 61000"), true));
197 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv6.conf.all.forwarding"),
198 StrEq("0"), true));
199 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_forward"), StrEq("0"), true));
200 // Asserts for RemoveOutboundIPv4SNATMark("vmtap+")
201 EXPECT_CALL(runner,
202 iptables(StrEq("mangle"),
203 ElementsAre("-D", "PREROUTING", "-i", "vmtap+", "-j",
204 "MARK", "--set-mark", "1/1", "-w"),
205 true, nullptr));
206 // Asserts for RemoveForwardEstablishedRule
207 EXPECT_CALL(runner,
208 iptables(StrEq("filter"),
209 ElementsAre("-D", "FORWARD", "-m", "state", "--state",
210 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
211 true, nullptr));
212 // Asserts for RemoveSNATMarkRules
213 EXPECT_CALL(
214 runner,
215 iptables(StrEq("filter"),
216 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
217 "state", "--state", "INVALID", "-j", "DROP", "-w"),
218 true, nullptr));
219 EXPECT_CALL(runner,
220 iptables(StrEq("filter"),
221 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
222 "1/1", "-j", "ACCEPT", "-w"),
223 true, nullptr));
224 EXPECT_CALL(runner,
225 iptables(StrEq("nat"),
226 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
227 "1/1", "-j", "MASQUERADE", "-w"),
228 true, nullptr));
229 // Asserts for RemoveSourceIPv4DropRule() calls.
230 EXPECT_CALL(runner,
231 iptables(StrEq("filter"),
232 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
233 "100.115.92.0/23", "-j", "DROP", "-w"),
234 true, nullptr));
235 EXPECT_CALL(runner,
236 iptables(StrEq("filter"),
237 ElementsAre("-D", "OUTPUT", "-o", "wlan+", "-s",
238 "100.115.92.0/23", "-j", "DROP", "-w"),
239 true, nullptr));
240 EXPECT_CALL(runner,
241 iptables(StrEq("filter"),
242 ElementsAre("-D", "OUTPUT", "-o", "mlan+", "-s",
243 "100.115.92.0/23", "-j", "DROP", "-w"),
244 true, nullptr));
245 EXPECT_CALL(runner,
246 iptables(StrEq("filter"),
247 ElementsAre("-D", "OUTPUT", "-o", "usb+", "-s",
248 "100.115.92.0/23", "-j", "DROP", "-w"),
249 true, nullptr));
250 EXPECT_CALL(runner,
251 iptables(StrEq("filter"),
252 ElementsAre("-D", "OUTPUT", "-o", "wwan+", "-s",
253 "100.115.92.0/23", "-j", "DROP", "-w"),
254 true, nullptr));
255 EXPECT_CALL(runner,
256 iptables(StrEq("filter"),
257 ElementsAre("-D", "OUTPUT", "-o", "rmnet+", "-s",
258 "100.115.92.0/23", "-j", "DROP", "-w"),
259 true, nullptr));
260
261 Datapath datapath(&runner, &firewall);
262 datapath.Stop();
263}
264
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900265TEST(DatapathTest, AddTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900266 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900267 MockFirewall firewall;
268 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900269 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900270 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900271 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900272 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900273 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900274 std::vector<ioctl_req_t> expected = {
275 TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, SIOCSIFNETMASK,
276 SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900277 EXPECT_EQ(ioctl_reqs, expected);
278 ioctl_reqs.clear();
279}
280
281TEST(DatapathTest, AddTAPWithOwner) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900282 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900283 MockFirewall firewall;
284 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900285 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900286 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900287 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900288 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900289 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900290 std::vector<ioctl_req_t> expected = {
291 TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, SIOCSIFADDR,
292 SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900293 EXPECT_EQ(ioctl_reqs, expected);
294 ioctl_reqs.clear();
295}
296
Garrick Evans621ed262019-11-13 12:28:43 +0900297TEST(DatapathTest, AddTAPNoAddrs) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900298 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900299 MockFirewall firewall;
300 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900301 auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, "");
Garrick Evans621ed262019-11-13 12:28:43 +0900302 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900303 std::vector<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS,
304 SIOCSIFFLAGS};
Garrick Evans621ed262019-11-13 12:28:43 +0900305 EXPECT_EQ(ioctl_reqs, expected);
306 ioctl_reqs.clear();
307}
308
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900309TEST(DatapathTest, RemoveTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900310 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900311 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900312 EXPECT_CALL(runner, ip(StrEq("tuntap"), StrEq("del"),
313 ElementsAre("foo0", "mode", "tap"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900314 Datapath datapath(&runner, &firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900315 datapath.RemoveTAP("foo0");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900316}
Garrick Evansf0ab7132019-06-18 14:50:42 +0900317
Hugo Benichi33860d72020-07-09 16:34:01 +0900318TEST(DatapathTest, NetnsAttachName) {
319 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900320 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900321 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
322 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), 1234, true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900323 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900324 EXPECT_TRUE(datapath.NetnsAttachName("netns_foo", 1234));
325}
326
327TEST(DatapathTest, NetnsDeleteName) {
328 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900329 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900330 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900331 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900332 EXPECT_TRUE(datapath.NetnsDeleteName("netns_foo"));
333}
334
Garrick Evans8a949dc2019-07-18 16:17:53 +0900335TEST(DatapathTest, AddBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900336 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900337 MockFirewall firewall;
338 Datapath datapath(&runner, &firewall);
Garrick Evans8e8e3472020-01-23 14:03:50 +0900339 EXPECT_CALL(runner, brctl(StrEq("addbr"), ElementsAre("br"), true));
Garrick Evans6f4fa3a2020-02-10 16:15:09 +0900340 EXPECT_CALL(
341 runner,
342 ip(StrEq("addr"), StrEq("add"),
343 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "br"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900344 EXPECT_CALL(runner,
345 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "up"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900346 EXPECT_CALL(runner, iptables(StrEq("mangle"),
347 ElementsAre("-A", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900348 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900349 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900350 datapath.AddBridge("br", Ipv4Addr(1, 1, 1, 1), 30);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900351}
352
Hugo Benichi76675592020-04-08 14:29:57 +0900353TEST(DatapathTest, ConnectVethPair) {
354 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900355 MockFirewall firewall;
Hugo Benichi76675592020-04-08 14:29:57 +0900356 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
357 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900358 "peer_foo", "netns", "netns_foo"),
Hugo Benichi76675592020-04-08 14:29:57 +0900359 true));
360 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
361 ElementsAre("100.115.92.169/30", "brd",
362 "100.115.92.171", "dev", "peer_foo"),
363 true))
364 .WillOnce(Return(0));
365 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
366 ElementsAre("dev", "peer_foo", "up", "addr",
367 "01:02:03:04:05:06", "multicast", "on"),
368 true))
369 .WillOnce(Return(0));
Hugo Benichi76675592020-04-08 14:29:57 +0900370 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
371 ElementsAre("veth_foo", "up"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900372 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900373 EXPECT_TRUE(datapath.ConnectVethPair(kTestPID, "netns_foo", "veth_foo",
374 "peer_foo", {1, 2, 3, 4, 5, 6},
Hugo Benichi76675592020-04-08 14:29:57 +0900375 Ipv4Addr(100, 115, 92, 169), 30, true));
376}
377
Garrick Evans2470caa2020-03-04 14:15:41 +0900378TEST(DatapathTest, AddVirtualInterfacePair) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900379 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900380 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900381 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
382 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900383 "peer_foo", "netns", "netns_foo"),
Garrick Evans8e8e3472020-01-23 14:03:50 +0900384 true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900385 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900386 EXPECT_TRUE(
387 datapath.AddVirtualInterfacePair("netns_foo", "veth_foo", "peer_foo"));
Garrick Evans2470caa2020-03-04 14:15:41 +0900388}
389
390TEST(DatapathTest, ToggleInterface) {
391 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900392 MockFirewall firewall;
Garrick Evans2470caa2020-03-04 14:15:41 +0900393 EXPECT_CALL(runner,
394 ip(StrEq("link"), StrEq("set"), ElementsAre("foo", "up"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900395 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
Garrick Evans2470caa2020-03-04 14:15:41 +0900396 ElementsAre("bar", "down"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900397 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900398 EXPECT_TRUE(datapath.ToggleInterface("foo", true));
399 EXPECT_TRUE(datapath.ToggleInterface("bar", false));
400}
401
402TEST(DatapathTest, ConfigureInterface) {
403 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900404 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900405 EXPECT_CALL(
406 runner,
Garrick Evans2470caa2020-03-04 14:15:41 +0900407 ip(StrEq("addr"), StrEq("add"),
408 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "foo"), true))
409 .WillOnce(Return(0));
410 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
411 ElementsAre("dev", "foo", "up", "addr",
412 "02:02:02:02:02:02", "multicast", "on"),
413 true))
414 .WillOnce(Return(0));
415
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900416 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900417 MacAddress mac_addr = {2, 2, 2, 2, 2, 2};
418 EXPECT_TRUE(datapath.ConfigureInterface("foo", mac_addr, Ipv4Addr(1, 1, 1, 1),
419 30, true, true));
Garrick Evans54861622019-07-19 09:05:09 +0900420}
421
422TEST(DatapathTest, RemoveInterface) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900423 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900424 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900425 EXPECT_CALL(runner,
426 ip(StrEq("link"), StrEq("delete"), ElementsAre("foo"), false));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900427 Datapath datapath(&runner, &firewall);
Garrick Evans54861622019-07-19 09:05:09 +0900428 datapath.RemoveInterface("foo");
Garrick Evans54861622019-07-19 09:05:09 +0900429}
430
Garrick Evans8a949dc2019-07-18 16:17:53 +0900431TEST(DatapathTest, RemoveBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900432 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900433 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900434 EXPECT_CALL(runner, iptables(StrEq("mangle"),
435 ElementsAre("-D", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900436 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900437 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900438 EXPECT_CALL(runner,
439 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "down"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900440 EXPECT_CALL(runner, brctl(StrEq("delbr"), ElementsAre("br"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900441 Datapath datapath(&runner, &firewall);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900442 datapath.RemoveBridge("br");
Garrick Evans8a949dc2019-07-18 16:17:53 +0900443}
444
Hugo Benichi321f23b2020-09-25 15:42:05 +0900445TEST(DatapathTest, AddRemoveSourceIPv4DropRule) {
446 MockProcessRunner runner;
447 MockFirewall firewall;
448 EXPECT_CALL(runner,
449 iptables(StrEq("filter"),
450 ElementsAre("-I", "OUTPUT", "-o", "eth+", "-s",
451 "100.115.92.0/24", "-j", "DROP", "-w"),
452 true, nullptr));
453 EXPECT_CALL(runner,
454 iptables(StrEq("filter"),
455 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
456 "100.115.92.0/24", "-j", "DROP", "-w"),
457 true, nullptr));
458 Datapath datapath(&runner, &firewall);
459 datapath.AddSourceIPv4DropRule("eth+", "100.115.92.0/24");
460 datapath.RemoveSourceIPv4DropRule("eth+", "100.115.92.0/24");
461}
462
Hugo Benichi8d622b52020-08-13 15:24:12 +0900463TEST(DatapathTest, StartRoutingDevice_Arc) {
464 MockProcessRunner runner;
465 MockFirewall firewall;
466 EXPECT_CALL(runner, iptables(StrEq("nat"),
467 ElementsAre("-A", "PREROUTING", "-i", "eth0",
468 "-m", "socket", "--nowildcard", "-j",
469 "ACCEPT", "-w"),
470 true, nullptr));
471 EXPECT_CALL(runner, iptables(StrEq("nat"),
472 ElementsAre("-A", "PREROUTING", "-i", "eth0",
473 "-p", "tcp", "-j", "DNAT",
474 "--to-destination", "1.2.3.4", "-w"),
475 true, nullptr));
476 EXPECT_CALL(runner, iptables(StrEq("nat"),
477 ElementsAre("-A", "PREROUTING", "-i", "eth0",
478 "-p", "udp", "-j", "DNAT",
479 "--to-destination", "1.2.3.4", "-w"),
480 true, nullptr));
481 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900482 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
483 "arc_eth0", "-j", "ACCEPT", "-w"),
484 true, nullptr));
485 EXPECT_CALL(runner, iptables(StrEq("filter"),
486 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
487 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900488 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900489 EXPECT_CALL(runner, iptables(StrEq("mangle"),
490 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
491 "-j", "MARK", "--set-mark",
492 "0x00002000/0x00003f00", "-w"),
493 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900494 EXPECT_CALL(runner, iptables(StrEq("mangle"),
495 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
496 "-j", "MARK", "--set-mark",
497 "0x03ea0000/0xffff0000", "-w"),
498 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900499 EXPECT_CALL(
500 runner,
501 ip6tables(StrEq("mangle"),
502 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
503 "--set-mark", "0x00002000/0x00003f00", "-w"),
504 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900505 EXPECT_CALL(
506 runner,
507 ip6tables(StrEq("mangle"),
508 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
509 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
510 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900511
512 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900513 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900514 datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
515 TrafficSource::ARC);
516}
517
518TEST(DatapathTest, StartRoutingDevice_CrosVM) {
519 MockProcessRunner runner;
520 MockFirewall firewall;
521 EXPECT_CALL(runner, iptables(StrEq("filter"),
522 ElementsAre("-A", "FORWARD", "-o", "vmtap0",
523 "-j", "ACCEPT", "-w"),
524 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900525 EXPECT_CALL(runner, iptables(StrEq("filter"),
526 ElementsAre("-A", "FORWARD", "-i", "vmtap0",
527 "-j", "ACCEPT", "-w"),
528 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900529 EXPECT_CALL(runner, iptables(StrEq("mangle"),
530 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
531 "-j", "MARK", "--set-mark",
532 "0x00002100/0x00003f00", "-w"),
533 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900534 EXPECT_CALL(runner, iptables(StrEq("mangle"),
535 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
536 "-j", "CONNMARK", "--restore-mark",
537 "--mask", "0xffff0000", "-w"),
538 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900539 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
540 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
541 "-j", "MARK", "--set-mark",
542 "0x00002100/0x00003f00", "-w"),
543 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900544 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
545 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
546 "-j", "CONNMARK", "--restore-mark",
547 "--mask", "0xffff0000", "-w"),
548 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900549
550 Datapath datapath(&runner, &firewall);
551 datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
552 TrafficSource::CROSVM);
553}
554
555TEST(DatapathTest, StopRoutingDevice_Arc) {
556 MockProcessRunner runner;
557 MockFirewall firewall;
558 EXPECT_CALL(runner, iptables(StrEq("nat"),
559 ElementsAre("-D", "PREROUTING", "-i", "eth0",
560 "-m", "socket", "--nowildcard", "-j",
561 "ACCEPT", "-w"),
562 true, nullptr));
563 EXPECT_CALL(runner, iptables(StrEq("nat"),
564 ElementsAre("-D", "PREROUTING", "-i", "eth0",
565 "-p", "tcp", "-j", "DNAT",
566 "--to-destination", "1.2.3.4", "-w"),
567 true, nullptr));
568 EXPECT_CALL(runner, iptables(StrEq("nat"),
569 ElementsAre("-D", "PREROUTING", "-i", "eth0",
570 "-p", "udp", "-j", "DNAT",
571 "--to-destination", "1.2.3.4", "-w"),
572 true, nullptr));
573 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900574 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
575 "arc_eth0", "-j", "ACCEPT", "-w"),
576 true, nullptr));
577 EXPECT_CALL(runner, iptables(StrEq("filter"),
578 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
579 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900580 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900581 EXPECT_CALL(runner, iptables(StrEq("mangle"),
582 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
583 "-j", "MARK", "--set-mark",
584 "0x00002000/0x00003f00", "-w"),
585 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900586 EXPECT_CALL(runner, iptables(StrEq("mangle"),
587 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
588 "-j", "MARK", "--set-mark",
589 "0x03ea0000/0xffff0000", "-w"),
590 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900591 EXPECT_CALL(
592 runner,
593 ip6tables(StrEq("mangle"),
594 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
595 "--set-mark", "0x00002000/0x00003f00", "-w"),
596 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900597 EXPECT_CALL(
598 runner,
599 ip6tables(StrEq("mangle"),
600 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
601 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
602 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900603
604 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900605 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900606 datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
607 TrafficSource::ARC);
608}
609
610TEST(DatapathTest, StopRoutingDevice_CrosVM) {
611 MockProcessRunner runner;
612 MockFirewall firewall;
613 EXPECT_CALL(runner, iptables(StrEq("filter"),
614 ElementsAre("-D", "FORWARD", "-o", "vmtap0",
615 "-j", "ACCEPT", "-w"),
616 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900617 EXPECT_CALL(runner, iptables(StrEq("filter"),
618 ElementsAre("-D", "FORWARD", "-i", "vmtap0",
619 "-j", "ACCEPT", "-w"),
620 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900621 EXPECT_CALL(runner, iptables(StrEq("mangle"),
622 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
623 "-j", "MARK", "--set-mark",
624 "0x00002100/0x00003f00", "-w"),
625 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900626 EXPECT_CALL(runner, iptables(StrEq("mangle"),
627 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
628 "-j", "CONNMARK", "--restore-mark",
629 "--mask", "0xffff0000", "-w"),
630 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900631 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
632 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
633 "-j", "MARK", "--set-mark",
634 "0x00002100/0x00003f00", "-w"),
635 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900636 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
637 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
638 "-j", "CONNMARK", "--restore-mark",
639 "--mask", "0xffff0000", "-w"),
640 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900641
642 Datapath datapath(&runner, &firewall);
643 datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
644 TrafficSource::CROSVM);
645}
646
Hugo Benichid82d8832020-08-14 10:05:03 +0900647TEST(DatapathTest, StartStopIpForwarding) {
648 struct {
649 IpFamily family;
650 std::string iif;
651 std::string oif;
652 std::vector<std::string> start_args;
653 std::vector<std::string> stop_args;
654 bool result;
655 } testcases[] = {
656 {IpFamily::IPv4, "", "", {}, {}, false},
657 {IpFamily::NONE, "foo", "bar", {}, {}, false},
658 {IpFamily::IPv4,
659 "foo",
660 "bar",
661 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
662 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
663 true},
664 {IpFamily::IPv4,
665 "",
666 "bar",
667 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
668 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
669 true},
670 {IpFamily::IPv4,
671 "foo",
672 "",
673 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
674 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
675 true},
676 {IpFamily::IPv6,
677 "foo",
678 "bar",
679 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
680 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
681 true},
682 {IpFamily::IPv6,
683 "",
684 "bar",
685 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
686 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
687 true},
688 {IpFamily::IPv6,
689 "foo",
690 "",
691 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
692 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
693 true},
694 {IpFamily::Dual,
695 "foo",
696 "bar",
697 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
698 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
699 true},
700 {IpFamily::Dual,
701 "",
702 "bar",
703 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
704 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
705 true},
706 {IpFamily::Dual,
707 "foo",
708 "",
709 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
710 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
711 true},
712 };
713
714 for (const auto& tt : testcases) {
715 MockProcessRunner runner;
716 MockFirewall firewall;
717 if (tt.result) {
718 if (tt.family & IpFamily::IPv4) {
719 EXPECT_CALL(runner,
720 iptables(StrEq("filter"), tt.start_args, true, nullptr))
721 .WillOnce(Return(0));
722 EXPECT_CALL(runner,
723 iptables(StrEq("filter"), tt.stop_args, true, nullptr))
724 .WillOnce(Return(0));
725 }
726 if (tt.family & IpFamily::IPv6) {
727 EXPECT_CALL(runner,
728 ip6tables(StrEq("filter"), tt.start_args, true, nullptr))
729 .WillOnce(Return(0));
730 EXPECT_CALL(runner,
731 ip6tables(StrEq("filter"), tt.stop_args, true, nullptr))
732 .WillOnce(Return(0));
733 }
734 }
735 Datapath datapath(&runner, &firewall);
736
737 EXPECT_EQ(tt.result, datapath.StartIpForwarding(tt.family, tt.iif, tt.oif));
738 EXPECT_EQ(tt.result, datapath.StopIpForwarding(tt.family, tt.iif, tt.oif));
739 }
740}
741
Hugo Benichi76be34a2020-08-26 22:35:54 +0900742TEST(DatapathTest, StartStopConnectionPinning) {
743 MockProcessRunner runner;
744 MockFirewall firewall;
745 EXPECT_CALL(runner, iptables(StrEq("mangle"),
746 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
747 "-j", "CONNMARK", "--set-mark",
748 "0x03eb0000/0xffff0000", "-w"),
749 true, nullptr));
750 EXPECT_CALL(runner, iptables(StrEq("mangle"),
751 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
752 "-j", "CONNMARK", "--set-mark",
753 "0x03eb0000/0xffff0000", "-w"),
754 true, nullptr));
755 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
756 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
757 "-j", "CONNMARK", "--set-mark",
758 "0x03eb0000/0xffff0000", "-w"),
759 true, nullptr));
760 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
761 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
762 "-j", "CONNMARK", "--set-mark",
763 "0x03eb0000/0xffff0000", "-w"),
764 true, nullptr));
765 Datapath datapath(&runner, &firewall);
766 datapath.SetIfnameIndex("eth0", 3);
767 datapath.StartConnectionPinning("eth0");
768 datapath.StopConnectionPinning("eth0");
769}
770
Garrick Evansf0ab7132019-06-18 14:50:42 +0900771TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900772 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900773 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900774 EXPECT_CALL(runner, iptables(StrEq("nat"),
775 ElementsAre("-A", "PREROUTING", "-i", "eth0",
776 "-m", "socket", "--nowildcard", "-j",
777 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900778 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900779 EXPECT_CALL(runner, iptables(StrEq("nat"),
780 ElementsAre("-A", "PREROUTING", "-i", "eth0",
781 "-p", "tcp", "-j", "DNAT",
782 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900783 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900784 EXPECT_CALL(runner, iptables(StrEq("nat"),
785 ElementsAre("-A", "PREROUTING", "-i", "eth0",
786 "-p", "udp", "-j", "DNAT",
787 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900788 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900789 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900790 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900791}
792
793TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900794 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900795 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900796 EXPECT_CALL(runner, iptables(StrEq("nat"),
797 ElementsAre("-D", "PREROUTING", "-i", "eth0",
798 "-m", "socket", "--nowildcard", "-j",
799 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900800 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900801 EXPECT_CALL(runner, iptables(StrEq("nat"),
802 ElementsAre("-D", "PREROUTING", "-i", "eth0",
803 "-p", "tcp", "-j", "DNAT",
804 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900805 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900806 EXPECT_CALL(runner, iptables(StrEq("nat"),
807 ElementsAre("-D", "PREROUTING", "-i", "eth0",
808 "-p", "udp", "-j", "DNAT",
809 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900810 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900811 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900812 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900813}
814
815TEST(DatapathTest, AddOutboundIPv4) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900816 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900817 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900818 EXPECT_CALL(runner, iptables(StrEq("filter"),
819 ElementsAre("-A", "FORWARD", "-o", "eth0", "-j",
820 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900821 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900822 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900823 datapath.AddOutboundIPv4("eth0");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900824}
825
826TEST(DatapathTest, RemoveInboundIPv4) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900827 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900828 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900829 EXPECT_CALL(runner, iptables(StrEq("filter"),
830 ElementsAre("-D", "FORWARD", "-o", "eth0", "-j",
831 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900832 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900833 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900834 datapath.RemoveOutboundIPv4("eth0");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900835}
836
Garrick Evans664a82f2019-12-17 12:18:05 +0900837TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900838 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900839 MockFirewall firewall;
840 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans664a82f2019-12-17 12:18:05 +0900841 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +0900842 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +0900843 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +0900844 EXPECT_EQ(ioctl_reqs, expected);
845 ioctl_reqs.clear();
846}
847
848TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900849 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900850 MockFirewall firewall;
Taoyu Lica49c832019-12-06 17:56:43 +0900851 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +0900852 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
853 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
854 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900855 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +0900856 .WillOnce(Return(1));
857 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
858 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
859 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900860 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900861 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
862 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
863 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900864 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +0900865 .WillOnce(Return(1));
866 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
867 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
868 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900869 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900870 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +0900871 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +0900872}
873
Taoyu Lica49c832019-12-06 17:56:43 +0900874TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900875 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900876 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900877 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
878 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
879 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900880 false, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900881 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
882 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
883 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900884 false, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900885 Datapath datapath(&runner, &firewall);
Taoyu Lica49c832019-12-06 17:56:43 +0900886 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +0900887}
888
Taoyu Li90c13912019-11-26 17:56:54 +0900889TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900890 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900891 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900892 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
893 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
894 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900895 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900896 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
897 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
898 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900899 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900900 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +0900901 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +0900902}
903
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900904TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900905 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900906 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900907 EXPECT_CALL(runner,
908 ip6(StrEq("route"), StrEq("replace"),
909 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900910 Datapath datapath(&runner, &firewall);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900911 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900912}
913
Hugo Benichie8758b52020-04-03 14:49:01 +0900914TEST(DatapathTest, AddIPv4Route) {
915 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900916 MockFirewall firewall;
917 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichie8758b52020-04-03 14:49:01 +0900918
919 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
920 Ipv4Addr(255, 255, 255, 0));
921 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
922 Ipv4Addr(255, 255, 255, 0));
923 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
924 Ipv4Addr(255, 255, 255, 252));
925 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
926 Ipv4Addr(255, 255, 255, 252));
927
928 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
929 SIOCDELRT};
930 EXPECT_EQ(expected_reqs, ioctl_reqs);
931 ioctl_reqs.clear();
932
933 std::string route1 =
934 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
935 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
936 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
937 "RTF_GATEWAY}";
938 std::string route2 =
939 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
940 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
941 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
942 std::vector<std::string> captured_routes;
943 for (const auto& route : ioctl_rtentry_args) {
944 std::ostringstream stream;
945 stream << route.second;
946 captured_routes.emplace_back(stream.str());
947 }
948 ioctl_rtentry_args.clear();
949 EXPECT_EQ(route1, captured_routes[0]);
950 EXPECT_EQ(route1, captured_routes[1]);
951 EXPECT_EQ(route2, captured_routes[2]);
952 EXPECT_EQ(route2, captured_routes[3]);
953}
954
Garrick Evansd291af62020-05-25 10:39:06 +0900955TEST(DatapathTest, AddSNATMarkRules) {
956 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900957 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +0900958 EXPECT_CALL(
959 runner,
960 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +0900961 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +0900962 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900963 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +0900964 EXPECT_CALL(runner,
965 iptables(StrEq("filter"),
966 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
967 "1/1", "-j", "ACCEPT", "-w"),
968 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +0900969 EXPECT_CALL(runner,
970 iptables(StrEq("nat"),
971 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +0900972 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900973 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900974 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +0900975 datapath.AddSNATMarkRules();
976}
977
978TEST(DatapathTest, RemoveSNATMarkRules) {
979 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900980 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +0900981 EXPECT_CALL(
982 runner,
983 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +0900984 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +0900985 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900986 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +0900987 EXPECT_CALL(runner,
988 iptables(StrEq("filter"),
989 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
990 "1/1", "-j", "ACCEPT", "-w"),
991 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +0900992 EXPECT_CALL(runner,
993 iptables(StrEq("nat"),
994 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +0900995 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900996 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900997 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +0900998 datapath.RemoveSNATMarkRules();
999}
1000
1001TEST(DatapathTest, AddForwardEstablishedRule) {
1002 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001003 MockFirewall firewall;
Garrick Evansd291af62020-05-25 10:39:06 +09001004 EXPECT_CALL(runner,
1005 iptables(StrEq("filter"),
1006 ElementsAre("-A", "FORWARD", "-m", "state", "--state",
1007 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001008 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001009 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001010 datapath.AddForwardEstablishedRule();
1011}
1012
1013TEST(DatapathTest, RemoveForwardEstablishedRule) {
1014 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001015 MockFirewall firewall;
Garrick Evansd291af62020-05-25 10:39:06 +09001016 EXPECT_CALL(runner,
1017 iptables(StrEq("filter"),
1018 ElementsAre("-D", "FORWARD", "-m", "state", "--state",
1019 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001020 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001021 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001022 datapath.RemoveForwardEstablishedRule();
1023}
1024
Garrick Evansff6e37f2020-05-25 10:54:47 +09001025TEST(DatapathTest, AddInterfaceSNAT) {
1026 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001027 MockFirewall firewall;
Garrick Evansff6e37f2020-05-25 10:54:47 +09001028 EXPECT_CALL(runner, iptables(StrEq("nat"),
1029 ElementsAre("-A", "POSTROUTING", "-o", "wwan+",
1030 "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001031 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001032 Datapath datapath(&runner, &firewall);
Garrick Evansff6e37f2020-05-25 10:54:47 +09001033 datapath.AddInterfaceSNAT("wwan+");
1034}
1035
1036TEST(DatapathTest, RemoveInterfaceSNAT) {
1037 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001038 MockFirewall firewall;
Garrick Evansff6e37f2020-05-25 10:54:47 +09001039 EXPECT_CALL(runner, iptables(StrEq("nat"),
1040 ElementsAre("-D", "POSTROUTING", "-o", "wwan+",
1041 "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001042 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001043 Datapath datapath(&runner, &firewall);
Garrick Evansff6e37f2020-05-25 10:54:47 +09001044 datapath.RemoveInterfaceSNAT("wwan+");
1045}
1046
Garrick Evans2f581a02020-05-11 10:43:35 +09001047TEST(DatapathTest, ArcVethHostName) {
1048 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
1049 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
1050 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
1051 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
1052 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
1053 EXPECT_EQ("vethexceeds_ify", ifname);
1054 EXPECT_LT(ifname.length(), IFNAMSIZ);
1055}
1056
Garrick Evans8a067562020-05-11 12:47:30 +09001057TEST(DatapathTest, ArcBridgeName) {
1058 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
1059 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
1060 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
1061 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
1062 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
1063 EXPECT_EQ("arc_exceeds_ify", ifname);
1064 EXPECT_LT(ifname.length(), IFNAMSIZ);
1065}
1066
Garrick Evans3388a032020-03-24 11:25:55 +09001067} // namespace patchpanel