blob: 01fced0a583c3de279073a3b3ca7313bd3eb8274 [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));
Hugo Benichi2a940542020-10-26 18:50:49 +0900186 // Asserts for OUTPUT CONNMARK restore rule
187 EXPECT_CALL(runner, iptables(StrEq("mangle"),
188 ElementsAre("-A", "OUTPUT", "-j", "CONNMARK",
189 "--restore-mark", "--mask",
190 "0xffff0000", "-w"),
191 true, nullptr));
192 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
193 ElementsAre("-A", "OUTPUT", "-j", "CONNMARK",
194 "--restore-mark", "--mask",
195 "0xffff0000", "-w"),
196 true, nullptr));
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900197 // Asserts for apply_local_source_mark chain
198 EXPECT_CALL(runner,
199 iptables(StrEq("mangle"),
200 ElementsAre("-N", "apply_local_source_mark", "-w"), true,
201 nullptr));
202 EXPECT_CALL(runner,
203 iptables(StrEq("mangle"),
204 ElementsAre("-F", "apply_local_source_mark", "-w"), true,
205 nullptr));
206 EXPECT_CALL(runner, iptables(StrEq("mangle"),
207 ElementsAre("-A", "OUTPUT", "-j",
208 "apply_local_source_mark", "-w"),
209 true, nullptr));
210 EXPECT_CALL(
211 runner,
212 iptables(StrEq("mangle"),
213 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
214 "--uid-owner", "chronos", "-j", "MARK", "--set-mark",
215 "0x00008100/0x0000ff00", "-w"),
216 true, nullptr));
217 EXPECT_CALL(runner, iptables(StrEq("mangle"),
218 ElementsAre("-A", "apply_local_source_mark",
219 "-m", "owner", "--uid-owner",
220 "debugd", "-j", "MARK", "--set-mark",
221 "0x00008200/0x0000ff00", "-w"),
222 true, nullptr));
223 EXPECT_CALL(runner,
224 iptables(StrEq("mangle"),
225 ElementsAre("-A", "apply_local_source_mark", "-m",
226 "owner", "--uid-owner", "cups", "-j", "MARK",
227 "--set-mark", "0x00008200/0x0000ff00", "-w"),
228 true, nullptr));
229 EXPECT_CALL(
230 runner,
231 iptables(StrEq("mangle"),
232 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
233 "--uid-owner", "kerberosd", "-j", "MARK",
234 "--set-mark", "0x00008400/0x0000ff00", "-w"),
235 true, nullptr));
236 EXPECT_CALL(
237 runner,
238 iptables(StrEq("mangle"),
239 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
240 "--uid-owner", "kerberosd-exec", "-j", "MARK",
241 "--set-mark", "0x00008400/0x0000ff00", "-w"),
242 true, nullptr));
243 EXPECT_CALL(
244 runner,
245 iptables(StrEq("mangle"),
246 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
247 "--uid-owner", "tlsdate", "-j", "MARK", "--set-mark",
248 "0x00008400/0x0000ff00", "-w"),
249 true, nullptr));
250 EXPECT_CALL(
251 runner,
252 iptables(StrEq("mangle"),
253 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
254 "--uid-owner", "pluginvm", "-j", "MARK",
255 "--set-mark", "0x00008200/0x0000ff00", "-w"),
256 true, nullptr));
257 EXPECT_CALL(
258 runner,
259 iptables(StrEq("mangle"),
260 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
261 "--uid-owner", "fuse-smbfs", "-j", "MARK",
262 "--set-mark", "0x00008400/0x0000ff00", "-w"),
263 true, nullptr));
264 EXPECT_CALL(
265 runner,
266 iptables(StrEq("mangle"),
Hugo Benichi7e3b1fc2020-11-19 15:47:05 +0900267 ElementsAre("-A", "apply_local_source_mark", "-m", "cgroup",
268 "--cgroup", "0x00010001", "-j", "MARK", "--set-mark",
269 "0x00000300/0x0000ff00", "-w"),
270 true, nullptr));
271 EXPECT_CALL(
272 runner,
273 iptables(StrEq("mangle"),
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900274 ElementsAre("-A", "apply_local_source_mark", "-m", "mark",
275 "--mark", "0x0/0x00003f00", "-j", "MARK",
276 "--set-mark", "0x00000400/0x00003f00", "-w"),
277 true, nullptr));
278 EXPECT_CALL(runner,
279 ip6tables(StrEq("mangle"),
280 ElementsAre("-N", "apply_local_source_mark", "-w"),
281 true, nullptr));
282 EXPECT_CALL(runner,
283 ip6tables(StrEq("mangle"),
284 ElementsAre("-F", "apply_local_source_mark", "-w"),
285 true, nullptr));
286 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
287 ElementsAre("-A", "OUTPUT", "-j",
288 "apply_local_source_mark", "-w"),
289 true, nullptr));
290 EXPECT_CALL(
291 runner,
292 ip6tables(StrEq("mangle"),
293 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
294 "--uid-owner", "debugd", "-j", "MARK", "--set-mark",
295 "0x00008200/0x0000ff00", "-w"),
296 true, nullptr));
297 EXPECT_CALL(
298 runner,
299 ip6tables(StrEq("mangle"),
300 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
301 "--uid-owner", "chronos", "-j", "MARK",
302 "--set-mark", "0x00008100/0x0000ff00", "-w"),
303 true, nullptr));
304 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
305 ElementsAre("-A", "apply_local_source_mark",
306 "-m", "owner", "--uid-owner",
307 "cups", "-j", "MARK", "--set-mark",
308 "0x00008200/0x0000ff00", "-w"),
309 true, nullptr));
310 EXPECT_CALL(
311 runner,
312 ip6tables(StrEq("mangle"),
313 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
314 "--uid-owner", "kerberosd", "-j", "MARK",
315 "--set-mark", "0x00008400/0x0000ff00", "-w"),
316 true, nullptr));
317 EXPECT_CALL(
318 runner,
319 ip6tables(StrEq("mangle"),
320 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
321 "--uid-owner", "kerberosd-exec", "-j", "MARK",
322 "--set-mark", "0x00008400/0x0000ff00", "-w"),
323 true, nullptr));
324 EXPECT_CALL(
325 runner,
326 ip6tables(StrEq("mangle"),
327 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
328 "--uid-owner", "tlsdate", "-j", "MARK",
329 "--set-mark", "0x00008400/0x0000ff00", "-w"),
330 true, nullptr));
331 EXPECT_CALL(
332 runner,
333 ip6tables(StrEq("mangle"),
334 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
335 "--uid-owner", "pluginvm", "-j", "MARK",
336 "--set-mark", "0x00008200/0x0000ff00", "-w"),
337 true, nullptr));
338 EXPECT_CALL(
339 runner,
340 ip6tables(StrEq("mangle"),
341 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
342 "--uid-owner", "fuse-smbfs", "-j", "MARK",
343 "--set-mark", "0x00008400/0x0000ff00", "-w"),
344 true, nullptr));
345 EXPECT_CALL(
346 runner,
347 ip6tables(StrEq("mangle"),
Hugo Benichi7e3b1fc2020-11-19 15:47:05 +0900348 ElementsAre("-A", "apply_local_source_mark", "-m", "cgroup",
349 "--cgroup", "0x00010001", "-j", "MARK",
350 "--set-mark", "0x00000300/0x0000ff00", "-w"),
351 true, nullptr));
352 EXPECT_CALL(
353 runner,
354 ip6tables(StrEq("mangle"),
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900355 ElementsAre("-A", "apply_local_source_mark", "-m", "mark",
356 "--mark", "0x0/0x00003f00", "-j", "MARK",
357 "--set-mark", "0x00000400/0x00003f00", "-w"),
358 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900359 // Asserts for apply_vpn_mark chain
360 EXPECT_CALL(runner, iptables(StrEq("mangle"),
361 ElementsAre("-N", "apply_vpn_mark", "-w"), true,
362 nullptr));
363 EXPECT_CALL(runner, iptables(StrEq("mangle"),
364 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
365 nullptr));
366 EXPECT_CALL(runner, iptables(StrEq("mangle"),
367 ElementsAre("-A", "OUTPUT", "-m", "mark",
368 "--mark", "0x00008000/0x0000c000",
369 "-j", "apply_vpn_mark", "-w"),
370 true, nullptr));
371 EXPECT_CALL(runner, iptables(StrEq("mangle"),
372 ElementsAre("-A", "apply_vpn_mark", "-m", "mark",
373 "!", "--mark", "0x0/0xffff0000",
374 "-j", "ACCEPT", "-w"),
375 true, nullptr));
376 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
377 ElementsAre("-N", "apply_vpn_mark", "-w"), true,
378 nullptr));
379 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
380 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
381 nullptr));
382 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
383 ElementsAre("-A", "OUTPUT", "-m", "mark",
384 "--mark", "0x00008000/0x0000c000",
385 "-j", "apply_vpn_mark", "-w"),
386 true, nullptr));
387 EXPECT_CALL(
388 runner,
389 ip6tables(StrEq("mangle"),
390 ElementsAre("-A", "apply_vpn_mark", "-m", "mark", "!", "--mark",
391 "0x0/0xffff0000", "-j", "ACCEPT", "-w"),
392 true, nullptr));
Hugo Benichibf811c62020-09-07 17:30:45 +0900393
394 Datapath datapath(&runner, &firewall);
395 datapath.Start();
396}
397
398TEST(DatapathTest, Stop) {
399 MockProcessRunner runner;
400 MockFirewall firewall;
401 // Asserts for sysctl modifications
402 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_local_port_range"),
403 StrEq("32768 61000"), true));
404 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv6.conf.all.forwarding"),
405 StrEq("0"), true));
406 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_forward"), StrEq("0"), true));
407 // Asserts for RemoveOutboundIPv4SNATMark("vmtap+")
408 EXPECT_CALL(runner,
409 iptables(StrEq("mangle"),
410 ElementsAre("-D", "PREROUTING", "-i", "vmtap+", "-j",
411 "MARK", "--set-mark", "1/1", "-w"),
412 true, nullptr));
413 // Asserts for RemoveForwardEstablishedRule
414 EXPECT_CALL(runner,
415 iptables(StrEq("filter"),
416 ElementsAre("-D", "FORWARD", "-m", "state", "--state",
417 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
418 true, nullptr));
419 // Asserts for RemoveSNATMarkRules
420 EXPECT_CALL(
421 runner,
422 iptables(StrEq("filter"),
423 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
424 "state", "--state", "INVALID", "-j", "DROP", "-w"),
425 true, nullptr));
426 EXPECT_CALL(runner,
427 iptables(StrEq("filter"),
428 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
429 "1/1", "-j", "ACCEPT", "-w"),
430 true, nullptr));
431 EXPECT_CALL(runner,
432 iptables(StrEq("nat"),
433 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
434 "1/1", "-j", "MASQUERADE", "-w"),
435 true, nullptr));
436 // Asserts for RemoveSourceIPv4DropRule() calls.
437 EXPECT_CALL(runner,
438 iptables(StrEq("filter"),
439 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
440 "100.115.92.0/23", "-j", "DROP", "-w"),
441 true, nullptr));
442 EXPECT_CALL(runner,
443 iptables(StrEq("filter"),
444 ElementsAre("-D", "OUTPUT", "-o", "wlan+", "-s",
445 "100.115.92.0/23", "-j", "DROP", "-w"),
446 true, nullptr));
447 EXPECT_CALL(runner,
448 iptables(StrEq("filter"),
449 ElementsAre("-D", "OUTPUT", "-o", "mlan+", "-s",
450 "100.115.92.0/23", "-j", "DROP", "-w"),
451 true, nullptr));
452 EXPECT_CALL(runner,
453 iptables(StrEq("filter"),
454 ElementsAre("-D", "OUTPUT", "-o", "usb+", "-s",
455 "100.115.92.0/23", "-j", "DROP", "-w"),
456 true, nullptr));
457 EXPECT_CALL(runner,
458 iptables(StrEq("filter"),
459 ElementsAre("-D", "OUTPUT", "-o", "wwan+", "-s",
460 "100.115.92.0/23", "-j", "DROP", "-w"),
461 true, nullptr));
462 EXPECT_CALL(runner,
463 iptables(StrEq("filter"),
464 ElementsAre("-D", "OUTPUT", "-o", "rmnet+", "-s",
465 "100.115.92.0/23", "-j", "DROP", "-w"),
466 true, nullptr));
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900467 // Asserts for apply_local_source_mark chain
468 EXPECT_CALL(runner, iptables(StrEq("mangle"),
469 ElementsAre("-D", "OUTPUT", "-j",
470 "apply_local_source_mark", "-w"),
471 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +0900472 // Asserts for OUTPUT CONNMARK restore rule
473 EXPECT_CALL(runner, iptables(StrEq("mangle"),
474 ElementsAre("-D", "OUTPUT", "-j", "CONNMARK",
475 "--restore-mark", "--mask",
476 "0xffff0000", "-w"),
477 true, nullptr));
478 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
479 ElementsAre("-D", "OUTPUT", "-j", "CONNMARK",
480 "--restore-mark", "--mask",
481 "0xffff0000", "-w"),
482 true, nullptr));
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900483 EXPECT_CALL(runner,
484 iptables(StrEq("mangle"),
485 ElementsAre("-F", "apply_local_source_mark", "-w"), true,
486 nullptr));
487 EXPECT_CALL(runner,
488 iptables(StrEq("mangle"),
489 ElementsAre("-X", "apply_local_source_mark", "-w"), true,
490 nullptr));
491 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
492 ElementsAre("-D", "OUTPUT", "-j",
493 "apply_local_source_mark", "-w"),
494 true, nullptr));
495 EXPECT_CALL(runner,
496 ip6tables(StrEq("mangle"),
497 ElementsAre("-F", "apply_local_source_mark", "-w"),
498 true, nullptr));
499 EXPECT_CALL(runner,
500 ip6tables(StrEq("mangle"),
501 ElementsAre("-X", "apply_local_source_mark", "-w"),
502 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900503 // Asserts for apply_vpn_mark chain
504 EXPECT_CALL(runner, iptables(StrEq("mangle"),
505 ElementsAre("-D", "OUTPUT", "-m", "mark",
506 "--mark", "0x00008000/0x0000c000",
507 "-j", "apply_vpn_mark", "-w"),
508 true, nullptr));
509 EXPECT_CALL(runner, iptables(StrEq("mangle"),
510 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
511 nullptr));
512 EXPECT_CALL(runner, iptables(StrEq("mangle"),
513 ElementsAre("-X", "apply_vpn_mark", "-w"), true,
514 nullptr));
515 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
516 ElementsAre("-D", "OUTPUT", "-m", "mark",
517 "--mark", "0x00008000/0x0000c000",
518 "-j", "apply_vpn_mark", "-w"),
519 true, nullptr));
520 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
521 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
522 nullptr));
523 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
524 ElementsAre("-X", "apply_vpn_mark", "-w"), true,
525 nullptr));
Hugo Benichibf811c62020-09-07 17:30:45 +0900526
527 Datapath datapath(&runner, &firewall);
528 datapath.Stop();
529}
530
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900531TEST(DatapathTest, AddTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900532 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900533 MockFirewall firewall;
534 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900535 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900536 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900537 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900538 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900539 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900540 std::vector<ioctl_req_t> expected = {
541 TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, SIOCSIFNETMASK,
542 SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900543 EXPECT_EQ(ioctl_reqs, expected);
544 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900545 ioctl_rtentry_args.clear();
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900546}
547
548TEST(DatapathTest, AddTAPWithOwner) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900549 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900550 MockFirewall firewall;
551 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900552 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900553 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900554 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900555 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900556 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900557 std::vector<ioctl_req_t> expected = {
558 TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, SIOCSIFADDR,
559 SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900560 EXPECT_EQ(ioctl_reqs, expected);
561 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900562 ioctl_rtentry_args.clear();
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900563}
564
Garrick Evans621ed262019-11-13 12:28:43 +0900565TEST(DatapathTest, AddTAPNoAddrs) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900566 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900567 MockFirewall firewall;
568 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900569 auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, "");
Garrick Evans621ed262019-11-13 12:28:43 +0900570 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900571 std::vector<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS,
572 SIOCSIFFLAGS};
Garrick Evans621ed262019-11-13 12:28:43 +0900573 EXPECT_EQ(ioctl_reqs, expected);
574 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900575 ioctl_rtentry_args.clear();
Garrick Evans621ed262019-11-13 12:28:43 +0900576}
577
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900578TEST(DatapathTest, RemoveTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900579 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900580 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900581 EXPECT_CALL(runner, ip(StrEq("tuntap"), StrEq("del"),
582 ElementsAre("foo0", "mode", "tap"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900583 Datapath datapath(&runner, &firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900584 datapath.RemoveTAP("foo0");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900585}
Garrick Evansf0ab7132019-06-18 14:50:42 +0900586
Hugo Benichi33860d72020-07-09 16:34:01 +0900587TEST(DatapathTest, NetnsAttachName) {
588 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900589 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900590 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
591 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), 1234, true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900592 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900593 EXPECT_TRUE(datapath.NetnsAttachName("netns_foo", 1234));
594}
595
596TEST(DatapathTest, NetnsDeleteName) {
597 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900598 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900599 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900600 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900601 EXPECT_TRUE(datapath.NetnsDeleteName("netns_foo"));
602}
603
Garrick Evans8a949dc2019-07-18 16:17:53 +0900604TEST(DatapathTest, AddBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900605 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900606 MockFirewall firewall;
607 Datapath datapath(&runner, &firewall);
Garrick Evans8e8e3472020-01-23 14:03:50 +0900608 EXPECT_CALL(runner, brctl(StrEq("addbr"), ElementsAre("br"), true));
Garrick Evans6f4fa3a2020-02-10 16:15:09 +0900609 EXPECT_CALL(
610 runner,
611 ip(StrEq("addr"), StrEq("add"),
612 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "br"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900613 EXPECT_CALL(runner,
614 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "up"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900615 EXPECT_CALL(runner, iptables(StrEq("mangle"),
616 ElementsAre("-A", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900617 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900618 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900619 datapath.AddBridge("br", Ipv4Addr(1, 1, 1, 1), 30);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900620}
621
Hugo Benichi76675592020-04-08 14:29:57 +0900622TEST(DatapathTest, ConnectVethPair) {
623 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900624 MockFirewall firewall;
Hugo Benichi76675592020-04-08 14:29:57 +0900625 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
626 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900627 "peer_foo", "netns", "netns_foo"),
Hugo Benichi76675592020-04-08 14:29:57 +0900628 true));
629 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
630 ElementsAre("100.115.92.169/30", "brd",
631 "100.115.92.171", "dev", "peer_foo"),
632 true))
633 .WillOnce(Return(0));
634 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
635 ElementsAre("dev", "peer_foo", "up", "addr",
636 "01:02:03:04:05:06", "multicast", "on"),
637 true))
638 .WillOnce(Return(0));
Hugo Benichi76675592020-04-08 14:29:57 +0900639 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
640 ElementsAre("veth_foo", "up"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900641 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900642 EXPECT_TRUE(datapath.ConnectVethPair(kTestPID, "netns_foo", "veth_foo",
643 "peer_foo", {1, 2, 3, 4, 5, 6},
Hugo Benichi76675592020-04-08 14:29:57 +0900644 Ipv4Addr(100, 115, 92, 169), 30, true));
645}
646
Garrick Evans2470caa2020-03-04 14:15:41 +0900647TEST(DatapathTest, AddVirtualInterfacePair) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900648 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900649 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900650 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
651 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900652 "peer_foo", "netns", "netns_foo"),
Garrick Evans8e8e3472020-01-23 14:03:50 +0900653 true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900654 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900655 EXPECT_TRUE(
656 datapath.AddVirtualInterfacePair("netns_foo", "veth_foo", "peer_foo"));
Garrick Evans2470caa2020-03-04 14:15:41 +0900657}
658
659TEST(DatapathTest, ToggleInterface) {
660 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900661 MockFirewall firewall;
Garrick Evans2470caa2020-03-04 14:15:41 +0900662 EXPECT_CALL(runner,
663 ip(StrEq("link"), StrEq("set"), ElementsAre("foo", "up"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900664 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
Garrick Evans2470caa2020-03-04 14:15:41 +0900665 ElementsAre("bar", "down"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900666 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900667 EXPECT_TRUE(datapath.ToggleInterface("foo", true));
668 EXPECT_TRUE(datapath.ToggleInterface("bar", false));
669}
670
671TEST(DatapathTest, ConfigureInterface) {
672 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900673 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900674 EXPECT_CALL(
675 runner,
Garrick Evans2470caa2020-03-04 14:15:41 +0900676 ip(StrEq("addr"), StrEq("add"),
677 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "foo"), true))
678 .WillOnce(Return(0));
679 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
680 ElementsAre("dev", "foo", "up", "addr",
681 "02:02:02:02:02:02", "multicast", "on"),
682 true))
683 .WillOnce(Return(0));
684
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900685 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900686 MacAddress mac_addr = {2, 2, 2, 2, 2, 2};
687 EXPECT_TRUE(datapath.ConfigureInterface("foo", mac_addr, Ipv4Addr(1, 1, 1, 1),
688 30, true, true));
Garrick Evans54861622019-07-19 09:05:09 +0900689}
690
691TEST(DatapathTest, RemoveInterface) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900692 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900693 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900694 EXPECT_CALL(runner,
695 ip(StrEq("link"), StrEq("delete"), ElementsAre("foo"), false));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900696 Datapath datapath(&runner, &firewall);
Garrick Evans54861622019-07-19 09:05:09 +0900697 datapath.RemoveInterface("foo");
Garrick Evans54861622019-07-19 09:05:09 +0900698}
699
Garrick Evans8a949dc2019-07-18 16:17:53 +0900700TEST(DatapathTest, RemoveBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900701 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900702 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900703 EXPECT_CALL(runner, iptables(StrEq("mangle"),
704 ElementsAre("-D", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900705 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900706 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900707 EXPECT_CALL(runner,
708 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "down"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900709 EXPECT_CALL(runner, brctl(StrEq("delbr"), ElementsAre("br"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900710 Datapath datapath(&runner, &firewall);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900711 datapath.RemoveBridge("br");
Garrick Evans8a949dc2019-07-18 16:17:53 +0900712}
713
Hugo Benichi321f23b2020-09-25 15:42:05 +0900714TEST(DatapathTest, AddRemoveSourceIPv4DropRule) {
715 MockProcessRunner runner;
716 MockFirewall firewall;
717 EXPECT_CALL(runner,
718 iptables(StrEq("filter"),
719 ElementsAre("-I", "OUTPUT", "-o", "eth+", "-s",
720 "100.115.92.0/24", "-j", "DROP", "-w"),
721 true, nullptr));
722 EXPECT_CALL(runner,
723 iptables(StrEq("filter"),
724 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
725 "100.115.92.0/24", "-j", "DROP", "-w"),
726 true, nullptr));
727 Datapath datapath(&runner, &firewall);
728 datapath.AddSourceIPv4DropRule("eth+", "100.115.92.0/24");
729 datapath.RemoveSourceIPv4DropRule("eth+", "100.115.92.0/24");
730}
731
Hugo Benichi7c342672020-09-08 09:18:14 +0900732TEST(DatapathTest, StartRoutingNamespace) {
733 MockProcessRunner runner;
734 MockFirewall firewall;
735 MacAddress mac = {1, 2, 3, 4, 5, 6};
736
737 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
738 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), kTestPID, true));
739 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
740 ElementsAre("arc_ns0", "type", "veth", "peer", "name",
741 "veth0", "netns", "netns_foo"),
742 true));
743 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
744 ElementsAre("100.115.92.130/30", "brd",
745 "100.115.92.131", "dev", "veth0"),
746 true))
747 .WillOnce(Return(0));
748 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
749 ElementsAre("dev", "veth0", "up", "addr",
750 "01:02:03:04:05:06", "multicast", "off"),
751 true))
752 .WillOnce(Return(0));
753 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
754 ElementsAre("arc_ns0", "up"), true));
755 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
756 ElementsAre("100.115.92.129/30", "brd",
757 "100.115.92.131", "dev", "arc_ns0"),
758 true))
759 .WillOnce(Return(0));
760 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
761 ElementsAre("dev", "arc_ns0", "up", "addr",
762 "01:02:03:04:05:06", "multicast", "off"),
763 true))
764 .WillOnce(Return(0));
765 EXPECT_CALL(runner, iptables(StrEq("filter"),
766 ElementsAre("-A", "FORWARD", "-o", "arc_ns0",
767 "-j", "ACCEPT", "-w"),
768 true, nullptr));
769 EXPECT_CALL(runner,
770 iptables(StrEq("mangle"),
771 ElementsAre("-A", "PREROUTING", "-i", "arc_ns0", "-j",
772 "MARK", "--set-mark", "1/1", "-w"),
773 true, nullptr));
774
Hugo Benichifcf81022020-12-04 11:01:37 +0900775 ConnectedNamespace nsinfo = {};
776 nsinfo.pid = kTestPID;
777 nsinfo.netns_name = "netns_foo";
778 nsinfo.outbound_ifname = "";
779 nsinfo.host_ifname = "arc_ns0";
780 nsinfo.peer_ifname = "veth0";
781 nsinfo.peer_subnet = std::make_unique<Subnet>(Ipv4Addr(100, 115, 92, 128), 30,
782 base::DoNothing());
783 nsinfo.peer_mac_addr = mac;
Hugo Benichi7c342672020-09-08 09:18:14 +0900784 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichifcf81022020-12-04 11:01:37 +0900785 datapath.StartRoutingNamespace(nsinfo);
Hugo Benichi7c342672020-09-08 09:18:14 +0900786 ioctl_reqs.clear();
787 ioctl_rtentry_args.clear();
788}
789
790TEST(DatapathTest, StopRoutingNamespace) {
791 MockProcessRunner runner;
792 MockFirewall firewall;
793
794 EXPECT_CALL(runner, iptables(StrEq("filter"),
795 ElementsAre("-D", "FORWARD", "-o", "arc_ns0",
796 "-j", "ACCEPT", "-w"),
797 true, nullptr));
798 EXPECT_CALL(runner,
799 iptables(StrEq("mangle"),
800 ElementsAre("-D", "PREROUTING", "-i", "arc_ns0", "-j",
801 "MARK", "--set-mark", "1/1", "-w"),
802 true, nullptr));
803 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
804 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("delete"), ElementsAre("arc_ns0"),
805 false));
806
Hugo Benichifcf81022020-12-04 11:01:37 +0900807 ConnectedNamespace nsinfo = {};
808 nsinfo.pid = kTestPID;
809 nsinfo.netns_name = "netns_foo";
810 nsinfo.outbound_ifname = "";
811 nsinfo.host_ifname = "arc_ns0";
812 nsinfo.peer_ifname = "veth0";
813 nsinfo.peer_subnet = std::make_unique<Subnet>(Ipv4Addr(100, 115, 92, 128), 30,
814 base::DoNothing());
Hugo Benichi7c342672020-09-08 09:18:14 +0900815 Datapath datapath(&runner, &firewall);
Hugo Benichifcf81022020-12-04 11:01:37 +0900816 datapath.StopRoutingNamespace(nsinfo);
Hugo Benichi7c342672020-09-08 09:18:14 +0900817}
818
Hugo Benichi8d622b52020-08-13 15:24:12 +0900819TEST(DatapathTest, StartRoutingDevice_Arc) {
820 MockProcessRunner runner;
821 MockFirewall firewall;
822 EXPECT_CALL(runner, iptables(StrEq("nat"),
823 ElementsAre("-A", "PREROUTING", "-i", "eth0",
824 "-m", "socket", "--nowildcard", "-j",
825 "ACCEPT", "-w"),
826 true, nullptr));
827 EXPECT_CALL(runner, iptables(StrEq("nat"),
828 ElementsAre("-A", "PREROUTING", "-i", "eth0",
829 "-p", "tcp", "-j", "DNAT",
830 "--to-destination", "1.2.3.4", "-w"),
831 true, nullptr));
832 EXPECT_CALL(runner, iptables(StrEq("nat"),
833 ElementsAre("-A", "PREROUTING", "-i", "eth0",
834 "-p", "udp", "-j", "DNAT",
835 "--to-destination", "1.2.3.4", "-w"),
836 true, nullptr));
837 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900838 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
839 "arc_eth0", "-j", "ACCEPT", "-w"),
840 true, nullptr));
841 EXPECT_CALL(runner, iptables(StrEq("filter"),
842 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
843 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900844 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900845 EXPECT_CALL(runner, iptables(StrEq("mangle"),
846 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
847 "-j", "MARK", "--set-mark",
848 "0x00002000/0x00003f00", "-w"),
849 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900850 EXPECT_CALL(runner, iptables(StrEq("mangle"),
851 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
852 "-j", "MARK", "--set-mark",
853 "0x03ea0000/0xffff0000", "-w"),
854 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900855 EXPECT_CALL(
856 runner,
857 ip6tables(StrEq("mangle"),
858 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
859 "--set-mark", "0x00002000/0x00003f00", "-w"),
860 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900861 EXPECT_CALL(
862 runner,
863 ip6tables(StrEq("mangle"),
864 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
865 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
866 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900867
868 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900869 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900870 datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
871 TrafficSource::ARC);
872}
873
874TEST(DatapathTest, StartRoutingDevice_CrosVM) {
875 MockProcessRunner runner;
876 MockFirewall firewall;
877 EXPECT_CALL(runner, iptables(StrEq("filter"),
878 ElementsAre("-A", "FORWARD", "-o", "vmtap0",
879 "-j", "ACCEPT", "-w"),
880 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900881 EXPECT_CALL(runner, iptables(StrEq("filter"),
882 ElementsAre("-A", "FORWARD", "-i", "vmtap0",
883 "-j", "ACCEPT", "-w"),
884 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900885 EXPECT_CALL(runner, iptables(StrEq("mangle"),
886 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
887 "-j", "MARK", "--set-mark",
888 "0x00002100/0x00003f00", "-w"),
889 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900890 EXPECT_CALL(runner, iptables(StrEq("mangle"),
891 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
892 "-j", "CONNMARK", "--restore-mark",
893 "--mask", "0xffff0000", "-w"),
894 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900895 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
896 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
897 "-j", "MARK", "--set-mark",
898 "0x00002100/0x00003f00", "-w"),
899 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900900 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
901 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
902 "-j", "CONNMARK", "--restore-mark",
903 "--mask", "0xffff0000", "-w"),
904 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900905 EXPECT_CALL(runner, iptables(StrEq("mangle"),
906 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
907 "-j", "apply_vpn_mark", "-w"),
908 true, nullptr));
909 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
910 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
911 "-j", "apply_vpn_mark", "-w"),
912 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900913
914 Datapath datapath(&runner, &firewall);
915 datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
916 TrafficSource::CROSVM);
917}
918
919TEST(DatapathTest, StopRoutingDevice_Arc) {
920 MockProcessRunner runner;
921 MockFirewall firewall;
922 EXPECT_CALL(runner, iptables(StrEq("nat"),
923 ElementsAre("-D", "PREROUTING", "-i", "eth0",
924 "-m", "socket", "--nowildcard", "-j",
925 "ACCEPT", "-w"),
926 true, nullptr));
927 EXPECT_CALL(runner, iptables(StrEq("nat"),
928 ElementsAre("-D", "PREROUTING", "-i", "eth0",
929 "-p", "tcp", "-j", "DNAT",
930 "--to-destination", "1.2.3.4", "-w"),
931 true, nullptr));
932 EXPECT_CALL(runner, iptables(StrEq("nat"),
933 ElementsAre("-D", "PREROUTING", "-i", "eth0",
934 "-p", "udp", "-j", "DNAT",
935 "--to-destination", "1.2.3.4", "-w"),
936 true, nullptr));
937 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900938 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
939 "arc_eth0", "-j", "ACCEPT", "-w"),
940 true, nullptr));
941 EXPECT_CALL(runner, iptables(StrEq("filter"),
942 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
943 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900944 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900945 EXPECT_CALL(runner, iptables(StrEq("mangle"),
946 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
947 "-j", "MARK", "--set-mark",
948 "0x00002000/0x00003f00", "-w"),
949 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900950 EXPECT_CALL(runner, iptables(StrEq("mangle"),
951 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
952 "-j", "MARK", "--set-mark",
953 "0x03ea0000/0xffff0000", "-w"),
954 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900955 EXPECT_CALL(
956 runner,
957 ip6tables(StrEq("mangle"),
958 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
959 "--set-mark", "0x00002000/0x00003f00", "-w"),
960 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900961 EXPECT_CALL(
962 runner,
963 ip6tables(StrEq("mangle"),
964 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
965 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
966 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900967
968 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900969 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900970 datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
971 TrafficSource::ARC);
972}
973
974TEST(DatapathTest, StopRoutingDevice_CrosVM) {
975 MockProcessRunner runner;
976 MockFirewall firewall;
977 EXPECT_CALL(runner, iptables(StrEq("filter"),
978 ElementsAre("-D", "FORWARD", "-o", "vmtap0",
979 "-j", "ACCEPT", "-w"),
980 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900981 EXPECT_CALL(runner, iptables(StrEq("filter"),
982 ElementsAre("-D", "FORWARD", "-i", "vmtap0",
983 "-j", "ACCEPT", "-w"),
984 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900985 EXPECT_CALL(runner, iptables(StrEq("mangle"),
986 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
987 "-j", "MARK", "--set-mark",
988 "0x00002100/0x00003f00", "-w"),
989 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900990 EXPECT_CALL(runner, iptables(StrEq("mangle"),
991 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
992 "-j", "CONNMARK", "--restore-mark",
993 "--mask", "0xffff0000", "-w"),
994 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900995 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
996 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
997 "-j", "MARK", "--set-mark",
998 "0x00002100/0x00003f00", "-w"),
999 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +09001000 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1001 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
1002 "-j", "CONNMARK", "--restore-mark",
1003 "--mask", "0xffff0000", "-w"),
1004 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +09001005 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1006 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
1007 "-j", "apply_vpn_mark", "-w"),
1008 true, nullptr));
1009 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1010 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
1011 "-j", "apply_vpn_mark", "-w"),
1012 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +09001013
1014 Datapath datapath(&runner, &firewall);
1015 datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
1016 TrafficSource::CROSVM);
1017}
1018
Hugo Benichid82d8832020-08-14 10:05:03 +09001019TEST(DatapathTest, StartStopIpForwarding) {
1020 struct {
1021 IpFamily family;
1022 std::string iif;
1023 std::string oif;
1024 std::vector<std::string> start_args;
1025 std::vector<std::string> stop_args;
1026 bool result;
1027 } testcases[] = {
1028 {IpFamily::IPv4, "", "", {}, {}, false},
1029 {IpFamily::NONE, "foo", "bar", {}, {}, false},
1030 {IpFamily::IPv4,
1031 "foo",
1032 "bar",
1033 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1034 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1035 true},
1036 {IpFamily::IPv4,
1037 "",
1038 "bar",
1039 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1040 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1041 true},
1042 {IpFamily::IPv4,
1043 "foo",
1044 "",
1045 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1046 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1047 true},
1048 {IpFamily::IPv6,
1049 "foo",
1050 "bar",
1051 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1052 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1053 true},
1054 {IpFamily::IPv6,
1055 "",
1056 "bar",
1057 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1058 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1059 true},
1060 {IpFamily::IPv6,
1061 "foo",
1062 "",
1063 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1064 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1065 true},
1066 {IpFamily::Dual,
1067 "foo",
1068 "bar",
1069 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1070 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1071 true},
1072 {IpFamily::Dual,
1073 "",
1074 "bar",
1075 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1076 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1077 true},
1078 {IpFamily::Dual,
1079 "foo",
1080 "",
1081 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1082 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1083 true},
1084 };
1085
1086 for (const auto& tt : testcases) {
1087 MockProcessRunner runner;
1088 MockFirewall firewall;
1089 if (tt.result) {
1090 if (tt.family & IpFamily::IPv4) {
1091 EXPECT_CALL(runner,
1092 iptables(StrEq("filter"), tt.start_args, true, nullptr))
1093 .WillOnce(Return(0));
1094 EXPECT_CALL(runner,
1095 iptables(StrEq("filter"), tt.stop_args, true, nullptr))
1096 .WillOnce(Return(0));
1097 }
1098 if (tt.family & IpFamily::IPv6) {
1099 EXPECT_CALL(runner,
1100 ip6tables(StrEq("filter"), tt.start_args, true, nullptr))
1101 .WillOnce(Return(0));
1102 EXPECT_CALL(runner,
1103 ip6tables(StrEq("filter"), tt.stop_args, true, nullptr))
1104 .WillOnce(Return(0));
1105 }
1106 }
1107 Datapath datapath(&runner, &firewall);
1108
1109 EXPECT_EQ(tt.result, datapath.StartIpForwarding(tt.family, tt.iif, tt.oif));
1110 EXPECT_EQ(tt.result, datapath.StopIpForwarding(tt.family, tt.iif, tt.oif));
1111 }
1112}
1113
Hugo Benichi76be34a2020-08-26 22:35:54 +09001114TEST(DatapathTest, StartStopConnectionPinning) {
1115 MockProcessRunner runner;
1116 MockFirewall firewall;
Hugo Benichi1af52392020-11-27 18:09:32 +09001117
1118 // Setup
Hugo Benichi76be34a2020-08-26 22:35:54 +09001119 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1120 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1121 "-j", "CONNMARK", "--set-mark",
1122 "0x03eb0000/0xffff0000", "-w"),
1123 true, nullptr));
Hugo Benichi76be34a2020-08-26 22:35:54 +09001124 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1125 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1126 "-j", "CONNMARK", "--set-mark",
1127 "0x03eb0000/0xffff0000", "-w"),
1128 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001129 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1130 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1131 "-j", "CONNMARK", "--save-mark",
1132 "--mask", "0x00003f00", "-w"),
1133 true, nullptr));
1134 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1135 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1136 "-j", "CONNMARK", "--save-mark",
1137 "--mask", "0x00003f00", "-w"),
1138 true, nullptr));
1139 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1140 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1141 "-j", "CONNMARK", "--restore-mark",
1142 "--mask", "0x00003f00", "-w"),
1143 true, nullptr));
1144 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1145 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1146 "-j", "CONNMARK", "--restore-mark",
1147 "--mask", "0x00003f00", "-w"),
1148 true, nullptr));
1149 // Teardown
1150 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1151 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1152 "-j", "CONNMARK", "--set-mark",
1153 "0x03eb0000/0xffff0000", "-w"),
1154 true, nullptr));
Hugo Benichi76be34a2020-08-26 22:35:54 +09001155 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1156 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1157 "-j", "CONNMARK", "--set-mark",
1158 "0x03eb0000/0xffff0000", "-w"),
1159 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001160 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1161 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1162 "-j", "CONNMARK", "--save-mark",
1163 "--mask", "0x00003f00", "-w"),
1164 true, nullptr));
1165 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1166 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1167 "-j", "CONNMARK", "--save-mark",
1168 "--mask", "0x00003f00", "-w"),
1169 true, nullptr));
1170 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1171 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1172 "-j", "CONNMARK", "--restore-mark",
1173 "--mask", "0x00003f00", "-w"),
1174 true, nullptr));
1175 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1176 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1177 "-j", "CONNMARK", "--restore-mark",
1178 "--mask", "0x00003f00", "-w"),
1179 true, nullptr));
1180
Hugo Benichi76be34a2020-08-26 22:35:54 +09001181 Datapath datapath(&runner, &firewall);
1182 datapath.SetIfnameIndex("eth0", 3);
1183 datapath.StartConnectionPinning("eth0");
1184 datapath.StopConnectionPinning("eth0");
1185}
1186
Hugo Benichi2a940542020-10-26 18:50:49 +09001187TEST(DatapathTest, StartStopVpnRouting_NoVirtualDevices) {
1188 MockProcessRunner runner;
1189 MockFirewall firewall;
1190
1191 // Setup
1192 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1193 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1194 "-j", "CONNMARK", "--set-mark",
1195 "0x03ed0000/0xffff0000", "-w"),
1196 true, nullptr));
1197 EXPECT_CALL(runner,
1198 iptables(StrEq("mangle"),
1199 ElementsAre("-A", "apply_vpn_mark", "-j", "MARK",
1200 "--set-mark", "0x03ed0000/0xffff0000", "-w"),
1201 true, nullptr));
1202 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1203 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1204 "-j", "CONNMARK", "--set-mark",
1205 "0x03ed0000/0xffff0000", "-w"),
1206 true, nullptr));
1207 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1208 ElementsAre("-A", "apply_vpn_mark", "-j",
1209 "MARK", "--set-mark",
1210 "0x03ed0000/0xffff0000", "-w"),
1211 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001212 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1213 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1214 "-j", "CONNMARK", "--save-mark",
1215 "--mask", "0x00003f00", "-w"),
1216 true, nullptr));
1217 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1218 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1219 "-j", "CONNMARK", "--save-mark",
1220 "--mask", "0x00003f00", "-w"),
1221 true, nullptr));
1222 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1223 ElementsAre("-A", "PREROUTING", "-i", "arcbr0",
1224 "-j", "CONNMARK", "--restore-mark",
1225 "--mask", "0x00003f00", "-w"),
1226 true, nullptr));
1227 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1228 ElementsAre("-A", "PREROUTING", "-i", "arcbr0",
1229 "-j", "CONNMARK", "--restore-mark",
1230 "--mask", "0x00003f00", "-w"),
1231 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +09001232 // Teardown
1233 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1234 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1235 "-j", "CONNMARK", "--set-mark",
1236 "0x03ed0000/0xffff0000", "-w"),
1237 true, nullptr));
1238 EXPECT_CALL(runner,
1239 iptables(StrEq("mangle"),
1240 ElementsAre("-D", "apply_vpn_mark", "-j", "MARK",
1241 "--set-mark", "0x03ed0000/0xffff0000", "-w"),
1242 true, nullptr));
1243 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1244 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1245 "-j", "CONNMARK", "--set-mark",
1246 "0x03ed0000/0xffff0000", "-w"),
1247 true, nullptr));
1248 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1249 ElementsAre("-D", "apply_vpn_mark", "-j",
1250 "MARK", "--set-mark",
1251 "0x03ed0000/0xffff0000", "-w"),
1252 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001253 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1254 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1255 "-j", "CONNMARK", "--save-mark",
1256 "--mask", "0x00003f00", "-w"),
1257 true, nullptr));
1258 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1259 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1260 "-j", "CONNMARK", "--save-mark",
1261 "--mask", "0x00003f00", "-w"),
1262 true, nullptr));
1263 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1264 ElementsAre("-D", "PREROUTING", "-i", "arcbr0",
1265 "-j", "CONNMARK", "--restore-mark",
1266 "--mask", "0x00003f00", "-w"),
1267 true, nullptr));
1268 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1269 ElementsAre("-D", "PREROUTING", "-i", "arcbr0",
1270 "-j", "CONNMARK", "--restore-mark",
1271 "--mask", "0x00003f00", "-w"),
1272 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +09001273
1274 Datapath datapath(&runner, &firewall);
1275 datapath.SetIfnameIndex("arcbr0", 5);
1276 datapath.StartVpnRouting("arcbr0");
1277 datapath.StopVpnRouting("arcbr0");
1278}
1279
Garrick Evansf0ab7132019-06-18 14:50:42 +09001280TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001281 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001282 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001283 EXPECT_CALL(runner, iptables(StrEq("nat"),
1284 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1285 "-m", "socket", "--nowildcard", "-j",
1286 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001287 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001288 EXPECT_CALL(runner, iptables(StrEq("nat"),
1289 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1290 "-p", "tcp", "-j", "DNAT",
1291 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001292 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001293 EXPECT_CALL(runner, iptables(StrEq("nat"),
1294 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1295 "-p", "udp", "-j", "DNAT",
1296 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001297 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001298 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001299 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001300}
1301
1302TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001303 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001304 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001305 EXPECT_CALL(runner, iptables(StrEq("nat"),
1306 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1307 "-m", "socket", "--nowildcard", "-j",
1308 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001309 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001310 EXPECT_CALL(runner, iptables(StrEq("nat"),
1311 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1312 "-p", "tcp", "-j", "DNAT",
1313 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001314 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001315 EXPECT_CALL(runner, iptables(StrEq("nat"),
1316 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1317 "-p", "udp", "-j", "DNAT",
1318 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001319 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001320 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001321 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001322}
1323
Garrick Evans664a82f2019-12-17 12:18:05 +09001324TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001325 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001326 MockFirewall firewall;
1327 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Hugo Benichi7c342672020-09-08 09:18:14 +09001328
Garrick Evans664a82f2019-12-17 12:18:05 +09001329 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +09001330 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +09001331 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +09001332 EXPECT_EQ(ioctl_reqs, expected);
1333 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +09001334 ioctl_rtentry_args.clear();
Taoyu Li90c13912019-11-26 17:56:54 +09001335}
1336
1337TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001338 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001339 MockFirewall firewall;
Taoyu Lica49c832019-12-06 17:56:43 +09001340 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +09001341 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1342 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1343 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001344 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001345 .WillOnce(Return(1));
1346 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1347 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
1348 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001349 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001350 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1351 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1352 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001353 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001354 .WillOnce(Return(1));
1355 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1356 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
1357 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001358 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001359 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001360 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001361}
1362
Taoyu Lica49c832019-12-06 17:56:43 +09001363TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001364 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001365 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001366 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1367 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1368 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001369 false, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001370 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1371 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1372 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001373 false, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001374 Datapath datapath(&runner, &firewall);
Taoyu Lica49c832019-12-06 17:56:43 +09001375 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +09001376}
1377
Taoyu Li90c13912019-11-26 17:56:54 +09001378TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001379 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001380 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001381 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1382 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
1383 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001384 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001385 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1386 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
1387 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001388 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001389 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001390 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001391}
1392
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001393TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001394 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001395 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001396 EXPECT_CALL(runner,
1397 ip6(StrEq("route"), StrEq("replace"),
1398 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001399 Datapath datapath(&runner, &firewall);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001400 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001401}
1402
Hugo Benichie8758b52020-04-03 14:49:01 +09001403TEST(DatapathTest, AddIPv4Route) {
1404 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001405 MockFirewall firewall;
1406 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichie8758b52020-04-03 14:49:01 +09001407
1408 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1409 Ipv4Addr(255, 255, 255, 0));
1410 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1411 Ipv4Addr(255, 255, 255, 0));
1412 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1413 Ipv4Addr(255, 255, 255, 252));
1414 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1415 Ipv4Addr(255, 255, 255, 252));
1416
1417 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
1418 SIOCDELRT};
1419 EXPECT_EQ(expected_reqs, ioctl_reqs);
Hugo Benichie8758b52020-04-03 14:49:01 +09001420
1421 std::string route1 =
1422 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
1423 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
1424 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
1425 "RTF_GATEWAY}";
1426 std::string route2 =
1427 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
1428 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
1429 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
1430 std::vector<std::string> captured_routes;
1431 for (const auto& route : ioctl_rtentry_args) {
1432 std::ostringstream stream;
1433 stream << route.second;
1434 captured_routes.emplace_back(stream.str());
1435 }
Hugo Benichie8758b52020-04-03 14:49:01 +09001436 EXPECT_EQ(route1, captured_routes[0]);
1437 EXPECT_EQ(route1, captured_routes[1]);
1438 EXPECT_EQ(route2, captured_routes[2]);
1439 EXPECT_EQ(route2, captured_routes[3]);
Hugo Benichi7c342672020-09-08 09:18:14 +09001440 ioctl_reqs.clear();
1441 ioctl_rtentry_args.clear();
Hugo Benichie8758b52020-04-03 14:49:01 +09001442}
1443
Garrick Evansd291af62020-05-25 10:39:06 +09001444TEST(DatapathTest, AddSNATMarkRules) {
1445 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001446 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001447 EXPECT_CALL(
1448 runner,
1449 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001450 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001451 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001452 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001453 EXPECT_CALL(runner,
1454 iptables(StrEq("filter"),
1455 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
1456 "1/1", "-j", "ACCEPT", "-w"),
1457 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001458 EXPECT_CALL(runner,
1459 iptables(StrEq("nat"),
1460 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001461 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001462 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001463 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001464 datapath.AddSNATMarkRules();
1465}
1466
1467TEST(DatapathTest, RemoveSNATMarkRules) {
1468 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001469 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001470 EXPECT_CALL(
1471 runner,
1472 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001473 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001474 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001475 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001476 EXPECT_CALL(runner,
1477 iptables(StrEq("filter"),
1478 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
1479 "1/1", "-j", "ACCEPT", "-w"),
1480 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001481 EXPECT_CALL(runner,
1482 iptables(StrEq("nat"),
1483 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001484 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001485 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001486 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001487 datapath.RemoveSNATMarkRules();
1488}
1489
Garrick Evans2f581a02020-05-11 10:43:35 +09001490TEST(DatapathTest, ArcVethHostName) {
1491 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
1492 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
1493 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
1494 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
1495 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
1496 EXPECT_EQ("vethexceeds_ify", ifname);
1497 EXPECT_LT(ifname.length(), IFNAMSIZ);
1498}
1499
Garrick Evans8a067562020-05-11 12:47:30 +09001500TEST(DatapathTest, ArcBridgeName) {
1501 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
1502 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
1503 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
1504 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
1505 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
1506 EXPECT_EQ("arc_exceeds_ify", ifname);
1507 EXPECT_LT(ifname.length(), IFNAMSIZ);
1508}
1509
Garrick Evans3388a032020-03-24 11:25:55 +09001510} // namespace patchpanel