blob: 889845d6c42c71c40c4d0355e1d2430288843cf5 [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"),
267 ElementsAre("-A", "apply_local_source_mark", "-m", "mark",
268 "--mark", "0x0/0x00003f00", "-j", "MARK",
269 "--set-mark", "0x00000400/0x00003f00", "-w"),
270 true, nullptr));
271 EXPECT_CALL(runner,
272 ip6tables(StrEq("mangle"),
273 ElementsAre("-N", "apply_local_source_mark", "-w"),
274 true, nullptr));
275 EXPECT_CALL(runner,
276 ip6tables(StrEq("mangle"),
277 ElementsAre("-F", "apply_local_source_mark", "-w"),
278 true, nullptr));
279 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
280 ElementsAre("-A", "OUTPUT", "-j",
281 "apply_local_source_mark", "-w"),
282 true, nullptr));
283 EXPECT_CALL(
284 runner,
285 ip6tables(StrEq("mangle"),
286 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
287 "--uid-owner", "debugd", "-j", "MARK", "--set-mark",
288 "0x00008200/0x0000ff00", "-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", "chronos", "-j", "MARK",
295 "--set-mark", "0x00008100/0x0000ff00", "-w"),
296 true, nullptr));
297 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
298 ElementsAre("-A", "apply_local_source_mark",
299 "-m", "owner", "--uid-owner",
300 "cups", "-j", "MARK", "--set-mark",
301 "0x00008200/0x0000ff00", "-w"),
302 true, nullptr));
303 EXPECT_CALL(
304 runner,
305 ip6tables(StrEq("mangle"),
306 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
307 "--uid-owner", "kerberosd", "-j", "MARK",
308 "--set-mark", "0x00008400/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-exec", "-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", "tlsdate", "-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", "pluginvm", "-j", "MARK",
329 "--set-mark", "0x00008200/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", "fuse-smbfs", "-j", "MARK",
336 "--set-mark", "0x00008400/0x0000ff00", "-w"),
337 true, nullptr));
338 EXPECT_CALL(
339 runner,
340 ip6tables(StrEq("mangle"),
341 ElementsAre("-A", "apply_local_source_mark", "-m", "mark",
342 "--mark", "0x0/0x00003f00", "-j", "MARK",
343 "--set-mark", "0x00000400/0x00003f00", "-w"),
344 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900345 // Asserts for apply_vpn_mark chain
346 EXPECT_CALL(runner, iptables(StrEq("mangle"),
347 ElementsAre("-N", "apply_vpn_mark", "-w"), true,
348 nullptr));
349 EXPECT_CALL(runner, iptables(StrEq("mangle"),
350 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
351 nullptr));
352 EXPECT_CALL(runner, iptables(StrEq("mangle"),
353 ElementsAre("-A", "OUTPUT", "-m", "mark",
354 "--mark", "0x00008000/0x0000c000",
355 "-j", "apply_vpn_mark", "-w"),
356 true, nullptr));
357 EXPECT_CALL(runner, iptables(StrEq("mangle"),
358 ElementsAre("-A", "apply_vpn_mark", "-m", "mark",
359 "!", "--mark", "0x0/0xffff0000",
360 "-j", "ACCEPT", "-w"),
361 true, nullptr));
362 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
363 ElementsAre("-N", "apply_vpn_mark", "-w"), true,
364 nullptr));
365 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
366 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
367 nullptr));
368 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
369 ElementsAre("-A", "OUTPUT", "-m", "mark",
370 "--mark", "0x00008000/0x0000c000",
371 "-j", "apply_vpn_mark", "-w"),
372 true, nullptr));
373 EXPECT_CALL(
374 runner,
375 ip6tables(StrEq("mangle"),
376 ElementsAre("-A", "apply_vpn_mark", "-m", "mark", "!", "--mark",
377 "0x0/0xffff0000", "-j", "ACCEPT", "-w"),
378 true, nullptr));
Hugo Benichibf811c62020-09-07 17:30:45 +0900379
380 Datapath datapath(&runner, &firewall);
381 datapath.Start();
382}
383
384TEST(DatapathTest, Stop) {
385 MockProcessRunner runner;
386 MockFirewall firewall;
387 // Asserts for sysctl modifications
388 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_local_port_range"),
389 StrEq("32768 61000"), true));
390 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv6.conf.all.forwarding"),
391 StrEq("0"), true));
392 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_forward"), StrEq("0"), true));
393 // Asserts for RemoveOutboundIPv4SNATMark("vmtap+")
394 EXPECT_CALL(runner,
395 iptables(StrEq("mangle"),
396 ElementsAre("-D", "PREROUTING", "-i", "vmtap+", "-j",
397 "MARK", "--set-mark", "1/1", "-w"),
398 true, nullptr));
399 // Asserts for RemoveForwardEstablishedRule
400 EXPECT_CALL(runner,
401 iptables(StrEq("filter"),
402 ElementsAre("-D", "FORWARD", "-m", "state", "--state",
403 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
404 true, nullptr));
405 // Asserts for RemoveSNATMarkRules
406 EXPECT_CALL(
407 runner,
408 iptables(StrEq("filter"),
409 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
410 "state", "--state", "INVALID", "-j", "DROP", "-w"),
411 true, nullptr));
412 EXPECT_CALL(runner,
413 iptables(StrEq("filter"),
414 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
415 "1/1", "-j", "ACCEPT", "-w"),
416 true, nullptr));
417 EXPECT_CALL(runner,
418 iptables(StrEq("nat"),
419 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
420 "1/1", "-j", "MASQUERADE", "-w"),
421 true, nullptr));
422 // Asserts for RemoveSourceIPv4DropRule() calls.
423 EXPECT_CALL(runner,
424 iptables(StrEq("filter"),
425 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
426 "100.115.92.0/23", "-j", "DROP", "-w"),
427 true, nullptr));
428 EXPECT_CALL(runner,
429 iptables(StrEq("filter"),
430 ElementsAre("-D", "OUTPUT", "-o", "wlan+", "-s",
431 "100.115.92.0/23", "-j", "DROP", "-w"),
432 true, nullptr));
433 EXPECT_CALL(runner,
434 iptables(StrEq("filter"),
435 ElementsAre("-D", "OUTPUT", "-o", "mlan+", "-s",
436 "100.115.92.0/23", "-j", "DROP", "-w"),
437 true, nullptr));
438 EXPECT_CALL(runner,
439 iptables(StrEq("filter"),
440 ElementsAre("-D", "OUTPUT", "-o", "usb+", "-s",
441 "100.115.92.0/23", "-j", "DROP", "-w"),
442 true, nullptr));
443 EXPECT_CALL(runner,
444 iptables(StrEq("filter"),
445 ElementsAre("-D", "OUTPUT", "-o", "wwan+", "-s",
446 "100.115.92.0/23", "-j", "DROP", "-w"),
447 true, nullptr));
448 EXPECT_CALL(runner,
449 iptables(StrEq("filter"),
450 ElementsAre("-D", "OUTPUT", "-o", "rmnet+", "-s",
451 "100.115.92.0/23", "-j", "DROP", "-w"),
452 true, nullptr));
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900453 // Asserts for apply_local_source_mark chain
454 EXPECT_CALL(runner, iptables(StrEq("mangle"),
455 ElementsAre("-D", "OUTPUT", "-j",
456 "apply_local_source_mark", "-w"),
457 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +0900458 // Asserts for OUTPUT CONNMARK restore rule
459 EXPECT_CALL(runner, iptables(StrEq("mangle"),
460 ElementsAre("-D", "OUTPUT", "-j", "CONNMARK",
461 "--restore-mark", "--mask",
462 "0xffff0000", "-w"),
463 true, nullptr));
464 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
465 ElementsAre("-D", "OUTPUT", "-j", "CONNMARK",
466 "--restore-mark", "--mask",
467 "0xffff0000", "-w"),
468 true, nullptr));
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900469 EXPECT_CALL(runner,
470 iptables(StrEq("mangle"),
471 ElementsAre("-F", "apply_local_source_mark", "-w"), true,
472 nullptr));
473 EXPECT_CALL(runner,
474 iptables(StrEq("mangle"),
475 ElementsAre("-X", "apply_local_source_mark", "-w"), true,
476 nullptr));
477 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
478 ElementsAre("-D", "OUTPUT", "-j",
479 "apply_local_source_mark", "-w"),
480 true, nullptr));
481 EXPECT_CALL(runner,
482 ip6tables(StrEq("mangle"),
483 ElementsAre("-F", "apply_local_source_mark", "-w"),
484 true, nullptr));
485 EXPECT_CALL(runner,
486 ip6tables(StrEq("mangle"),
487 ElementsAre("-X", "apply_local_source_mark", "-w"),
488 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900489 // Asserts for apply_vpn_mark chain
490 EXPECT_CALL(runner, iptables(StrEq("mangle"),
491 ElementsAre("-D", "OUTPUT", "-m", "mark",
492 "--mark", "0x00008000/0x0000c000",
493 "-j", "apply_vpn_mark", "-w"),
494 true, nullptr));
495 EXPECT_CALL(runner, iptables(StrEq("mangle"),
496 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
497 nullptr));
498 EXPECT_CALL(runner, iptables(StrEq("mangle"),
499 ElementsAre("-X", "apply_vpn_mark", "-w"), true,
500 nullptr));
501 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
502 ElementsAre("-D", "OUTPUT", "-m", "mark",
503 "--mark", "0x00008000/0x0000c000",
504 "-j", "apply_vpn_mark", "-w"),
505 true, nullptr));
506 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
507 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
508 nullptr));
509 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
510 ElementsAre("-X", "apply_vpn_mark", "-w"), true,
511 nullptr));
Hugo Benichibf811c62020-09-07 17:30:45 +0900512
513 Datapath datapath(&runner, &firewall);
514 datapath.Stop();
515}
516
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900517TEST(DatapathTest, AddTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900518 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900519 MockFirewall firewall;
520 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900521 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900522 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900523 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900524 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900525 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900526 std::vector<ioctl_req_t> expected = {
527 TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, SIOCSIFNETMASK,
528 SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900529 EXPECT_EQ(ioctl_reqs, expected);
530 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900531 ioctl_rtentry_args.clear();
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900532}
533
534TEST(DatapathTest, AddTAPWithOwner) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900535 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900536 MockFirewall firewall;
537 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900538 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900539 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900540 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900541 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900542 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900543 std::vector<ioctl_req_t> expected = {
544 TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, SIOCSIFADDR,
545 SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900546 EXPECT_EQ(ioctl_reqs, expected);
547 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900548 ioctl_rtentry_args.clear();
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900549}
550
Garrick Evans621ed262019-11-13 12:28:43 +0900551TEST(DatapathTest, AddTAPNoAddrs) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900552 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900553 MockFirewall firewall;
554 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900555 auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, "");
Garrick Evans621ed262019-11-13 12:28:43 +0900556 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900557 std::vector<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS,
558 SIOCSIFFLAGS};
Garrick Evans621ed262019-11-13 12:28:43 +0900559 EXPECT_EQ(ioctl_reqs, expected);
560 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900561 ioctl_rtentry_args.clear();
Garrick Evans621ed262019-11-13 12:28:43 +0900562}
563
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900564TEST(DatapathTest, RemoveTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900565 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900566 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900567 EXPECT_CALL(runner, ip(StrEq("tuntap"), StrEq("del"),
568 ElementsAre("foo0", "mode", "tap"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900569 Datapath datapath(&runner, &firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900570 datapath.RemoveTAP("foo0");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900571}
Garrick Evansf0ab7132019-06-18 14:50:42 +0900572
Hugo Benichi33860d72020-07-09 16:34:01 +0900573TEST(DatapathTest, NetnsAttachName) {
574 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900575 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900576 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
577 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), 1234, true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900578 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900579 EXPECT_TRUE(datapath.NetnsAttachName("netns_foo", 1234));
580}
581
582TEST(DatapathTest, NetnsDeleteName) {
583 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900584 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900585 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900586 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900587 EXPECT_TRUE(datapath.NetnsDeleteName("netns_foo"));
588}
589
Garrick Evans8a949dc2019-07-18 16:17:53 +0900590TEST(DatapathTest, AddBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900591 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900592 MockFirewall firewall;
593 Datapath datapath(&runner, &firewall);
Garrick Evans8e8e3472020-01-23 14:03:50 +0900594 EXPECT_CALL(runner, brctl(StrEq("addbr"), ElementsAre("br"), true));
Garrick Evans6f4fa3a2020-02-10 16:15:09 +0900595 EXPECT_CALL(
596 runner,
597 ip(StrEq("addr"), StrEq("add"),
598 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "br"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900599 EXPECT_CALL(runner,
600 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "up"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900601 EXPECT_CALL(runner, iptables(StrEq("mangle"),
602 ElementsAre("-A", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900603 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900604 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900605 datapath.AddBridge("br", Ipv4Addr(1, 1, 1, 1), 30);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900606}
607
Hugo Benichi76675592020-04-08 14:29:57 +0900608TEST(DatapathTest, ConnectVethPair) {
609 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900610 MockFirewall firewall;
Hugo Benichi76675592020-04-08 14:29:57 +0900611 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
612 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900613 "peer_foo", "netns", "netns_foo"),
Hugo Benichi76675592020-04-08 14:29:57 +0900614 true));
615 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
616 ElementsAre("100.115.92.169/30", "brd",
617 "100.115.92.171", "dev", "peer_foo"),
618 true))
619 .WillOnce(Return(0));
620 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
621 ElementsAre("dev", "peer_foo", "up", "addr",
622 "01:02:03:04:05:06", "multicast", "on"),
623 true))
624 .WillOnce(Return(0));
Hugo Benichi76675592020-04-08 14:29:57 +0900625 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
626 ElementsAre("veth_foo", "up"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900627 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900628 EXPECT_TRUE(datapath.ConnectVethPair(kTestPID, "netns_foo", "veth_foo",
629 "peer_foo", {1, 2, 3, 4, 5, 6},
Hugo Benichi76675592020-04-08 14:29:57 +0900630 Ipv4Addr(100, 115, 92, 169), 30, true));
631}
632
Garrick Evans2470caa2020-03-04 14:15:41 +0900633TEST(DatapathTest, AddVirtualInterfacePair) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900634 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900635 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900636 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
637 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900638 "peer_foo", "netns", "netns_foo"),
Garrick Evans8e8e3472020-01-23 14:03:50 +0900639 true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900640 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900641 EXPECT_TRUE(
642 datapath.AddVirtualInterfacePair("netns_foo", "veth_foo", "peer_foo"));
Garrick Evans2470caa2020-03-04 14:15:41 +0900643}
644
645TEST(DatapathTest, ToggleInterface) {
646 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900647 MockFirewall firewall;
Garrick Evans2470caa2020-03-04 14:15:41 +0900648 EXPECT_CALL(runner,
649 ip(StrEq("link"), StrEq("set"), ElementsAre("foo", "up"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900650 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
Garrick Evans2470caa2020-03-04 14:15:41 +0900651 ElementsAre("bar", "down"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900652 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900653 EXPECT_TRUE(datapath.ToggleInterface("foo", true));
654 EXPECT_TRUE(datapath.ToggleInterface("bar", false));
655}
656
657TEST(DatapathTest, ConfigureInterface) {
658 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900659 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900660 EXPECT_CALL(
661 runner,
Garrick Evans2470caa2020-03-04 14:15:41 +0900662 ip(StrEq("addr"), StrEq("add"),
663 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "foo"), true))
664 .WillOnce(Return(0));
665 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
666 ElementsAre("dev", "foo", "up", "addr",
667 "02:02:02:02:02:02", "multicast", "on"),
668 true))
669 .WillOnce(Return(0));
670
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900671 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900672 MacAddress mac_addr = {2, 2, 2, 2, 2, 2};
673 EXPECT_TRUE(datapath.ConfigureInterface("foo", mac_addr, Ipv4Addr(1, 1, 1, 1),
674 30, true, true));
Garrick Evans54861622019-07-19 09:05:09 +0900675}
676
677TEST(DatapathTest, RemoveInterface) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900678 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900679 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900680 EXPECT_CALL(runner,
681 ip(StrEq("link"), StrEq("delete"), ElementsAre("foo"), false));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900682 Datapath datapath(&runner, &firewall);
Garrick Evans54861622019-07-19 09:05:09 +0900683 datapath.RemoveInterface("foo");
Garrick Evans54861622019-07-19 09:05:09 +0900684}
685
Garrick Evans8a949dc2019-07-18 16:17:53 +0900686TEST(DatapathTest, RemoveBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900687 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900688 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900689 EXPECT_CALL(runner, iptables(StrEq("mangle"),
690 ElementsAre("-D", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900691 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900692 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900693 EXPECT_CALL(runner,
694 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "down"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900695 EXPECT_CALL(runner, brctl(StrEq("delbr"), ElementsAre("br"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900696 Datapath datapath(&runner, &firewall);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900697 datapath.RemoveBridge("br");
Garrick Evans8a949dc2019-07-18 16:17:53 +0900698}
699
Hugo Benichi321f23b2020-09-25 15:42:05 +0900700TEST(DatapathTest, AddRemoveSourceIPv4DropRule) {
701 MockProcessRunner runner;
702 MockFirewall firewall;
703 EXPECT_CALL(runner,
704 iptables(StrEq("filter"),
705 ElementsAre("-I", "OUTPUT", "-o", "eth+", "-s",
706 "100.115.92.0/24", "-j", "DROP", "-w"),
707 true, nullptr));
708 EXPECT_CALL(runner,
709 iptables(StrEq("filter"),
710 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
711 "100.115.92.0/24", "-j", "DROP", "-w"),
712 true, nullptr));
713 Datapath datapath(&runner, &firewall);
714 datapath.AddSourceIPv4DropRule("eth+", "100.115.92.0/24");
715 datapath.RemoveSourceIPv4DropRule("eth+", "100.115.92.0/24");
716}
717
Hugo Benichi7c342672020-09-08 09:18:14 +0900718TEST(DatapathTest, StartRoutingNamespace) {
719 MockProcessRunner runner;
720 MockFirewall firewall;
721 MacAddress mac = {1, 2, 3, 4, 5, 6};
722
723 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
724 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), kTestPID, true));
725 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
726 ElementsAre("arc_ns0", "type", "veth", "peer", "name",
727 "veth0", "netns", "netns_foo"),
728 true));
729 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
730 ElementsAre("100.115.92.130/30", "brd",
731 "100.115.92.131", "dev", "veth0"),
732 true))
733 .WillOnce(Return(0));
734 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
735 ElementsAre("dev", "veth0", "up", "addr",
736 "01:02:03:04:05:06", "multicast", "off"),
737 true))
738 .WillOnce(Return(0));
739 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
740 ElementsAre("arc_ns0", "up"), true));
741 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
742 ElementsAre("100.115.92.129/30", "brd",
743 "100.115.92.131", "dev", "arc_ns0"),
744 true))
745 .WillOnce(Return(0));
746 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
747 ElementsAre("dev", "arc_ns0", "up", "addr",
748 "01:02:03:04:05:06", "multicast", "off"),
749 true))
750 .WillOnce(Return(0));
751 EXPECT_CALL(runner, iptables(StrEq("filter"),
752 ElementsAre("-A", "FORWARD", "-o", "arc_ns0",
753 "-j", "ACCEPT", "-w"),
754 true, nullptr));
755 EXPECT_CALL(runner,
756 iptables(StrEq("mangle"),
757 ElementsAre("-A", "PREROUTING", "-i", "arc_ns0", "-j",
758 "MARK", "--set-mark", "1/1", "-w"),
759 true, nullptr));
760
761 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
762 datapath.StartRoutingNamespace(
763 kTestPID, "netns_foo", "arc_ns0", "veth0", Ipv4Addr(100, 115, 92, 128),
764 30, Ipv4Addr(100, 115, 92, 129), Ipv4Addr(100, 115, 92, 130), mac);
765 ioctl_reqs.clear();
766 ioctl_rtentry_args.clear();
767}
768
769TEST(DatapathTest, StopRoutingNamespace) {
770 MockProcessRunner runner;
771 MockFirewall firewall;
772
773 EXPECT_CALL(runner, iptables(StrEq("filter"),
774 ElementsAre("-D", "FORWARD", "-o", "arc_ns0",
775 "-j", "ACCEPT", "-w"),
776 true, nullptr));
777 EXPECT_CALL(runner,
778 iptables(StrEq("mangle"),
779 ElementsAre("-D", "PREROUTING", "-i", "arc_ns0", "-j",
780 "MARK", "--set-mark", "1/1", "-w"),
781 true, nullptr));
782 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
783 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("delete"), ElementsAre("arc_ns0"),
784 false));
785
786 Datapath datapath(&runner, &firewall);
787 datapath.StopRoutingNamespace("netns_foo", "arc_ns0",
788 Ipv4Addr(100, 115, 92, 128), 30,
789 Ipv4Addr(100, 115, 92, 129));
790}
791
Hugo Benichi8d622b52020-08-13 15:24:12 +0900792TEST(DatapathTest, StartRoutingDevice_Arc) {
793 MockProcessRunner runner;
794 MockFirewall firewall;
795 EXPECT_CALL(runner, iptables(StrEq("nat"),
796 ElementsAre("-A", "PREROUTING", "-i", "eth0",
797 "-m", "socket", "--nowildcard", "-j",
798 "ACCEPT", "-w"),
799 true, nullptr));
800 EXPECT_CALL(runner, iptables(StrEq("nat"),
801 ElementsAre("-A", "PREROUTING", "-i", "eth0",
802 "-p", "tcp", "-j", "DNAT",
803 "--to-destination", "1.2.3.4", "-w"),
804 true, nullptr));
805 EXPECT_CALL(runner, iptables(StrEq("nat"),
806 ElementsAre("-A", "PREROUTING", "-i", "eth0",
807 "-p", "udp", "-j", "DNAT",
808 "--to-destination", "1.2.3.4", "-w"),
809 true, nullptr));
810 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900811 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
812 "arc_eth0", "-j", "ACCEPT", "-w"),
813 true, nullptr));
814 EXPECT_CALL(runner, iptables(StrEq("filter"),
815 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
816 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900817 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900818 EXPECT_CALL(runner, iptables(StrEq("mangle"),
819 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
820 "-j", "MARK", "--set-mark",
821 "0x00002000/0x00003f00", "-w"),
822 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900823 EXPECT_CALL(runner, iptables(StrEq("mangle"),
824 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
825 "-j", "MARK", "--set-mark",
826 "0x03ea0000/0xffff0000", "-w"),
827 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900828 EXPECT_CALL(
829 runner,
830 ip6tables(StrEq("mangle"),
831 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
832 "--set-mark", "0x00002000/0x00003f00", "-w"),
833 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900834 EXPECT_CALL(
835 runner,
836 ip6tables(StrEq("mangle"),
837 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
838 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
839 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900840
841 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900842 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900843 datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
844 TrafficSource::ARC);
845}
846
847TEST(DatapathTest, StartRoutingDevice_CrosVM) {
848 MockProcessRunner runner;
849 MockFirewall firewall;
850 EXPECT_CALL(runner, iptables(StrEq("filter"),
851 ElementsAre("-A", "FORWARD", "-o", "vmtap0",
852 "-j", "ACCEPT", "-w"),
853 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900854 EXPECT_CALL(runner, iptables(StrEq("filter"),
855 ElementsAre("-A", "FORWARD", "-i", "vmtap0",
856 "-j", "ACCEPT", "-w"),
857 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900858 EXPECT_CALL(runner, iptables(StrEq("mangle"),
859 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
860 "-j", "MARK", "--set-mark",
861 "0x00002100/0x00003f00", "-w"),
862 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900863 EXPECT_CALL(runner, iptables(StrEq("mangle"),
864 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
865 "-j", "CONNMARK", "--restore-mark",
866 "--mask", "0xffff0000", "-w"),
867 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900868 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
869 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
870 "-j", "MARK", "--set-mark",
871 "0x00002100/0x00003f00", "-w"),
872 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900873 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
874 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
875 "-j", "CONNMARK", "--restore-mark",
876 "--mask", "0xffff0000", "-w"),
877 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900878 EXPECT_CALL(runner, iptables(StrEq("mangle"),
879 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
880 "-j", "apply_vpn_mark", "-w"),
881 true, nullptr));
882 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
883 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
884 "-j", "apply_vpn_mark", "-w"),
885 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900886
887 Datapath datapath(&runner, &firewall);
888 datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
889 TrafficSource::CROSVM);
890}
891
892TEST(DatapathTest, StopRoutingDevice_Arc) {
893 MockProcessRunner runner;
894 MockFirewall firewall;
895 EXPECT_CALL(runner, iptables(StrEq("nat"),
896 ElementsAre("-D", "PREROUTING", "-i", "eth0",
897 "-m", "socket", "--nowildcard", "-j",
898 "ACCEPT", "-w"),
899 true, nullptr));
900 EXPECT_CALL(runner, iptables(StrEq("nat"),
901 ElementsAre("-D", "PREROUTING", "-i", "eth0",
902 "-p", "tcp", "-j", "DNAT",
903 "--to-destination", "1.2.3.4", "-w"),
904 true, nullptr));
905 EXPECT_CALL(runner, iptables(StrEq("nat"),
906 ElementsAre("-D", "PREROUTING", "-i", "eth0",
907 "-p", "udp", "-j", "DNAT",
908 "--to-destination", "1.2.3.4", "-w"),
909 true, nullptr));
910 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900911 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
912 "arc_eth0", "-j", "ACCEPT", "-w"),
913 true, nullptr));
914 EXPECT_CALL(runner, iptables(StrEq("filter"),
915 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
916 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900917 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900918 EXPECT_CALL(runner, iptables(StrEq("mangle"),
919 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
920 "-j", "MARK", "--set-mark",
921 "0x00002000/0x00003f00", "-w"),
922 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900923 EXPECT_CALL(runner, iptables(StrEq("mangle"),
924 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
925 "-j", "MARK", "--set-mark",
926 "0x03ea0000/0xffff0000", "-w"),
927 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900928 EXPECT_CALL(
929 runner,
930 ip6tables(StrEq("mangle"),
931 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
932 "--set-mark", "0x00002000/0x00003f00", "-w"),
933 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900934 EXPECT_CALL(
935 runner,
936 ip6tables(StrEq("mangle"),
937 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
938 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
939 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900940
941 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900942 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900943 datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
944 TrafficSource::ARC);
945}
946
947TEST(DatapathTest, StopRoutingDevice_CrosVM) {
948 MockProcessRunner runner;
949 MockFirewall firewall;
950 EXPECT_CALL(runner, iptables(StrEq("filter"),
951 ElementsAre("-D", "FORWARD", "-o", "vmtap0",
952 "-j", "ACCEPT", "-w"),
953 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900954 EXPECT_CALL(runner, iptables(StrEq("filter"),
955 ElementsAre("-D", "FORWARD", "-i", "vmtap0",
956 "-j", "ACCEPT", "-w"),
957 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900958 EXPECT_CALL(runner, iptables(StrEq("mangle"),
959 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
960 "-j", "MARK", "--set-mark",
961 "0x00002100/0x00003f00", "-w"),
962 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900963 EXPECT_CALL(runner, iptables(StrEq("mangle"),
964 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
965 "-j", "CONNMARK", "--restore-mark",
966 "--mask", "0xffff0000", "-w"),
967 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900968 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
969 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
970 "-j", "MARK", "--set-mark",
971 "0x00002100/0x00003f00", "-w"),
972 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900973 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
974 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
975 "-j", "CONNMARK", "--restore-mark",
976 "--mask", "0xffff0000", "-w"),
977 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900978 EXPECT_CALL(runner, iptables(StrEq("mangle"),
979 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
980 "-j", "apply_vpn_mark", "-w"),
981 true, nullptr));
982 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
983 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
984 "-j", "apply_vpn_mark", "-w"),
985 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900986
987 Datapath datapath(&runner, &firewall);
988 datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
989 TrafficSource::CROSVM);
990}
991
Hugo Benichid82d8832020-08-14 10:05:03 +0900992TEST(DatapathTest, StartStopIpForwarding) {
993 struct {
994 IpFamily family;
995 std::string iif;
996 std::string oif;
997 std::vector<std::string> start_args;
998 std::vector<std::string> stop_args;
999 bool result;
1000 } testcases[] = {
1001 {IpFamily::IPv4, "", "", {}, {}, false},
1002 {IpFamily::NONE, "foo", "bar", {}, {}, false},
1003 {IpFamily::IPv4,
1004 "foo",
1005 "bar",
1006 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1007 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1008 true},
1009 {IpFamily::IPv4,
1010 "",
1011 "bar",
1012 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1013 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1014 true},
1015 {IpFamily::IPv4,
1016 "foo",
1017 "",
1018 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1019 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1020 true},
1021 {IpFamily::IPv6,
1022 "foo",
1023 "bar",
1024 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1025 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1026 true},
1027 {IpFamily::IPv6,
1028 "",
1029 "bar",
1030 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1031 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1032 true},
1033 {IpFamily::IPv6,
1034 "foo",
1035 "",
1036 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1037 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1038 true},
1039 {IpFamily::Dual,
1040 "foo",
1041 "bar",
1042 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1043 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1044 true},
1045 {IpFamily::Dual,
1046 "",
1047 "bar",
1048 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1049 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1050 true},
1051 {IpFamily::Dual,
1052 "foo",
1053 "",
1054 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1055 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1056 true},
1057 };
1058
1059 for (const auto& tt : testcases) {
1060 MockProcessRunner runner;
1061 MockFirewall firewall;
1062 if (tt.result) {
1063 if (tt.family & IpFamily::IPv4) {
1064 EXPECT_CALL(runner,
1065 iptables(StrEq("filter"), tt.start_args, true, nullptr))
1066 .WillOnce(Return(0));
1067 EXPECT_CALL(runner,
1068 iptables(StrEq("filter"), tt.stop_args, true, nullptr))
1069 .WillOnce(Return(0));
1070 }
1071 if (tt.family & IpFamily::IPv6) {
1072 EXPECT_CALL(runner,
1073 ip6tables(StrEq("filter"), tt.start_args, true, nullptr))
1074 .WillOnce(Return(0));
1075 EXPECT_CALL(runner,
1076 ip6tables(StrEq("filter"), tt.stop_args, true, nullptr))
1077 .WillOnce(Return(0));
1078 }
1079 }
1080 Datapath datapath(&runner, &firewall);
1081
1082 EXPECT_EQ(tt.result, datapath.StartIpForwarding(tt.family, tt.iif, tt.oif));
1083 EXPECT_EQ(tt.result, datapath.StopIpForwarding(tt.family, tt.iif, tt.oif));
1084 }
1085}
1086
Hugo Benichi76be34a2020-08-26 22:35:54 +09001087TEST(DatapathTest, StartStopConnectionPinning) {
1088 MockProcessRunner runner;
1089 MockFirewall firewall;
Hugo Benichi1af52392020-11-27 18:09:32 +09001090
1091 // Setup
Hugo Benichi76be34a2020-08-26 22:35:54 +09001092 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1093 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1094 "-j", "CONNMARK", "--set-mark",
1095 "0x03eb0000/0xffff0000", "-w"),
1096 true, nullptr));
Hugo Benichi76be34a2020-08-26 22:35:54 +09001097 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1098 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1099 "-j", "CONNMARK", "--set-mark",
1100 "0x03eb0000/0xffff0000", "-w"),
1101 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001102 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1103 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1104 "-j", "CONNMARK", "--save-mark",
1105 "--mask", "0x00003f00", "-w"),
1106 true, nullptr));
1107 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1108 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1109 "-j", "CONNMARK", "--save-mark",
1110 "--mask", "0x00003f00", "-w"),
1111 true, nullptr));
1112 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1113 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1114 "-j", "CONNMARK", "--restore-mark",
1115 "--mask", "0x00003f00", "-w"),
1116 true, nullptr));
1117 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1118 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1119 "-j", "CONNMARK", "--restore-mark",
1120 "--mask", "0x00003f00", "-w"),
1121 true, nullptr));
1122 // Teardown
1123 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1124 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1125 "-j", "CONNMARK", "--set-mark",
1126 "0x03eb0000/0xffff0000", "-w"),
1127 true, nullptr));
Hugo Benichi76be34a2020-08-26 22:35:54 +09001128 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1129 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1130 "-j", "CONNMARK", "--set-mark",
1131 "0x03eb0000/0xffff0000", "-w"),
1132 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001133 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1134 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1135 "-j", "CONNMARK", "--save-mark",
1136 "--mask", "0x00003f00", "-w"),
1137 true, nullptr));
1138 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1139 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1140 "-j", "CONNMARK", "--save-mark",
1141 "--mask", "0x00003f00", "-w"),
1142 true, nullptr));
1143 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1144 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1145 "-j", "CONNMARK", "--restore-mark",
1146 "--mask", "0x00003f00", "-w"),
1147 true, nullptr));
1148 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1149 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1150 "-j", "CONNMARK", "--restore-mark",
1151 "--mask", "0x00003f00", "-w"),
1152 true, nullptr));
1153
Hugo Benichi76be34a2020-08-26 22:35:54 +09001154 Datapath datapath(&runner, &firewall);
1155 datapath.SetIfnameIndex("eth0", 3);
1156 datapath.StartConnectionPinning("eth0");
1157 datapath.StopConnectionPinning("eth0");
1158}
1159
Hugo Benichi2a940542020-10-26 18:50:49 +09001160TEST(DatapathTest, StartStopVpnRouting_NoVirtualDevices) {
1161 MockProcessRunner runner;
1162 MockFirewall firewall;
1163
1164 // Setup
1165 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1166 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1167 "-j", "CONNMARK", "--set-mark",
1168 "0x03ed0000/0xffff0000", "-w"),
1169 true, nullptr));
1170 EXPECT_CALL(runner,
1171 iptables(StrEq("mangle"),
1172 ElementsAre("-A", "apply_vpn_mark", "-j", "MARK",
1173 "--set-mark", "0x03ed0000/0xffff0000", "-w"),
1174 true, nullptr));
1175 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1176 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1177 "-j", "CONNMARK", "--set-mark",
1178 "0x03ed0000/0xffff0000", "-w"),
1179 true, nullptr));
1180 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1181 ElementsAre("-A", "apply_vpn_mark", "-j",
1182 "MARK", "--set-mark",
1183 "0x03ed0000/0xffff0000", "-w"),
1184 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001185 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1186 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1187 "-j", "CONNMARK", "--save-mark",
1188 "--mask", "0x00003f00", "-w"),
1189 true, nullptr));
1190 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1191 ElementsAre("-A", "POSTROUTING", "-o", "arcbr0",
1192 "-j", "CONNMARK", "--save-mark",
1193 "--mask", "0x00003f00", "-w"),
1194 true, nullptr));
1195 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1196 ElementsAre("-A", "PREROUTING", "-i", "arcbr0",
1197 "-j", "CONNMARK", "--restore-mark",
1198 "--mask", "0x00003f00", "-w"),
1199 true, nullptr));
1200 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1201 ElementsAre("-A", "PREROUTING", "-i", "arcbr0",
1202 "-j", "CONNMARK", "--restore-mark",
1203 "--mask", "0x00003f00", "-w"),
1204 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +09001205 // Teardown
1206 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1207 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1208 "-j", "CONNMARK", "--set-mark",
1209 "0x03ed0000/0xffff0000", "-w"),
1210 true, nullptr));
1211 EXPECT_CALL(runner,
1212 iptables(StrEq("mangle"),
1213 ElementsAre("-D", "apply_vpn_mark", "-j", "MARK",
1214 "--set-mark", "0x03ed0000/0xffff0000", "-w"),
1215 true, nullptr));
1216 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1217 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1218 "-j", "CONNMARK", "--set-mark",
1219 "0x03ed0000/0xffff0000", "-w"),
1220 true, nullptr));
1221 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1222 ElementsAre("-D", "apply_vpn_mark", "-j",
1223 "MARK", "--set-mark",
1224 "0x03ed0000/0xffff0000", "-w"),
1225 true, nullptr));
Hugo Benichi1af52392020-11-27 18:09:32 +09001226 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1227 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1228 "-j", "CONNMARK", "--save-mark",
1229 "--mask", "0x00003f00", "-w"),
1230 true, nullptr));
1231 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1232 ElementsAre("-D", "POSTROUTING", "-o", "arcbr0",
1233 "-j", "CONNMARK", "--save-mark",
1234 "--mask", "0x00003f00", "-w"),
1235 true, nullptr));
1236 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1237 ElementsAre("-D", "PREROUTING", "-i", "arcbr0",
1238 "-j", "CONNMARK", "--restore-mark",
1239 "--mask", "0x00003f00", "-w"),
1240 true, nullptr));
1241 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1242 ElementsAre("-D", "PREROUTING", "-i", "arcbr0",
1243 "-j", "CONNMARK", "--restore-mark",
1244 "--mask", "0x00003f00", "-w"),
1245 true, nullptr));
Hugo Benichi2a940542020-10-26 18:50:49 +09001246
1247 Datapath datapath(&runner, &firewall);
1248 datapath.SetIfnameIndex("arcbr0", 5);
1249 datapath.StartVpnRouting("arcbr0");
1250 datapath.StopVpnRouting("arcbr0");
1251}
1252
Garrick Evansf0ab7132019-06-18 14:50:42 +09001253TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001254 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001255 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001256 EXPECT_CALL(runner, iptables(StrEq("nat"),
1257 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1258 "-m", "socket", "--nowildcard", "-j",
1259 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001260 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001261 EXPECT_CALL(runner, iptables(StrEq("nat"),
1262 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1263 "-p", "tcp", "-j", "DNAT",
1264 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001265 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001266 EXPECT_CALL(runner, iptables(StrEq("nat"),
1267 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1268 "-p", "udp", "-j", "DNAT",
1269 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001270 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001271 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001272 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001273}
1274
1275TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001276 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001277 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001278 EXPECT_CALL(runner, iptables(StrEq("nat"),
1279 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1280 "-m", "socket", "--nowildcard", "-j",
1281 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001282 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001283 EXPECT_CALL(runner, iptables(StrEq("nat"),
1284 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1285 "-p", "tcp", "-j", "DNAT",
1286 "--to-destination", "1.2.3.4", "-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("-D", "PREROUTING", "-i", "eth0",
1290 "-p", "udp", "-j", "DNAT",
1291 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001292 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001293 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001294 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001295}
1296
Garrick Evans664a82f2019-12-17 12:18:05 +09001297TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001298 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001299 MockFirewall firewall;
1300 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Hugo Benichi7c342672020-09-08 09:18:14 +09001301
Garrick Evans664a82f2019-12-17 12:18:05 +09001302 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +09001303 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +09001304 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +09001305 EXPECT_EQ(ioctl_reqs, expected);
1306 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +09001307 ioctl_rtentry_args.clear();
Taoyu Li90c13912019-11-26 17:56:54 +09001308}
1309
1310TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001311 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001312 MockFirewall firewall;
Taoyu Lica49c832019-12-06 17:56:43 +09001313 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +09001314 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1315 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1316 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001317 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001318 .WillOnce(Return(1));
1319 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1320 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
1321 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001322 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001323 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1324 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1325 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001326 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001327 .WillOnce(Return(1));
1328 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1329 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
1330 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001331 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001332 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001333 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001334}
1335
Taoyu Lica49c832019-12-06 17:56:43 +09001336TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001337 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001338 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001339 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1340 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1341 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001342 false, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001343 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1344 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1345 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001346 false, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001347 Datapath datapath(&runner, &firewall);
Taoyu Lica49c832019-12-06 17:56:43 +09001348 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +09001349}
1350
Taoyu Li90c13912019-11-26 17:56:54 +09001351TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001352 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001353 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001354 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1355 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
1356 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001357 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001358 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1359 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
1360 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001361 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001362 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001363 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001364}
1365
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001366TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001367 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001368 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001369 EXPECT_CALL(runner,
1370 ip6(StrEq("route"), StrEq("replace"),
1371 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001372 Datapath datapath(&runner, &firewall);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001373 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001374}
1375
Hugo Benichie8758b52020-04-03 14:49:01 +09001376TEST(DatapathTest, AddIPv4Route) {
1377 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001378 MockFirewall firewall;
1379 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichie8758b52020-04-03 14:49:01 +09001380
1381 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1382 Ipv4Addr(255, 255, 255, 0));
1383 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1384 Ipv4Addr(255, 255, 255, 0));
1385 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1386 Ipv4Addr(255, 255, 255, 252));
1387 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1388 Ipv4Addr(255, 255, 255, 252));
1389
1390 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
1391 SIOCDELRT};
1392 EXPECT_EQ(expected_reqs, ioctl_reqs);
Hugo Benichie8758b52020-04-03 14:49:01 +09001393
1394 std::string route1 =
1395 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
1396 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
1397 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
1398 "RTF_GATEWAY}";
1399 std::string route2 =
1400 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
1401 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
1402 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
1403 std::vector<std::string> captured_routes;
1404 for (const auto& route : ioctl_rtentry_args) {
1405 std::ostringstream stream;
1406 stream << route.second;
1407 captured_routes.emplace_back(stream.str());
1408 }
Hugo Benichie8758b52020-04-03 14:49:01 +09001409 EXPECT_EQ(route1, captured_routes[0]);
1410 EXPECT_EQ(route1, captured_routes[1]);
1411 EXPECT_EQ(route2, captured_routes[2]);
1412 EXPECT_EQ(route2, captured_routes[3]);
Hugo Benichi7c342672020-09-08 09:18:14 +09001413 ioctl_reqs.clear();
1414 ioctl_rtentry_args.clear();
Hugo Benichie8758b52020-04-03 14:49:01 +09001415}
1416
Garrick Evansd291af62020-05-25 10:39:06 +09001417TEST(DatapathTest, AddSNATMarkRules) {
1418 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001419 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001420 EXPECT_CALL(
1421 runner,
1422 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001423 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001424 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001425 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001426 EXPECT_CALL(runner,
1427 iptables(StrEq("filter"),
1428 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
1429 "1/1", "-j", "ACCEPT", "-w"),
1430 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001431 EXPECT_CALL(runner,
1432 iptables(StrEq("nat"),
1433 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001434 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001435 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001436 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001437 datapath.AddSNATMarkRules();
1438}
1439
1440TEST(DatapathTest, RemoveSNATMarkRules) {
1441 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001442 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001443 EXPECT_CALL(
1444 runner,
1445 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001446 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001447 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001448 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001449 EXPECT_CALL(runner,
1450 iptables(StrEq("filter"),
1451 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
1452 "1/1", "-j", "ACCEPT", "-w"),
1453 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001454 EXPECT_CALL(runner,
1455 iptables(StrEq("nat"),
1456 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001457 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001458 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001459 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001460 datapath.RemoveSNATMarkRules();
1461}
1462
Garrick Evans2f581a02020-05-11 10:43:35 +09001463TEST(DatapathTest, ArcVethHostName) {
1464 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
1465 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
1466 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
1467 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
1468 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
1469 EXPECT_EQ("vethexceeds_ify", ifname);
1470 EXPECT_LT(ifname.length(), IFNAMSIZ);
1471}
1472
Garrick Evans8a067562020-05-11 12:47:30 +09001473TEST(DatapathTest, ArcBridgeName) {
1474 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
1475 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
1476 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
1477 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
1478 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
1479 EXPECT_EQ("arc_exceeds_ify", ifname);
1480 EXPECT_LT(ifname.length(), IFNAMSIZ);
1481}
1482
Garrick Evans3388a032020-03-24 11:25:55 +09001483} // namespace patchpanel