blob: f69e7d65d0a6f8b8f6e51a8ad4f6139ee46cc507 [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
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900117TEST(DatapathTest, AddTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900118 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900119 MockFirewall firewall;
120 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900121 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900122 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900123 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900124 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900125 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900126 std::vector<ioctl_req_t> expected = {
127 TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, SIOCSIFNETMASK,
128 SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900129 EXPECT_EQ(ioctl_reqs, expected);
130 ioctl_reqs.clear();
131}
132
133TEST(DatapathTest, AddTAPWithOwner) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900134 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900135 MockFirewall firewall;
136 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900137 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900138 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900139 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900140 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900141 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900142 std::vector<ioctl_req_t> expected = {
143 TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, SIOCSIFADDR,
144 SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900145 EXPECT_EQ(ioctl_reqs, expected);
146 ioctl_reqs.clear();
147}
148
Garrick Evans621ed262019-11-13 12:28:43 +0900149TEST(DatapathTest, AddTAPNoAddrs) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900150 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900151 MockFirewall firewall;
152 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900153 auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, "");
Garrick Evans621ed262019-11-13 12:28:43 +0900154 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900155 std::vector<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS,
156 SIOCSIFFLAGS};
Garrick Evans621ed262019-11-13 12:28:43 +0900157 EXPECT_EQ(ioctl_reqs, expected);
158 ioctl_reqs.clear();
159}
160
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900161TEST(DatapathTest, RemoveTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900162 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900163 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900164 EXPECT_CALL(runner, ip(StrEq("tuntap"), StrEq("del"),
165 ElementsAre("foo0", "mode", "tap"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900166 Datapath datapath(&runner, &firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900167 datapath.RemoveTAP("foo0");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900168}
Garrick Evansf0ab7132019-06-18 14:50:42 +0900169
Hugo Benichi33860d72020-07-09 16:34:01 +0900170TEST(DatapathTest, NetnsAttachName) {
171 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900172 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900173 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
174 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), 1234, true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900175 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900176 EXPECT_TRUE(datapath.NetnsAttachName("netns_foo", 1234));
177}
178
179TEST(DatapathTest, NetnsDeleteName) {
180 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900181 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900182 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900183 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900184 EXPECT_TRUE(datapath.NetnsDeleteName("netns_foo"));
185}
186
Garrick Evans8a949dc2019-07-18 16:17:53 +0900187TEST(DatapathTest, AddBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900188 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900189 MockFirewall firewall;
190 Datapath datapath(&runner, &firewall);
Garrick Evans8e8e3472020-01-23 14:03:50 +0900191 EXPECT_CALL(runner, brctl(StrEq("addbr"), ElementsAre("br"), true));
Garrick Evans6f4fa3a2020-02-10 16:15:09 +0900192 EXPECT_CALL(
193 runner,
194 ip(StrEq("addr"), StrEq("add"),
195 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "br"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900196 EXPECT_CALL(runner,
197 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "up"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900198 EXPECT_CALL(runner, iptables(StrEq("mangle"),
199 ElementsAre("-A", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900200 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900201 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900202 datapath.AddBridge("br", Ipv4Addr(1, 1, 1, 1), 30);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900203}
204
Hugo Benichi76675592020-04-08 14:29:57 +0900205TEST(DatapathTest, ConnectVethPair) {
206 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900207 MockFirewall firewall;
Hugo Benichi76675592020-04-08 14:29:57 +0900208 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
209 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900210 "peer_foo", "netns", "netns_foo"),
Hugo Benichi76675592020-04-08 14:29:57 +0900211 true));
212 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
213 ElementsAre("100.115.92.169/30", "brd",
214 "100.115.92.171", "dev", "peer_foo"),
215 true))
216 .WillOnce(Return(0));
217 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
218 ElementsAre("dev", "peer_foo", "up", "addr",
219 "01:02:03:04:05:06", "multicast", "on"),
220 true))
221 .WillOnce(Return(0));
Hugo Benichi76675592020-04-08 14:29:57 +0900222 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
223 ElementsAre("veth_foo", "up"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900224 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900225 EXPECT_TRUE(datapath.ConnectVethPair(kTestPID, "netns_foo", "veth_foo",
226 "peer_foo", {1, 2, 3, 4, 5, 6},
Hugo Benichi76675592020-04-08 14:29:57 +0900227 Ipv4Addr(100, 115, 92, 169), 30, true));
228}
229
Garrick Evans2470caa2020-03-04 14:15:41 +0900230TEST(DatapathTest, AddVirtualInterfacePair) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900231 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900232 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900233 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
234 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900235 "peer_foo", "netns", "netns_foo"),
Garrick Evans8e8e3472020-01-23 14:03:50 +0900236 true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900237 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900238 EXPECT_TRUE(
239 datapath.AddVirtualInterfacePair("netns_foo", "veth_foo", "peer_foo"));
Garrick Evans2470caa2020-03-04 14:15:41 +0900240}
241
242TEST(DatapathTest, ToggleInterface) {
243 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900244 MockFirewall firewall;
Garrick Evans2470caa2020-03-04 14:15:41 +0900245 EXPECT_CALL(runner,
246 ip(StrEq("link"), StrEq("set"), ElementsAre("foo", "up"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900247 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
Garrick Evans2470caa2020-03-04 14:15:41 +0900248 ElementsAre("bar", "down"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900249 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900250 EXPECT_TRUE(datapath.ToggleInterface("foo", true));
251 EXPECT_TRUE(datapath.ToggleInterface("bar", false));
252}
253
254TEST(DatapathTest, ConfigureInterface) {
255 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900256 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900257 EXPECT_CALL(
258 runner,
Garrick Evans2470caa2020-03-04 14:15:41 +0900259 ip(StrEq("addr"), StrEq("add"),
260 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "foo"), true))
261 .WillOnce(Return(0));
262 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
263 ElementsAre("dev", "foo", "up", "addr",
264 "02:02:02:02:02:02", "multicast", "on"),
265 true))
266 .WillOnce(Return(0));
267
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900268 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900269 MacAddress mac_addr = {2, 2, 2, 2, 2, 2};
270 EXPECT_TRUE(datapath.ConfigureInterface("foo", mac_addr, Ipv4Addr(1, 1, 1, 1),
271 30, true, true));
Garrick Evans54861622019-07-19 09:05:09 +0900272}
273
274TEST(DatapathTest, RemoveInterface) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900275 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900276 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900277 EXPECT_CALL(runner,
278 ip(StrEq("link"), StrEq("delete"), ElementsAre("foo"), false));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900279 Datapath datapath(&runner, &firewall);
Garrick Evans54861622019-07-19 09:05:09 +0900280 datapath.RemoveInterface("foo");
Garrick Evans54861622019-07-19 09:05:09 +0900281}
282
Garrick Evans8a949dc2019-07-18 16:17:53 +0900283TEST(DatapathTest, RemoveBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900284 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900285 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900286 EXPECT_CALL(runner, iptables(StrEq("mangle"),
287 ElementsAre("-D", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900288 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900289 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900290 EXPECT_CALL(runner,
291 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "down"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900292 EXPECT_CALL(runner, brctl(StrEq("delbr"), ElementsAre("br"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900293 Datapath datapath(&runner, &firewall);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900294 datapath.RemoveBridge("br");
Garrick Evans8a949dc2019-07-18 16:17:53 +0900295}
296
Hugo Benichi321f23b2020-09-25 15:42:05 +0900297TEST(DatapathTest, AddRemoveSourceIPv4DropRule) {
298 MockProcessRunner runner;
299 MockFirewall firewall;
300 EXPECT_CALL(runner,
301 iptables(StrEq("filter"),
302 ElementsAre("-I", "OUTPUT", "-o", "eth+", "-s",
303 "100.115.92.0/24", "-j", "DROP", "-w"),
304 true, nullptr));
305 EXPECT_CALL(runner,
306 iptables(StrEq("filter"),
307 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
308 "100.115.92.0/24", "-j", "DROP", "-w"),
309 true, nullptr));
310 Datapath datapath(&runner, &firewall);
311 datapath.AddSourceIPv4DropRule("eth+", "100.115.92.0/24");
312 datapath.RemoveSourceIPv4DropRule("eth+", "100.115.92.0/24");
313}
314
Hugo Benichi8d622b52020-08-13 15:24:12 +0900315TEST(DatapathTest, StartRoutingDevice_Arc) {
316 MockProcessRunner runner;
317 MockFirewall firewall;
318 EXPECT_CALL(runner, iptables(StrEq("nat"),
319 ElementsAre("-A", "PREROUTING", "-i", "eth0",
320 "-m", "socket", "--nowildcard", "-j",
321 "ACCEPT", "-w"),
322 true, nullptr));
323 EXPECT_CALL(runner, iptables(StrEq("nat"),
324 ElementsAre("-A", "PREROUTING", "-i", "eth0",
325 "-p", "tcp", "-j", "DNAT",
326 "--to-destination", "1.2.3.4", "-w"),
327 true, nullptr));
328 EXPECT_CALL(runner, iptables(StrEq("nat"),
329 ElementsAre("-A", "PREROUTING", "-i", "eth0",
330 "-p", "udp", "-j", "DNAT",
331 "--to-destination", "1.2.3.4", "-w"),
332 true, nullptr));
333 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900334 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
335 "arc_eth0", "-j", "ACCEPT", "-w"),
336 true, nullptr));
337 EXPECT_CALL(runner, iptables(StrEq("filter"),
338 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
339 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900340 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900341 EXPECT_CALL(runner, iptables(StrEq("mangle"),
342 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
343 "-j", "MARK", "--set-mark",
344 "0x00002000/0x00003f00", "-w"),
345 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900346 EXPECT_CALL(runner, iptables(StrEq("mangle"),
347 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
348 "-j", "MARK", "--set-mark",
349 "0x03ea0000/0xffff0000", "-w"),
350 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900351 EXPECT_CALL(
352 runner,
353 ip6tables(StrEq("mangle"),
354 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
355 "--set-mark", "0x00002000/0x00003f00", "-w"),
356 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900357 EXPECT_CALL(
358 runner,
359 ip6tables(StrEq("mangle"),
360 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
361 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
362 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900363
364 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900365 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900366 datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
367 TrafficSource::ARC);
368}
369
370TEST(DatapathTest, StartRoutingDevice_CrosVM) {
371 MockProcessRunner runner;
372 MockFirewall firewall;
373 EXPECT_CALL(runner, iptables(StrEq("filter"),
374 ElementsAre("-A", "FORWARD", "-o", "vmtap0",
375 "-j", "ACCEPT", "-w"),
376 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900377 EXPECT_CALL(runner, iptables(StrEq("filter"),
378 ElementsAre("-A", "FORWARD", "-i", "vmtap0",
379 "-j", "ACCEPT", "-w"),
380 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900381 EXPECT_CALL(runner, iptables(StrEq("mangle"),
382 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
383 "-j", "MARK", "--set-mark",
384 "0x00002100/0x00003f00", "-w"),
385 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900386 EXPECT_CALL(runner, iptables(StrEq("mangle"),
387 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
388 "-j", "CONNMARK", "--restore-mark",
389 "--mask", "0xffff0000", "-w"),
390 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900391 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
392 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
393 "-j", "MARK", "--set-mark",
394 "0x00002100/0x00003f00", "-w"),
395 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900396 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
397 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
398 "-j", "CONNMARK", "--restore-mark",
399 "--mask", "0xffff0000", "-w"),
400 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900401
402 Datapath datapath(&runner, &firewall);
403 datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
404 TrafficSource::CROSVM);
405}
406
407TEST(DatapathTest, StopRoutingDevice_Arc) {
408 MockProcessRunner runner;
409 MockFirewall firewall;
410 EXPECT_CALL(runner, iptables(StrEq("nat"),
411 ElementsAre("-D", "PREROUTING", "-i", "eth0",
412 "-m", "socket", "--nowildcard", "-j",
413 "ACCEPT", "-w"),
414 true, nullptr));
415 EXPECT_CALL(runner, iptables(StrEq("nat"),
416 ElementsAre("-D", "PREROUTING", "-i", "eth0",
417 "-p", "tcp", "-j", "DNAT",
418 "--to-destination", "1.2.3.4", "-w"),
419 true, nullptr));
420 EXPECT_CALL(runner, iptables(StrEq("nat"),
421 ElementsAre("-D", "PREROUTING", "-i", "eth0",
422 "-p", "udp", "-j", "DNAT",
423 "--to-destination", "1.2.3.4", "-w"),
424 true, nullptr));
425 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900426 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
427 "arc_eth0", "-j", "ACCEPT", "-w"),
428 true, nullptr));
429 EXPECT_CALL(runner, iptables(StrEq("filter"),
430 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
431 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900432 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900433 EXPECT_CALL(runner, iptables(StrEq("mangle"),
434 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
435 "-j", "MARK", "--set-mark",
436 "0x00002000/0x00003f00", "-w"),
437 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900438 EXPECT_CALL(runner, iptables(StrEq("mangle"),
439 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
440 "-j", "MARK", "--set-mark",
441 "0x03ea0000/0xffff0000", "-w"),
442 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900443 EXPECT_CALL(
444 runner,
445 ip6tables(StrEq("mangle"),
446 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
447 "--set-mark", "0x00002000/0x00003f00", "-w"),
448 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900449 EXPECT_CALL(
450 runner,
451 ip6tables(StrEq("mangle"),
452 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
453 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
454 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900455
456 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900457 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900458 datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
459 TrafficSource::ARC);
460}
461
462TEST(DatapathTest, StopRoutingDevice_CrosVM) {
463 MockProcessRunner runner;
464 MockFirewall firewall;
465 EXPECT_CALL(runner, iptables(StrEq("filter"),
466 ElementsAre("-D", "FORWARD", "-o", "vmtap0",
467 "-j", "ACCEPT", "-w"),
468 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900469 EXPECT_CALL(runner, iptables(StrEq("filter"),
470 ElementsAre("-D", "FORWARD", "-i", "vmtap0",
471 "-j", "ACCEPT", "-w"),
472 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900473 EXPECT_CALL(runner, iptables(StrEq("mangle"),
474 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
475 "-j", "MARK", "--set-mark",
476 "0x00002100/0x00003f00", "-w"),
477 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900478 EXPECT_CALL(runner, iptables(StrEq("mangle"),
479 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
480 "-j", "CONNMARK", "--restore-mark",
481 "--mask", "0xffff0000", "-w"),
482 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900483 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
484 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
485 "-j", "MARK", "--set-mark",
486 "0x00002100/0x00003f00", "-w"),
487 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900488 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
489 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
490 "-j", "CONNMARK", "--restore-mark",
491 "--mask", "0xffff0000", "-w"),
492 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900493
494 Datapath datapath(&runner, &firewall);
495 datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
496 TrafficSource::CROSVM);
497}
498
Hugo Benichid82d8832020-08-14 10:05:03 +0900499TEST(DatapathTest, StartStopIpForwarding) {
500 struct {
501 IpFamily family;
502 std::string iif;
503 std::string oif;
504 std::vector<std::string> start_args;
505 std::vector<std::string> stop_args;
506 bool result;
507 } testcases[] = {
508 {IpFamily::IPv4, "", "", {}, {}, false},
509 {IpFamily::NONE, "foo", "bar", {}, {}, false},
510 {IpFamily::IPv4,
511 "foo",
512 "bar",
513 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
514 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
515 true},
516 {IpFamily::IPv4,
517 "",
518 "bar",
519 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
520 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
521 true},
522 {IpFamily::IPv4,
523 "foo",
524 "",
525 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
526 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
527 true},
528 {IpFamily::IPv6,
529 "foo",
530 "bar",
531 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
532 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
533 true},
534 {IpFamily::IPv6,
535 "",
536 "bar",
537 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
538 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
539 true},
540 {IpFamily::IPv6,
541 "foo",
542 "",
543 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
544 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
545 true},
546 {IpFamily::Dual,
547 "foo",
548 "bar",
549 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
550 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
551 true},
552 {IpFamily::Dual,
553 "",
554 "bar",
555 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
556 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
557 true},
558 {IpFamily::Dual,
559 "foo",
560 "",
561 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
562 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
563 true},
564 };
565
566 for (const auto& tt : testcases) {
567 MockProcessRunner runner;
568 MockFirewall firewall;
569 if (tt.result) {
570 if (tt.family & IpFamily::IPv4) {
571 EXPECT_CALL(runner,
572 iptables(StrEq("filter"), tt.start_args, true, nullptr))
573 .WillOnce(Return(0));
574 EXPECT_CALL(runner,
575 iptables(StrEq("filter"), tt.stop_args, true, nullptr))
576 .WillOnce(Return(0));
577 }
578 if (tt.family & IpFamily::IPv6) {
579 EXPECT_CALL(runner,
580 ip6tables(StrEq("filter"), tt.start_args, true, nullptr))
581 .WillOnce(Return(0));
582 EXPECT_CALL(runner,
583 ip6tables(StrEq("filter"), tt.stop_args, true, nullptr))
584 .WillOnce(Return(0));
585 }
586 }
587 Datapath datapath(&runner, &firewall);
588
589 EXPECT_EQ(tt.result, datapath.StartIpForwarding(tt.family, tt.iif, tt.oif));
590 EXPECT_EQ(tt.result, datapath.StopIpForwarding(tt.family, tt.iif, tt.oif));
591 }
592}
593
Hugo Benichi76be34a2020-08-26 22:35:54 +0900594TEST(DatapathTest, StartStopConnectionPinning) {
595 MockProcessRunner runner;
596 MockFirewall firewall;
597 EXPECT_CALL(runner, iptables(StrEq("mangle"),
598 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
599 "-j", "CONNMARK", "--set-mark",
600 "0x03eb0000/0xffff0000", "-w"),
601 true, nullptr));
602 EXPECT_CALL(runner, iptables(StrEq("mangle"),
603 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
604 "-j", "CONNMARK", "--set-mark",
605 "0x03eb0000/0xffff0000", "-w"),
606 true, nullptr));
607 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
608 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
609 "-j", "CONNMARK", "--set-mark",
610 "0x03eb0000/0xffff0000", "-w"),
611 true, nullptr));
612 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
613 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
614 "-j", "CONNMARK", "--set-mark",
615 "0x03eb0000/0xffff0000", "-w"),
616 true, nullptr));
617 Datapath datapath(&runner, &firewall);
618 datapath.SetIfnameIndex("eth0", 3);
619 datapath.StartConnectionPinning("eth0");
620 datapath.StopConnectionPinning("eth0");
621}
622
Garrick Evansf0ab7132019-06-18 14:50:42 +0900623TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900624 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900625 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900626 EXPECT_CALL(runner, iptables(StrEq("nat"),
627 ElementsAre("-A", "PREROUTING", "-i", "eth0",
628 "-m", "socket", "--nowildcard", "-j",
629 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900630 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900631 EXPECT_CALL(runner, iptables(StrEq("nat"),
632 ElementsAre("-A", "PREROUTING", "-i", "eth0",
633 "-p", "tcp", "-j", "DNAT",
634 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900635 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900636 EXPECT_CALL(runner, iptables(StrEq("nat"),
637 ElementsAre("-A", "PREROUTING", "-i", "eth0",
638 "-p", "udp", "-j", "DNAT",
639 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900640 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900641 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900642 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900643}
644
645TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900646 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900647 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900648 EXPECT_CALL(runner, iptables(StrEq("nat"),
649 ElementsAre("-D", "PREROUTING", "-i", "eth0",
650 "-m", "socket", "--nowildcard", "-j",
651 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900652 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900653 EXPECT_CALL(runner, iptables(StrEq("nat"),
654 ElementsAre("-D", "PREROUTING", "-i", "eth0",
655 "-p", "tcp", "-j", "DNAT",
656 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900657 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900658 EXPECT_CALL(runner, iptables(StrEq("nat"),
659 ElementsAre("-D", "PREROUTING", "-i", "eth0",
660 "-p", "udp", "-j", "DNAT",
661 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900662 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900663 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900664 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900665}
666
667TEST(DatapathTest, AddOutboundIPv4) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900668 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900669 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900670 EXPECT_CALL(runner, iptables(StrEq("filter"),
671 ElementsAre("-A", "FORWARD", "-o", "eth0", "-j",
672 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900673 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900674 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900675 datapath.AddOutboundIPv4("eth0");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900676}
677
678TEST(DatapathTest, RemoveInboundIPv4) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900679 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900680 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900681 EXPECT_CALL(runner, iptables(StrEq("filter"),
682 ElementsAre("-D", "FORWARD", "-o", "eth0", "-j",
683 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900684 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900685 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +0900686 datapath.RemoveOutboundIPv4("eth0");
Garrick Evansf0ab7132019-06-18 14:50:42 +0900687}
688
Garrick Evans664a82f2019-12-17 12:18:05 +0900689TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900690 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900691 MockFirewall firewall;
692 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans664a82f2019-12-17 12:18:05 +0900693 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +0900694 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +0900695 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +0900696 EXPECT_EQ(ioctl_reqs, expected);
697 ioctl_reqs.clear();
698}
699
700TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900701 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900702 MockFirewall firewall;
Taoyu Lica49c832019-12-06 17:56:43 +0900703 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +0900704 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
705 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
706 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900707 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +0900708 .WillOnce(Return(1));
709 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
710 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
711 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900712 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900713 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
714 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
715 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900716 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +0900717 .WillOnce(Return(1));
718 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
719 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
720 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900721 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900722 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +0900723 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +0900724}
725
Taoyu Lica49c832019-12-06 17:56:43 +0900726TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900727 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900728 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900729 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
730 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
731 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900732 false, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900733 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
734 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
735 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900736 false, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900737 Datapath datapath(&runner, &firewall);
Taoyu Lica49c832019-12-06 17:56:43 +0900738 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +0900739}
740
Taoyu Li90c13912019-11-26 17:56:54 +0900741TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900742 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900743 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900744 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
745 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
746 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900747 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900748 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
749 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
750 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900751 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900752 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +0900753 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +0900754}
755
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900756TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900757 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900758 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900759 EXPECT_CALL(runner,
760 ip6(StrEq("route"), StrEq("replace"),
761 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900762 Datapath datapath(&runner, &firewall);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900763 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +0900764}
765
Hugo Benichie8758b52020-04-03 14:49:01 +0900766TEST(DatapathTest, AddIPv4Route) {
767 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900768 MockFirewall firewall;
769 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichie8758b52020-04-03 14:49:01 +0900770
771 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
772 Ipv4Addr(255, 255, 255, 0));
773 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
774 Ipv4Addr(255, 255, 255, 0));
775 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
776 Ipv4Addr(255, 255, 255, 252));
777 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
778 Ipv4Addr(255, 255, 255, 252));
779
780 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
781 SIOCDELRT};
782 EXPECT_EQ(expected_reqs, ioctl_reqs);
783 ioctl_reqs.clear();
784
785 std::string route1 =
786 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
787 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
788 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
789 "RTF_GATEWAY}";
790 std::string route2 =
791 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
792 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
793 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
794 std::vector<std::string> captured_routes;
795 for (const auto& route : ioctl_rtentry_args) {
796 std::ostringstream stream;
797 stream << route.second;
798 captured_routes.emplace_back(stream.str());
799 }
800 ioctl_rtentry_args.clear();
801 EXPECT_EQ(route1, captured_routes[0]);
802 EXPECT_EQ(route1, captured_routes[1]);
803 EXPECT_EQ(route2, captured_routes[2]);
804 EXPECT_EQ(route2, captured_routes[3]);
805}
806
Garrick Evansd291af62020-05-25 10:39:06 +0900807TEST(DatapathTest, AddSNATMarkRules) {
808 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900809 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +0900810 EXPECT_CALL(
811 runner,
812 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +0900813 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +0900814 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900815 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +0900816 EXPECT_CALL(runner,
817 iptables(StrEq("filter"),
818 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
819 "1/1", "-j", "ACCEPT", "-w"),
820 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +0900821 EXPECT_CALL(runner,
822 iptables(StrEq("nat"),
823 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +0900824 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900825 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900826 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +0900827 datapath.AddSNATMarkRules();
828}
829
830TEST(DatapathTest, RemoveSNATMarkRules) {
831 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900832 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +0900833 EXPECT_CALL(
834 runner,
835 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +0900836 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +0900837 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900838 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +0900839 EXPECT_CALL(runner,
840 iptables(StrEq("filter"),
841 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
842 "1/1", "-j", "ACCEPT", "-w"),
843 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +0900844 EXPECT_CALL(runner,
845 iptables(StrEq("nat"),
846 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +0900847 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900848 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900849 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +0900850 datapath.RemoveSNATMarkRules();
851}
852
853TEST(DatapathTest, AddForwardEstablishedRule) {
854 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900855 MockFirewall firewall;
Garrick Evansd291af62020-05-25 10:39:06 +0900856 EXPECT_CALL(runner,
857 iptables(StrEq("filter"),
858 ElementsAre("-A", "FORWARD", "-m", "state", "--state",
859 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900860 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900861 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +0900862 datapath.AddForwardEstablishedRule();
863}
864
865TEST(DatapathTest, RemoveForwardEstablishedRule) {
866 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900867 MockFirewall firewall;
Garrick Evansd291af62020-05-25 10:39:06 +0900868 EXPECT_CALL(runner,
869 iptables(StrEq("filter"),
870 ElementsAre("-D", "FORWARD", "-m", "state", "--state",
871 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900872 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900873 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +0900874 datapath.RemoveForwardEstablishedRule();
875}
876
Garrick Evansff6e37f2020-05-25 10:54:47 +0900877TEST(DatapathTest, AddInterfaceSNAT) {
878 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900879 MockFirewall firewall;
Garrick Evansff6e37f2020-05-25 10:54:47 +0900880 EXPECT_CALL(runner, iptables(StrEq("nat"),
881 ElementsAre("-A", "POSTROUTING", "-o", "wwan+",
882 "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900883 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900884 Datapath datapath(&runner, &firewall);
Garrick Evansff6e37f2020-05-25 10:54:47 +0900885 datapath.AddInterfaceSNAT("wwan+");
886}
887
888TEST(DatapathTest, RemoveInterfaceSNAT) {
889 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900890 MockFirewall firewall;
Garrick Evansff6e37f2020-05-25 10:54:47 +0900891 EXPECT_CALL(runner, iptables(StrEq("nat"),
892 ElementsAre("-D", "POSTROUTING", "-o", "wwan+",
893 "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900894 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900895 Datapath datapath(&runner, &firewall);
Garrick Evansff6e37f2020-05-25 10:54:47 +0900896 datapath.RemoveInterfaceSNAT("wwan+");
897}
898
Garrick Evans2f581a02020-05-11 10:43:35 +0900899TEST(DatapathTest, ArcVethHostName) {
900 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
901 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
902 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
903 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
904 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
905 EXPECT_EQ("vethexceeds_ify", ifname);
906 EXPECT_LT(ifname.length(), IFNAMSIZ);
907}
908
Garrick Evans8a067562020-05-11 12:47:30 +0900909TEST(DatapathTest, ArcBridgeName) {
910 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
911 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
912 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
913 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
914 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
915 EXPECT_EQ("arc_exceeds_ify", ifname);
916 EXPECT_LT(ifname.length(), IFNAMSIZ);
917}
918
Garrick Evans3388a032020-03-24 11:25:55 +0900919} // namespace patchpanel