blob: 0238e33ecb72fa8ccd22c3f8b8076992b3279a76 [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
775 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
776 datapath.StartRoutingNamespace(
777 kTestPID, "netns_foo", "arc_ns0", "veth0", Ipv4Addr(100, 115, 92, 128),
778 30, Ipv4Addr(100, 115, 92, 129), Ipv4Addr(100, 115, 92, 130), mac);
779 ioctl_reqs.clear();
780 ioctl_rtentry_args.clear();
781}
782
783TEST(DatapathTest, StopRoutingNamespace) {
784 MockProcessRunner runner;
785 MockFirewall firewall;
786
787 EXPECT_CALL(runner, iptables(StrEq("filter"),
788 ElementsAre("-D", "FORWARD", "-o", "arc_ns0",
789 "-j", "ACCEPT", "-w"),
790 true, nullptr));
791 EXPECT_CALL(runner,
792 iptables(StrEq("mangle"),
793 ElementsAre("-D", "PREROUTING", "-i", "arc_ns0", "-j",
794 "MARK", "--set-mark", "1/1", "-w"),
795 true, nullptr));
796 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
797 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("delete"), ElementsAre("arc_ns0"),
798 false));
799
800 Datapath datapath(&runner, &firewall);
801 datapath.StopRoutingNamespace("netns_foo", "arc_ns0",
802 Ipv4Addr(100, 115, 92, 128), 30,
803 Ipv4Addr(100, 115, 92, 129));
804}
805
Hugo Benichi8d622b52020-08-13 15:24:12 +0900806TEST(DatapathTest, StartRoutingDevice_Arc) {
807 MockProcessRunner runner;
808 MockFirewall firewall;
809 EXPECT_CALL(runner, iptables(StrEq("nat"),
810 ElementsAre("-A", "PREROUTING", "-i", "eth0",
811 "-m", "socket", "--nowildcard", "-j",
812 "ACCEPT", "-w"),
813 true, nullptr));
814 EXPECT_CALL(runner, iptables(StrEq("nat"),
815 ElementsAre("-A", "PREROUTING", "-i", "eth0",
816 "-p", "tcp", "-j", "DNAT",
817 "--to-destination", "1.2.3.4", "-w"),
818 true, nullptr));
819 EXPECT_CALL(runner, iptables(StrEq("nat"),
820 ElementsAre("-A", "PREROUTING", "-i", "eth0",
821 "-p", "udp", "-j", "DNAT",
822 "--to-destination", "1.2.3.4", "-w"),
823 true, nullptr));
824 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900825 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
826 "arc_eth0", "-j", "ACCEPT", "-w"),
827 true, nullptr));
828 EXPECT_CALL(runner, iptables(StrEq("filter"),
829 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
830 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900831 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900832 EXPECT_CALL(runner, iptables(StrEq("mangle"),
833 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
834 "-j", "MARK", "--set-mark",
835 "0x00002000/0x00003f00", "-w"),
836 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900837 EXPECT_CALL(runner, iptables(StrEq("mangle"),
838 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
839 "-j", "MARK", "--set-mark",
840 "0x03ea0000/0xffff0000", "-w"),
841 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900842 EXPECT_CALL(
843 runner,
844 ip6tables(StrEq("mangle"),
845 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
846 "--set-mark", "0x00002000/0x00003f00", "-w"),
847 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900848 EXPECT_CALL(
849 runner,
850 ip6tables(StrEq("mangle"),
851 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
852 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
853 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900854
855 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900856 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900857 datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
858 TrafficSource::ARC);
859}
860
861TEST(DatapathTest, StartRoutingDevice_CrosVM) {
862 MockProcessRunner runner;
863 MockFirewall firewall;
864 EXPECT_CALL(runner, iptables(StrEq("filter"),
865 ElementsAre("-A", "FORWARD", "-o", "vmtap0",
866 "-j", "ACCEPT", "-w"),
867 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900868 EXPECT_CALL(runner, iptables(StrEq("filter"),
869 ElementsAre("-A", "FORWARD", "-i", "vmtap0",
870 "-j", "ACCEPT", "-w"),
871 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900872 EXPECT_CALL(runner, iptables(StrEq("mangle"),
873 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
874 "-j", "MARK", "--set-mark",
875 "0x00002100/0x00003f00", "-w"),
876 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900877 EXPECT_CALL(runner, iptables(StrEq("mangle"),
878 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
879 "-j", "CONNMARK", "--restore-mark",
880 "--mask", "0xffff0000", "-w"),
881 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900882 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
883 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
884 "-j", "MARK", "--set-mark",
885 "0x00002100/0x00003f00", "-w"),
886 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900887 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
888 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
889 "-j", "CONNMARK", "--restore-mark",
890 "--mask", "0xffff0000", "-w"),
891 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900892 EXPECT_CALL(runner, iptables(StrEq("mangle"),
893 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
894 "-j", "apply_vpn_mark", "-w"),
895 true, nullptr));
896 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
897 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
898 "-j", "apply_vpn_mark", "-w"),
899 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900900
901 Datapath datapath(&runner, &firewall);
902 datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
903 TrafficSource::CROSVM);
904}
905
906TEST(DatapathTest, StopRoutingDevice_Arc) {
907 MockProcessRunner runner;
908 MockFirewall firewall;
909 EXPECT_CALL(runner, iptables(StrEq("nat"),
910 ElementsAre("-D", "PREROUTING", "-i", "eth0",
911 "-m", "socket", "--nowildcard", "-j",
912 "ACCEPT", "-w"),
913 true, nullptr));
914 EXPECT_CALL(runner, iptables(StrEq("nat"),
915 ElementsAre("-D", "PREROUTING", "-i", "eth0",
916 "-p", "tcp", "-j", "DNAT",
917 "--to-destination", "1.2.3.4", "-w"),
918 true, nullptr));
919 EXPECT_CALL(runner, iptables(StrEq("nat"),
920 ElementsAre("-D", "PREROUTING", "-i", "eth0",
921 "-p", "udp", "-j", "DNAT",
922 "--to-destination", "1.2.3.4", "-w"),
923 true, nullptr));
924 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900925 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
926 "arc_eth0", "-j", "ACCEPT", "-w"),
927 true, nullptr));
928 EXPECT_CALL(runner, iptables(StrEq("filter"),
929 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
930 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900931 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900932 EXPECT_CALL(runner, iptables(StrEq("mangle"),
933 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
934 "-j", "MARK", "--set-mark",
935 "0x00002000/0x00003f00", "-w"),
936 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900937 EXPECT_CALL(runner, iptables(StrEq("mangle"),
938 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
939 "-j", "MARK", "--set-mark",
940 "0x03ea0000/0xffff0000", "-w"),
941 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900942 EXPECT_CALL(
943 runner,
944 ip6tables(StrEq("mangle"),
945 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
946 "--set-mark", "0x00002000/0x00003f00", "-w"),
947 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900948 EXPECT_CALL(
949 runner,
950 ip6tables(StrEq("mangle"),
951 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
952 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
953 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900954
955 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900956 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900957 datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
958 TrafficSource::ARC);
959}
960
961TEST(DatapathTest, StopRoutingDevice_CrosVM) {
962 MockProcessRunner runner;
963 MockFirewall firewall;
964 EXPECT_CALL(runner, iptables(StrEq("filter"),
965 ElementsAre("-D", "FORWARD", "-o", "vmtap0",
966 "-j", "ACCEPT", "-w"),
967 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900968 EXPECT_CALL(runner, iptables(StrEq("filter"),
969 ElementsAre("-D", "FORWARD", "-i", "vmtap0",
970 "-j", "ACCEPT", "-w"),
971 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900972 EXPECT_CALL(runner, iptables(StrEq("mangle"),
973 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
974 "-j", "MARK", "--set-mark",
975 "0x00002100/0x00003f00", "-w"),
976 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900977 EXPECT_CALL(runner, iptables(StrEq("mangle"),
978 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
979 "-j", "CONNMARK", "--restore-mark",
980 "--mask", "0xffff0000", "-w"),
981 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900982 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
983 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
984 "-j", "MARK", "--set-mark",
985 "0x00002100/0x00003f00", "-w"),
986 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900987 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
988 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
989 "-j", "CONNMARK", "--restore-mark",
990 "--mask", "0xffff0000", "-w"),
991 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900992 EXPECT_CALL(runner, iptables(StrEq("mangle"),
993 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
994 "-j", "apply_vpn_mark", "-w"),
995 true, nullptr));
996 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
997 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
998 "-j", "apply_vpn_mark", "-w"),
999 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +09001000
1001 Datapath datapath(&runner, &firewall);
1002 datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
1003 TrafficSource::CROSVM);
1004}
1005
Hugo Benichid82d8832020-08-14 10:05:03 +09001006TEST(DatapathTest, StartStopIpForwarding) {
1007 struct {
1008 IpFamily family;
1009 std::string iif;
1010 std::string oif;
1011 std::vector<std::string> start_args;
1012 std::vector<std::string> stop_args;
1013 bool result;
1014 } testcases[] = {
1015 {IpFamily::IPv4, "", "", {}, {}, false},
1016 {IpFamily::NONE, "foo", "bar", {}, {}, false},
1017 {IpFamily::IPv4,
1018 "foo",
1019 "bar",
1020 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1021 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1022 true},
1023 {IpFamily::IPv4,
1024 "",
1025 "bar",
1026 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1027 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1028 true},
1029 {IpFamily::IPv4,
1030 "foo",
1031 "",
1032 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1033 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1034 true},
1035 {IpFamily::IPv6,
1036 "foo",
1037 "bar",
1038 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1039 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1040 true},
1041 {IpFamily::IPv6,
1042 "",
1043 "bar",
1044 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1045 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1046 true},
1047 {IpFamily::IPv6,
1048 "foo",
1049 "",
1050 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1051 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1052 true},
1053 {IpFamily::Dual,
1054 "foo",
1055 "bar",
1056 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1057 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1058 true},
1059 {IpFamily::Dual,
1060 "",
1061 "bar",
1062 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1063 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1064 true},
1065 {IpFamily::Dual,
1066 "foo",
1067 "",
1068 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1069 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1070 true},
1071 };
1072
1073 for (const auto& tt : testcases) {
1074 MockProcessRunner runner;
1075 MockFirewall firewall;
1076 if (tt.result) {
1077 if (tt.family & IpFamily::IPv4) {
1078 EXPECT_CALL(runner,
1079 iptables(StrEq("filter"), tt.start_args, true, nullptr))
1080 .WillOnce(Return(0));
1081 EXPECT_CALL(runner,
1082 iptables(StrEq("filter"), tt.stop_args, true, nullptr))
1083 .WillOnce(Return(0));
1084 }
1085 if (tt.family & IpFamily::IPv6) {
1086 EXPECT_CALL(runner,
1087 ip6tables(StrEq("filter"), tt.start_args, true, nullptr))
1088 .WillOnce(Return(0));
1089 EXPECT_CALL(runner,
1090 ip6tables(StrEq("filter"), tt.stop_args, true, nullptr))
1091 .WillOnce(Return(0));
1092 }
1093 }
1094 Datapath datapath(&runner, &firewall);
1095
1096 EXPECT_EQ(tt.result, datapath.StartIpForwarding(tt.family, tt.iif, tt.oif));
1097 EXPECT_EQ(tt.result, datapath.StopIpForwarding(tt.family, tt.iif, tt.oif));
1098 }
1099}
1100
Hugo Benichi76be34a2020-08-26 22:35:54 +09001101TEST(DatapathTest, StartStopConnectionPinning) {
1102 MockProcessRunner runner;
1103 MockFirewall firewall;
Hugo Benichi1af52392020-11-27 18:09:32 +09001104
1105 // Setup
Hugo Benichi76be34a2020-08-26 22:35:54 +09001106 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1107 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1108 "-j", "CONNMARK", "--set-mark",
1109 "0x03eb0000/0xffff0000", "-w"),
1110 true, nullptr));
Hugo Benichi76be34a2020-08-26 22:35:54 +09001111 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1112 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1113 "-j", "CONNMARK", "--set-mark",
1114 "0x03eb0000/0xffff0000", "-w"),
1115 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001116 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1117 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1118 "-j", "CONNMARK", "--save-mark",
1119 "--mask", "0x00003f00", "-w"),
1120 true, nullptr));
1121 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1122 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1123 "-j", "CONNMARK", "--save-mark",
1124 "--mask", "0x00003f00", "-w"),
1125 true, nullptr));
1126 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1127 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1128 "-j", "CONNMARK", "--restore-mark",
1129 "--mask", "0x00003f00", "-w"),
1130 true, nullptr));
1131 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1132 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1133 "-j", "CONNMARK", "--restore-mark",
1134 "--mask", "0x00003f00", "-w"),
1135 true, nullptr));
1136 // Teardown
1137 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1138 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1139 "-j", "CONNMARK", "--set-mark",
1140 "0x03eb0000/0xffff0000", "-w"),
1141 true, nullptr));
Hugo Benichi76be34a2020-08-26 22:35:54 +09001142 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1143 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1144 "-j", "CONNMARK", "--set-mark",
1145 "0x03eb0000/0xffff0000", "-w"),
1146 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001147 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1148 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1149 "-j", "CONNMARK", "--save-mark",
1150 "--mask", "0x00003f00", "-w"),
1151 true, nullptr));
1152 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1153 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1154 "-j", "CONNMARK", "--save-mark",
1155 "--mask", "0x00003f00", "-w"),
1156 true, nullptr));
1157 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1158 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1159 "-j", "CONNMARK", "--restore-mark",
1160 "--mask", "0x00003f00", "-w"),
1161 true, nullptr));
1162 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1163 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1164 "-j", "CONNMARK", "--restore-mark",
1165 "--mask", "0x00003f00", "-w"),
1166 true, nullptr));
1167
Hugo Benichi76be34a2020-08-26 22:35:54 +09001168 Datapath datapath(&runner, &firewall);
1169 datapath.SetIfnameIndex("eth0", 3);
1170 datapath.StartConnectionPinning("eth0");
1171 datapath.StopConnectionPinning("eth0");
1172}
1173
Hugo Benichi2a940542020-10-26 18:50:49 +09001174TEST(DatapathTest, StartStopVpnRouting_NoVirtualDevices) {
1175 MockProcessRunner runner;
1176 MockFirewall firewall;
1177
1178 // Setup
1179 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1180 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1181 "-j", "CONNMARK", "--set-mark",
1182 "0x03ed0000/0xffff0000", "-w"),
1183 true, nullptr));
1184 EXPECT_CALL(runner,
1185 iptables(StrEq("mangle"),
1186 ElementsAre("-A", "apply_vpn_mark", "-j", "MARK",
1187 "--set-mark", "0x03ed0000/0xffff0000", "-w"),
1188 true, nullptr));
1189 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1190 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1191 "-j", "CONNMARK", "--set-mark",
1192 "0x03ed0000/0xffff0000", "-w"),
1193 true, nullptr));
1194 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1195 ElementsAre("-A", "apply_vpn_mark", "-j",
1196 "MARK", "--set-mark",
1197 "0x03ed0000/0xffff0000", "-w"),
1198 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001199 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1200 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1201 "-j", "CONNMARK", "--save-mark",
1202 "--mask", "0x00003f00", "-w"),
1203 true, nullptr));
1204 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1205 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1206 "-j", "CONNMARK", "--save-mark",
1207 "--mask", "0x00003f00", "-w"),
1208 true, nullptr));
1209 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1210 ElementsAre("-A", "PREROUTING", "-i", "arcbr0",
1211 "-j", "CONNMARK", "--restore-mark",
1212 "--mask", "0x00003f00", "-w"),
1213 true, nullptr));
1214 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1215 ElementsAre("-A", "PREROUTING", "-i", "arcbr0",
1216 "-j", "CONNMARK", "--restore-mark",
1217 "--mask", "0x00003f00", "-w"),
1218 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +09001219 // Teardown
1220 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1221 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1222 "-j", "CONNMARK", "--set-mark",
1223 "0x03ed0000/0xffff0000", "-w"),
1224 true, nullptr));
1225 EXPECT_CALL(runner,
1226 iptables(StrEq("mangle"),
1227 ElementsAre("-D", "apply_vpn_mark", "-j", "MARK",
1228 "--set-mark", "0x03ed0000/0xffff0000", "-w"),
1229 true, nullptr));
1230 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1231 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1232 "-j", "CONNMARK", "--set-mark",
1233 "0x03ed0000/0xffff0000", "-w"),
1234 true, nullptr));
1235 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1236 ElementsAre("-D", "apply_vpn_mark", "-j",
1237 "MARK", "--set-mark",
1238 "0x03ed0000/0xffff0000", "-w"),
1239 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001240 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1241 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1242 "-j", "CONNMARK", "--save-mark",
1243 "--mask", "0x00003f00", "-w"),
1244 true, nullptr));
1245 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1246 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1247 "-j", "CONNMARK", "--save-mark",
1248 "--mask", "0x00003f00", "-w"),
1249 true, nullptr));
1250 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1251 ElementsAre("-D", "PREROUTING", "-i", "arcbr0",
1252 "-j", "CONNMARK", "--restore-mark",
1253 "--mask", "0x00003f00", "-w"),
1254 true, nullptr));
1255 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1256 ElementsAre("-D", "PREROUTING", "-i", "arcbr0",
1257 "-j", "CONNMARK", "--restore-mark",
1258 "--mask", "0x00003f00", "-w"),
1259 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +09001260
1261 Datapath datapath(&runner, &firewall);
1262 datapath.SetIfnameIndex("arcbr0", 5);
1263 datapath.StartVpnRouting("arcbr0");
1264 datapath.StopVpnRouting("arcbr0");
1265}
1266
Garrick Evansf0ab7132019-06-18 14:50:42 +09001267TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001268 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001269 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001270 EXPECT_CALL(runner, iptables(StrEq("nat"),
1271 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1272 "-m", "socket", "--nowildcard", "-j",
1273 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001274 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001275 EXPECT_CALL(runner, iptables(StrEq("nat"),
1276 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1277 "-p", "tcp", "-j", "DNAT",
1278 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001279 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001280 EXPECT_CALL(runner, iptables(StrEq("nat"),
1281 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1282 "-p", "udp", "-j", "DNAT",
1283 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001284 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001285 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001286 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001287}
1288
1289TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001290 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001291 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001292 EXPECT_CALL(runner, iptables(StrEq("nat"),
1293 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1294 "-m", "socket", "--nowildcard", "-j",
1295 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001296 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001297 EXPECT_CALL(runner, iptables(StrEq("nat"),
1298 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1299 "-p", "tcp", "-j", "DNAT",
1300 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001301 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001302 EXPECT_CALL(runner, iptables(StrEq("nat"),
1303 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1304 "-p", "udp", "-j", "DNAT",
1305 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001306 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001307 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001308 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001309}
1310
Garrick Evans664a82f2019-12-17 12:18:05 +09001311TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001312 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001313 MockFirewall firewall;
1314 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Hugo Benichi7c342672020-09-08 09:18:14 +09001315
Garrick Evans664a82f2019-12-17 12:18:05 +09001316 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +09001317 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +09001318 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +09001319 EXPECT_EQ(ioctl_reqs, expected);
1320 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +09001321 ioctl_rtentry_args.clear();
Taoyu Li90c13912019-11-26 17:56:54 +09001322}
1323
1324TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001325 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001326 MockFirewall firewall;
Taoyu Lica49c832019-12-06 17:56:43 +09001327 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +09001328 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1329 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1330 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001331 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001332 .WillOnce(Return(1));
1333 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1334 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
1335 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001336 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001337 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1338 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1339 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001340 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001341 .WillOnce(Return(1));
1342 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1343 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
1344 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001345 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001346 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001347 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001348}
1349
Taoyu Lica49c832019-12-06 17:56:43 +09001350TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001351 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001352 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001353 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1354 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1355 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001356 false, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001357 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1358 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1359 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001360 false, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001361 Datapath datapath(&runner, &firewall);
Taoyu Lica49c832019-12-06 17:56:43 +09001362 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +09001363}
1364
Taoyu Li90c13912019-11-26 17:56:54 +09001365TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001366 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001367 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001368 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1369 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
1370 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001371 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001372 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1373 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
1374 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001375 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001376 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001377 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001378}
1379
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001380TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001381 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001382 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001383 EXPECT_CALL(runner,
1384 ip6(StrEq("route"), StrEq("replace"),
1385 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001386 Datapath datapath(&runner, &firewall);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001387 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001388}
1389
Hugo Benichie8758b52020-04-03 14:49:01 +09001390TEST(DatapathTest, AddIPv4Route) {
1391 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001392 MockFirewall firewall;
1393 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichie8758b52020-04-03 14:49:01 +09001394
1395 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1396 Ipv4Addr(255, 255, 255, 0));
1397 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1398 Ipv4Addr(255, 255, 255, 0));
1399 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1400 Ipv4Addr(255, 255, 255, 252));
1401 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1402 Ipv4Addr(255, 255, 255, 252));
1403
1404 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
1405 SIOCDELRT};
1406 EXPECT_EQ(expected_reqs, ioctl_reqs);
Hugo Benichie8758b52020-04-03 14:49:01 +09001407
1408 std::string route1 =
1409 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
1410 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
1411 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
1412 "RTF_GATEWAY}";
1413 std::string route2 =
1414 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
1415 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
1416 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
1417 std::vector<std::string> captured_routes;
1418 for (const auto& route : ioctl_rtentry_args) {
1419 std::ostringstream stream;
1420 stream << route.second;
1421 captured_routes.emplace_back(stream.str());
1422 }
Hugo Benichie8758b52020-04-03 14:49:01 +09001423 EXPECT_EQ(route1, captured_routes[0]);
1424 EXPECT_EQ(route1, captured_routes[1]);
1425 EXPECT_EQ(route2, captured_routes[2]);
1426 EXPECT_EQ(route2, captured_routes[3]);
Hugo Benichi7c342672020-09-08 09:18:14 +09001427 ioctl_reqs.clear();
1428 ioctl_rtentry_args.clear();
Hugo Benichie8758b52020-04-03 14:49:01 +09001429}
1430
Garrick Evansd291af62020-05-25 10:39:06 +09001431TEST(DatapathTest, AddSNATMarkRules) {
1432 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001433 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001434 EXPECT_CALL(
1435 runner,
1436 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001437 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001438 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001439 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001440 EXPECT_CALL(runner,
1441 iptables(StrEq("filter"),
1442 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
1443 "1/1", "-j", "ACCEPT", "-w"),
1444 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001445 EXPECT_CALL(runner,
1446 iptables(StrEq("nat"),
1447 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001448 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001449 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001450 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001451 datapath.AddSNATMarkRules();
1452}
1453
1454TEST(DatapathTest, RemoveSNATMarkRules) {
1455 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001456 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001457 EXPECT_CALL(
1458 runner,
1459 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001460 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001461 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001462 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001463 EXPECT_CALL(runner,
1464 iptables(StrEq("filter"),
1465 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
1466 "1/1", "-j", "ACCEPT", "-w"),
1467 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001468 EXPECT_CALL(runner,
1469 iptables(StrEq("nat"),
1470 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001471 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001472 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001473 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001474 datapath.RemoveSNATMarkRules();
1475}
1476
Garrick Evans2f581a02020-05-11 10:43:35 +09001477TEST(DatapathTest, ArcVethHostName) {
1478 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
1479 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
1480 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
1481 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
1482 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
1483 EXPECT_EQ("vethexceeds_ify", ifname);
1484 EXPECT_LT(ifname.length(), IFNAMSIZ);
1485}
1486
Garrick Evans8a067562020-05-11 12:47:30 +09001487TEST(DatapathTest, ArcBridgeName) {
1488 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
1489 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
1490 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
1491 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
1492 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
1493 EXPECT_EQ("arc_exceeds_ify", ifname);
1494 EXPECT_LT(ifname.length(), IFNAMSIZ);
1495}
1496
Garrick Evans3388a032020-03-24 11:25:55 +09001497} // namespace patchpanel