blob: 0ec69e3e2afebfe5eac8244d9b097a97a7528d89 [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 Benichi3a9162b2020-09-09 15:47:40 +0900186 // Asserts for apply_local_source_mark chain
187 EXPECT_CALL(runner,
188 iptables(StrEq("mangle"),
189 ElementsAre("-N", "apply_local_source_mark", "-w"), true,
190 nullptr));
191 EXPECT_CALL(runner,
192 iptables(StrEq("mangle"),
193 ElementsAre("-F", "apply_local_source_mark", "-w"), true,
194 nullptr));
195 EXPECT_CALL(runner, iptables(StrEq("mangle"),
196 ElementsAre("-A", "OUTPUT", "-j",
197 "apply_local_source_mark", "-w"),
198 true, nullptr));
199 EXPECT_CALL(
200 runner,
201 iptables(StrEq("mangle"),
202 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
203 "--uid-owner", "chronos", "-j", "MARK", "--set-mark",
204 "0x00008100/0x0000ff00", "-w"),
205 true, nullptr));
206 EXPECT_CALL(runner, iptables(StrEq("mangle"),
207 ElementsAre("-A", "apply_local_source_mark",
208 "-m", "owner", "--uid-owner",
209 "debugd", "-j", "MARK", "--set-mark",
210 "0x00008200/0x0000ff00", "-w"),
211 true, nullptr));
212 EXPECT_CALL(runner,
213 iptables(StrEq("mangle"),
214 ElementsAre("-A", "apply_local_source_mark", "-m",
215 "owner", "--uid-owner", "cups", "-j", "MARK",
216 "--set-mark", "0x00008200/0x0000ff00", "-w"),
217 true, nullptr));
218 EXPECT_CALL(
219 runner,
220 iptables(StrEq("mangle"),
221 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
222 "--uid-owner", "kerberosd", "-j", "MARK",
223 "--set-mark", "0x00008400/0x0000ff00", "-w"),
224 true, nullptr));
225 EXPECT_CALL(
226 runner,
227 iptables(StrEq("mangle"),
228 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
229 "--uid-owner", "kerberosd-exec", "-j", "MARK",
230 "--set-mark", "0x00008400/0x0000ff00", "-w"),
231 true, nullptr));
232 EXPECT_CALL(
233 runner,
234 iptables(StrEq("mangle"),
235 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
236 "--uid-owner", "tlsdate", "-j", "MARK", "--set-mark",
237 "0x00008400/0x0000ff00", "-w"),
238 true, nullptr));
239 EXPECT_CALL(
240 runner,
241 iptables(StrEq("mangle"),
242 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
243 "--uid-owner", "pluginvm", "-j", "MARK",
244 "--set-mark", "0x00008200/0x0000ff00", "-w"),
245 true, nullptr));
246 EXPECT_CALL(
247 runner,
248 iptables(StrEq("mangle"),
249 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
250 "--uid-owner", "fuse-smbfs", "-j", "MARK",
251 "--set-mark", "0x00008400/0x0000ff00", "-w"),
252 true, nullptr));
253 EXPECT_CALL(
254 runner,
255 iptables(StrEq("mangle"),
256 ElementsAre("-A", "apply_local_source_mark", "-m", "mark",
257 "--mark", "0x0/0x00003f00", "-j", "MARK",
258 "--set-mark", "0x00000400/0x00003f00", "-w"),
259 true, nullptr));
260 EXPECT_CALL(runner,
261 ip6tables(StrEq("mangle"),
262 ElementsAre("-N", "apply_local_source_mark", "-w"),
263 true, nullptr));
264 EXPECT_CALL(runner,
265 ip6tables(StrEq("mangle"),
266 ElementsAre("-F", "apply_local_source_mark", "-w"),
267 true, nullptr));
268 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
269 ElementsAre("-A", "OUTPUT", "-j",
270 "apply_local_source_mark", "-w"),
271 true, nullptr));
272 EXPECT_CALL(
273 runner,
274 ip6tables(StrEq("mangle"),
275 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
276 "--uid-owner", "debugd", "-j", "MARK", "--set-mark",
277 "0x00008200/0x0000ff00", "-w"),
278 true, nullptr));
279 EXPECT_CALL(
280 runner,
281 ip6tables(StrEq("mangle"),
282 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
283 "--uid-owner", "chronos", "-j", "MARK",
284 "--set-mark", "0x00008100/0x0000ff00", "-w"),
285 true, nullptr));
286 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
287 ElementsAre("-A", "apply_local_source_mark",
288 "-m", "owner", "--uid-owner",
289 "cups", "-j", "MARK", "--set-mark",
290 "0x00008200/0x0000ff00", "-w"),
291 true, nullptr));
292 EXPECT_CALL(
293 runner,
294 ip6tables(StrEq("mangle"),
295 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
296 "--uid-owner", "kerberosd", "-j", "MARK",
297 "--set-mark", "0x00008400/0x0000ff00", "-w"),
298 true, nullptr));
299 EXPECT_CALL(
300 runner,
301 ip6tables(StrEq("mangle"),
302 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
303 "--uid-owner", "kerberosd-exec", "-j", "MARK",
304 "--set-mark", "0x00008400/0x0000ff00", "-w"),
305 true, nullptr));
306 EXPECT_CALL(
307 runner,
308 ip6tables(StrEq("mangle"),
309 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
310 "--uid-owner", "tlsdate", "-j", "MARK",
311 "--set-mark", "0x00008400/0x0000ff00", "-w"),
312 true, nullptr));
313 EXPECT_CALL(
314 runner,
315 ip6tables(StrEq("mangle"),
316 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
317 "--uid-owner", "pluginvm", "-j", "MARK",
318 "--set-mark", "0x00008200/0x0000ff00", "-w"),
319 true, nullptr));
320 EXPECT_CALL(
321 runner,
322 ip6tables(StrEq("mangle"),
323 ElementsAre("-A", "apply_local_source_mark", "-m", "owner",
324 "--uid-owner", "fuse-smbfs", "-j", "MARK",
325 "--set-mark", "0x00008400/0x0000ff00", "-w"),
326 true, nullptr));
327 EXPECT_CALL(
328 runner,
329 ip6tables(StrEq("mangle"),
330 ElementsAre("-A", "apply_local_source_mark", "-m", "mark",
331 "--mark", "0x0/0x00003f00", "-j", "MARK",
332 "--set-mark", "0x00000400/0x00003f00", "-w"),
333 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900334 // Asserts for apply_vpn_mark chain
335 EXPECT_CALL(runner, iptables(StrEq("mangle"),
336 ElementsAre("-N", "apply_vpn_mark", "-w"), true,
337 nullptr));
338 EXPECT_CALL(runner, iptables(StrEq("mangle"),
339 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
340 nullptr));
341 EXPECT_CALL(runner, iptables(StrEq("mangle"),
342 ElementsAre("-A", "OUTPUT", "-m", "mark",
343 "--mark", "0x00008000/0x0000c000",
344 "-j", "apply_vpn_mark", "-w"),
345 true, nullptr));
346 EXPECT_CALL(runner, iptables(StrEq("mangle"),
347 ElementsAre("-A", "apply_vpn_mark", "-m", "mark",
348 "!", "--mark", "0x0/0xffff0000",
349 "-j", "ACCEPT", "-w"),
350 true, nullptr));
351 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
352 ElementsAre("-N", "apply_vpn_mark", "-w"), true,
353 nullptr));
354 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
355 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
356 nullptr));
357 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
358 ElementsAre("-A", "OUTPUT", "-m", "mark",
359 "--mark", "0x00008000/0x0000c000",
360 "-j", "apply_vpn_mark", "-w"),
361 true, nullptr));
362 EXPECT_CALL(
363 runner,
364 ip6tables(StrEq("mangle"),
365 ElementsAre("-A", "apply_vpn_mark", "-m", "mark", "!", "--mark",
366 "0x0/0xffff0000", "-j", "ACCEPT", "-w"),
367 true, nullptr));
Hugo Benichibf811c62020-09-07 17:30:45 +0900368
369 Datapath datapath(&runner, &firewall);
370 datapath.Start();
371}
372
373TEST(DatapathTest, Stop) {
374 MockProcessRunner runner;
375 MockFirewall firewall;
376 // Asserts for sysctl modifications
377 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_local_port_range"),
378 StrEq("32768 61000"), true));
379 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv6.conf.all.forwarding"),
380 StrEq("0"), true));
381 EXPECT_CALL(runner, sysctl_w(StrEq("net.ipv4.ip_forward"), StrEq("0"), true));
382 // Asserts for RemoveOutboundIPv4SNATMark("vmtap+")
383 EXPECT_CALL(runner,
384 iptables(StrEq("mangle"),
385 ElementsAre("-D", "PREROUTING", "-i", "vmtap+", "-j",
386 "MARK", "--set-mark", "1/1", "-w"),
387 true, nullptr));
388 // Asserts for RemoveForwardEstablishedRule
389 EXPECT_CALL(runner,
390 iptables(StrEq("filter"),
391 ElementsAre("-D", "FORWARD", "-m", "state", "--state",
392 "ESTABLISHED,RELATED", "-j", "ACCEPT", "-w"),
393 true, nullptr));
394 // Asserts for RemoveSNATMarkRules
395 EXPECT_CALL(
396 runner,
397 iptables(StrEq("filter"),
398 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
399 "state", "--state", "INVALID", "-j", "DROP", "-w"),
400 true, nullptr));
401 EXPECT_CALL(runner,
402 iptables(StrEq("filter"),
403 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
404 "1/1", "-j", "ACCEPT", "-w"),
405 true, nullptr));
406 EXPECT_CALL(runner,
407 iptables(StrEq("nat"),
408 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
409 "1/1", "-j", "MASQUERADE", "-w"),
410 true, nullptr));
411 // Asserts for RemoveSourceIPv4DropRule() calls.
412 EXPECT_CALL(runner,
413 iptables(StrEq("filter"),
414 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
415 "100.115.92.0/23", "-j", "DROP", "-w"),
416 true, nullptr));
417 EXPECT_CALL(runner,
418 iptables(StrEq("filter"),
419 ElementsAre("-D", "OUTPUT", "-o", "wlan+", "-s",
420 "100.115.92.0/23", "-j", "DROP", "-w"),
421 true, nullptr));
422 EXPECT_CALL(runner,
423 iptables(StrEq("filter"),
424 ElementsAre("-D", "OUTPUT", "-o", "mlan+", "-s",
425 "100.115.92.0/23", "-j", "DROP", "-w"),
426 true, nullptr));
427 EXPECT_CALL(runner,
428 iptables(StrEq("filter"),
429 ElementsAre("-D", "OUTPUT", "-o", "usb+", "-s",
430 "100.115.92.0/23", "-j", "DROP", "-w"),
431 true, nullptr));
432 EXPECT_CALL(runner,
433 iptables(StrEq("filter"),
434 ElementsAre("-D", "OUTPUT", "-o", "wwan+", "-s",
435 "100.115.92.0/23", "-j", "DROP", "-w"),
436 true, nullptr));
437 EXPECT_CALL(runner,
438 iptables(StrEq("filter"),
439 ElementsAre("-D", "OUTPUT", "-o", "rmnet+", "-s",
440 "100.115.92.0/23", "-j", "DROP", "-w"),
441 true, nullptr));
Hugo Benichi3a9162b2020-09-09 15:47:40 +0900442 // Asserts for apply_local_source_mark chain
443 EXPECT_CALL(runner, iptables(StrEq("mangle"),
444 ElementsAre("-D", "OUTPUT", "-j",
445 "apply_local_source_mark", "-w"),
446 true, nullptr));
447 EXPECT_CALL(runner,
448 iptables(StrEq("mangle"),
449 ElementsAre("-F", "apply_local_source_mark", "-w"), true,
450 nullptr));
451 EXPECT_CALL(runner,
452 iptables(StrEq("mangle"),
453 ElementsAre("-X", "apply_local_source_mark", "-w"), true,
454 nullptr));
455 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
456 ElementsAre("-D", "OUTPUT", "-j",
457 "apply_local_source_mark", "-w"),
458 true, nullptr));
459 EXPECT_CALL(runner,
460 ip6tables(StrEq("mangle"),
461 ElementsAre("-F", "apply_local_source_mark", "-w"),
462 true, nullptr));
463 EXPECT_CALL(runner,
464 ip6tables(StrEq("mangle"),
465 ElementsAre("-X", "apply_local_source_mark", "-w"),
466 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900467 // Asserts for apply_vpn_mark chain
468 EXPECT_CALL(runner, iptables(StrEq("mangle"),
469 ElementsAre("-D", "OUTPUT", "-m", "mark",
470 "--mark", "0x00008000/0x0000c000",
471 "-j", "apply_vpn_mark", "-w"),
472 true, nullptr));
473 EXPECT_CALL(runner, iptables(StrEq("mangle"),
474 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
475 nullptr));
476 EXPECT_CALL(runner, iptables(StrEq("mangle"),
477 ElementsAre("-X", "apply_vpn_mark", "-w"), true,
478 nullptr));
479 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
480 ElementsAre("-D", "OUTPUT", "-m", "mark",
481 "--mark", "0x00008000/0x0000c000",
482 "-j", "apply_vpn_mark", "-w"),
483 true, nullptr));
484 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
485 ElementsAre("-F", "apply_vpn_mark", "-w"), true,
486 nullptr));
487 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
488 ElementsAre("-X", "apply_vpn_mark", "-w"), true,
489 nullptr));
Hugo Benichibf811c62020-09-07 17:30:45 +0900490
491 Datapath datapath(&runner, &firewall);
492 datapath.Stop();
493}
494
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900495TEST(DatapathTest, AddTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900496 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900497 MockFirewall firewall;
498 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900499 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900500 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900501 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900502 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900503 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900504 std::vector<ioctl_req_t> expected = {
505 TUNSETIFF, TUNSETPERSIST, SIOCSIFADDR, SIOCSIFNETMASK,
506 SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900507 EXPECT_EQ(ioctl_reqs, expected);
508 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900509 ioctl_rtentry_args.clear();
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900510}
511
512TEST(DatapathTest, AddTAPWithOwner) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900513 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900514 MockFirewall firewall;
515 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900516 MacAddress mac = {1, 2, 3, 4, 5, 6};
Qijiang Fane90b8792020-03-09 16:15:41 +0900517 Subnet subnet(Ipv4Addr(100, 115, 92, 4), 30, base::DoNothing());
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900518 auto addr = subnet.AllocateAtOffset(0);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900519 auto ifname = datapath.AddTAP("foo0", &mac, addr.get(), "root");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900520 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900521 std::vector<ioctl_req_t> expected = {
522 TUNSETIFF, TUNSETPERSIST, TUNSETOWNER, SIOCSIFADDR,
523 SIOCSIFNETMASK, SIOCSIFHWADDR, SIOCGIFFLAGS, SIOCSIFFLAGS};
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900524 EXPECT_EQ(ioctl_reqs, expected);
525 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900526 ioctl_rtentry_args.clear();
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900527}
528
Garrick Evans621ed262019-11-13 12:28:43 +0900529TEST(DatapathTest, AddTAPNoAddrs) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900530 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900531 MockFirewall firewall;
532 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Garrick Evans4f9f5572019-11-26 10:25:16 +0900533 auto ifname = datapath.AddTAP("foo0", nullptr, nullptr, "");
Garrick Evans621ed262019-11-13 12:28:43 +0900534 EXPECT_EQ(ifname, "foo0");
Hugo Benichie8758b52020-04-03 14:49:01 +0900535 std::vector<ioctl_req_t> expected = {TUNSETIFF, TUNSETPERSIST, SIOCGIFFLAGS,
536 SIOCSIFFLAGS};
Garrick Evans621ed262019-11-13 12:28:43 +0900537 EXPECT_EQ(ioctl_reqs, expected);
538 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +0900539 ioctl_rtentry_args.clear();
Garrick Evans621ed262019-11-13 12:28:43 +0900540}
541
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900542TEST(DatapathTest, RemoveTAP) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900543 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900544 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900545 EXPECT_CALL(runner, ip(StrEq("tuntap"), StrEq("del"),
546 ElementsAre("foo0", "mode", "tap"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900547 Datapath datapath(&runner, &firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900548 datapath.RemoveTAP("foo0");
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900549}
Garrick Evansf0ab7132019-06-18 14:50:42 +0900550
Hugo Benichi33860d72020-07-09 16:34:01 +0900551TEST(DatapathTest, NetnsAttachName) {
552 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900553 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900554 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
555 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), 1234, true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900556 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900557 EXPECT_TRUE(datapath.NetnsAttachName("netns_foo", 1234));
558}
559
560TEST(DatapathTest, NetnsDeleteName) {
561 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900562 MockFirewall firewall;
Hugo Benichi33860d72020-07-09 16:34:01 +0900563 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900564 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900565 EXPECT_TRUE(datapath.NetnsDeleteName("netns_foo"));
566}
567
Garrick Evans8a949dc2019-07-18 16:17:53 +0900568TEST(DatapathTest, AddBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900569 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900570 MockFirewall firewall;
571 Datapath datapath(&runner, &firewall);
Garrick Evans8e8e3472020-01-23 14:03:50 +0900572 EXPECT_CALL(runner, brctl(StrEq("addbr"), ElementsAre("br"), true));
Garrick Evans6f4fa3a2020-02-10 16:15:09 +0900573 EXPECT_CALL(
574 runner,
575 ip(StrEq("addr"), StrEq("add"),
576 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "br"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900577 EXPECT_CALL(runner,
578 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "up"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900579 EXPECT_CALL(runner, iptables(StrEq("mangle"),
580 ElementsAre("-A", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900581 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900582 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900583 datapath.AddBridge("br", Ipv4Addr(1, 1, 1, 1), 30);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900584}
585
Hugo Benichi76675592020-04-08 14:29:57 +0900586TEST(DatapathTest, ConnectVethPair) {
587 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900588 MockFirewall firewall;
Hugo Benichi76675592020-04-08 14:29:57 +0900589 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
590 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900591 "peer_foo", "netns", "netns_foo"),
Hugo Benichi76675592020-04-08 14:29:57 +0900592 true));
593 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
594 ElementsAre("100.115.92.169/30", "brd",
595 "100.115.92.171", "dev", "peer_foo"),
596 true))
597 .WillOnce(Return(0));
598 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
599 ElementsAre("dev", "peer_foo", "up", "addr",
600 "01:02:03:04:05:06", "multicast", "on"),
601 true))
602 .WillOnce(Return(0));
Hugo Benichi76675592020-04-08 14:29:57 +0900603 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
604 ElementsAre("veth_foo", "up"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900605 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900606 EXPECT_TRUE(datapath.ConnectVethPair(kTestPID, "netns_foo", "veth_foo",
607 "peer_foo", {1, 2, 3, 4, 5, 6},
Hugo Benichi76675592020-04-08 14:29:57 +0900608 Ipv4Addr(100, 115, 92, 169), 30, true));
609}
610
Garrick Evans2470caa2020-03-04 14:15:41 +0900611TEST(DatapathTest, AddVirtualInterfacePair) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900612 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900613 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900614 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
615 ElementsAre("veth_foo", "type", "veth", "peer", "name",
Hugo Benichi33860d72020-07-09 16:34:01 +0900616 "peer_foo", "netns", "netns_foo"),
Garrick Evans8e8e3472020-01-23 14:03:50 +0900617 true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900618 Datapath datapath(&runner, &firewall);
Hugo Benichi33860d72020-07-09 16:34:01 +0900619 EXPECT_TRUE(
620 datapath.AddVirtualInterfacePair("netns_foo", "veth_foo", "peer_foo"));
Garrick Evans2470caa2020-03-04 14:15:41 +0900621}
622
623TEST(DatapathTest, ToggleInterface) {
624 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900625 MockFirewall firewall;
Garrick Evans2470caa2020-03-04 14:15:41 +0900626 EXPECT_CALL(runner,
627 ip(StrEq("link"), StrEq("set"), ElementsAre("foo", "up"), true));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900628 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
Garrick Evans2470caa2020-03-04 14:15:41 +0900629 ElementsAre("bar", "down"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900630 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900631 EXPECT_TRUE(datapath.ToggleInterface("foo", true));
632 EXPECT_TRUE(datapath.ToggleInterface("bar", false));
633}
634
635TEST(DatapathTest, ConfigureInterface) {
636 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900637 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900638 EXPECT_CALL(
639 runner,
Garrick Evans2470caa2020-03-04 14:15:41 +0900640 ip(StrEq("addr"), StrEq("add"),
641 ElementsAre("1.1.1.1/30", "brd", "1.1.1.3", "dev", "foo"), true))
642 .WillOnce(Return(0));
643 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
644 ElementsAre("dev", "foo", "up", "addr",
645 "02:02:02:02:02:02", "multicast", "on"),
646 true))
647 .WillOnce(Return(0));
648
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900649 Datapath datapath(&runner, &firewall);
Garrick Evans2470caa2020-03-04 14:15:41 +0900650 MacAddress mac_addr = {2, 2, 2, 2, 2, 2};
651 EXPECT_TRUE(datapath.ConfigureInterface("foo", mac_addr, Ipv4Addr(1, 1, 1, 1),
652 30, true, true));
Garrick Evans54861622019-07-19 09:05:09 +0900653}
654
655TEST(DatapathTest, RemoveInterface) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900656 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900657 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900658 EXPECT_CALL(runner,
659 ip(StrEq("link"), StrEq("delete"), ElementsAre("foo"), false));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900660 Datapath datapath(&runner, &firewall);
Garrick Evans54861622019-07-19 09:05:09 +0900661 datapath.RemoveInterface("foo");
Garrick Evans54861622019-07-19 09:05:09 +0900662}
663
Garrick Evans8a949dc2019-07-18 16:17:53 +0900664TEST(DatapathTest, RemoveBridge) {
Garrick Evans8e8e3472020-01-23 14:03:50 +0900665 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900666 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +0900667 EXPECT_CALL(runner, iptables(StrEq("mangle"),
668 ElementsAre("-D", "PREROUTING", "-i", "br", "-j",
Hugo Benichi6c445322020-08-12 16:46:19 +0900669 "MARK", "--set-mark", "1/1", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +0900670 true, nullptr));
Garrick Evans7a1a9ee2020-01-28 11:03:57 +0900671 EXPECT_CALL(runner,
672 ip(StrEq("link"), StrEq("set"), ElementsAre("br", "down"), true));
Garrick Evans8e8e3472020-01-23 14:03:50 +0900673 EXPECT_CALL(runner, brctl(StrEq("delbr"), ElementsAre("br"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900674 Datapath datapath(&runner, &firewall);
Garrick Evans8a949dc2019-07-18 16:17:53 +0900675 datapath.RemoveBridge("br");
Garrick Evans8a949dc2019-07-18 16:17:53 +0900676}
677
Hugo Benichi321f23b2020-09-25 15:42:05 +0900678TEST(DatapathTest, AddRemoveSourceIPv4DropRule) {
679 MockProcessRunner runner;
680 MockFirewall firewall;
681 EXPECT_CALL(runner,
682 iptables(StrEq("filter"),
683 ElementsAre("-I", "OUTPUT", "-o", "eth+", "-s",
684 "100.115.92.0/24", "-j", "DROP", "-w"),
685 true, nullptr));
686 EXPECT_CALL(runner,
687 iptables(StrEq("filter"),
688 ElementsAre("-D", "OUTPUT", "-o", "eth+", "-s",
689 "100.115.92.0/24", "-j", "DROP", "-w"),
690 true, nullptr));
691 Datapath datapath(&runner, &firewall);
692 datapath.AddSourceIPv4DropRule("eth+", "100.115.92.0/24");
693 datapath.RemoveSourceIPv4DropRule("eth+", "100.115.92.0/24");
694}
695
Hugo Benichi7c342672020-09-08 09:18:14 +0900696TEST(DatapathTest, StartRoutingNamespace) {
697 MockProcessRunner runner;
698 MockFirewall firewall;
699 MacAddress mac = {1, 2, 3, 4, 5, 6};
700
701 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), false));
702 EXPECT_CALL(runner, ip_netns_attach(StrEq("netns_foo"), kTestPID, true));
703 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("add"),
704 ElementsAre("arc_ns0", "type", "veth", "peer", "name",
705 "veth0", "netns", "netns_foo"),
706 true));
707 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
708 ElementsAre("100.115.92.130/30", "brd",
709 "100.115.92.131", "dev", "veth0"),
710 true))
711 .WillOnce(Return(0));
712 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
713 ElementsAre("dev", "veth0", "up", "addr",
714 "01:02:03:04:05:06", "multicast", "off"),
715 true))
716 .WillOnce(Return(0));
717 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
718 ElementsAre("arc_ns0", "up"), true));
719 EXPECT_CALL(runner, ip(StrEq("addr"), StrEq("add"),
720 ElementsAre("100.115.92.129/30", "brd",
721 "100.115.92.131", "dev", "arc_ns0"),
722 true))
723 .WillOnce(Return(0));
724 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("set"),
725 ElementsAre("dev", "arc_ns0", "up", "addr",
726 "01:02:03:04:05:06", "multicast", "off"),
727 true))
728 .WillOnce(Return(0));
729 EXPECT_CALL(runner, iptables(StrEq("filter"),
730 ElementsAre("-A", "FORWARD", "-o", "arc_ns0",
731 "-j", "ACCEPT", "-w"),
732 true, nullptr));
733 EXPECT_CALL(runner,
734 iptables(StrEq("mangle"),
735 ElementsAre("-A", "PREROUTING", "-i", "arc_ns0", "-j",
736 "MARK", "--set-mark", "1/1", "-w"),
737 true, nullptr));
738
739 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
740 datapath.StartRoutingNamespace(
741 kTestPID, "netns_foo", "arc_ns0", "veth0", Ipv4Addr(100, 115, 92, 128),
742 30, Ipv4Addr(100, 115, 92, 129), Ipv4Addr(100, 115, 92, 130), mac);
743 ioctl_reqs.clear();
744 ioctl_rtentry_args.clear();
745}
746
747TEST(DatapathTest, StopRoutingNamespace) {
748 MockProcessRunner runner;
749 MockFirewall firewall;
750
751 EXPECT_CALL(runner, iptables(StrEq("filter"),
752 ElementsAre("-D", "FORWARD", "-o", "arc_ns0",
753 "-j", "ACCEPT", "-w"),
754 true, nullptr));
755 EXPECT_CALL(runner,
756 iptables(StrEq("mangle"),
757 ElementsAre("-D", "PREROUTING", "-i", "arc_ns0", "-j",
758 "MARK", "--set-mark", "1/1", "-w"),
759 true, nullptr));
760 EXPECT_CALL(runner, ip_netns_delete(StrEq("netns_foo"), true));
761 EXPECT_CALL(runner, ip(StrEq("link"), StrEq("delete"), ElementsAre("arc_ns0"),
762 false));
763
764 Datapath datapath(&runner, &firewall);
765 datapath.StopRoutingNamespace("netns_foo", "arc_ns0",
766 Ipv4Addr(100, 115, 92, 128), 30,
767 Ipv4Addr(100, 115, 92, 129));
768}
769
Hugo Benichi8d622b52020-08-13 15:24:12 +0900770TEST(DatapathTest, StartRoutingDevice_Arc) {
771 MockProcessRunner runner;
772 MockFirewall firewall;
773 EXPECT_CALL(runner, iptables(StrEq("nat"),
774 ElementsAre("-A", "PREROUTING", "-i", "eth0",
775 "-m", "socket", "--nowildcard", "-j",
776 "ACCEPT", "-w"),
777 true, nullptr));
778 EXPECT_CALL(runner, iptables(StrEq("nat"),
779 ElementsAre("-A", "PREROUTING", "-i", "eth0",
780 "-p", "tcp", "-j", "DNAT",
781 "--to-destination", "1.2.3.4", "-w"),
782 true, nullptr));
783 EXPECT_CALL(runner, iptables(StrEq("nat"),
784 ElementsAre("-A", "PREROUTING", "-i", "eth0",
785 "-p", "udp", "-j", "DNAT",
786 "--to-destination", "1.2.3.4", "-w"),
787 true, nullptr));
788 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900789 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
790 "arc_eth0", "-j", "ACCEPT", "-w"),
791 true, nullptr));
792 EXPECT_CALL(runner, iptables(StrEq("filter"),
793 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
794 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900795 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900796 EXPECT_CALL(runner, iptables(StrEq("mangle"),
797 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
798 "-j", "MARK", "--set-mark",
799 "0x00002000/0x00003f00", "-w"),
800 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900801 EXPECT_CALL(runner, iptables(StrEq("mangle"),
802 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0",
803 "-j", "MARK", "--set-mark",
804 "0x03ea0000/0xffff0000", "-w"),
805 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900806 EXPECT_CALL(
807 runner,
808 ip6tables(StrEq("mangle"),
809 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
810 "--set-mark", "0x00002000/0x00003f00", "-w"),
811 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900812 EXPECT_CALL(
813 runner,
814 ip6tables(StrEq("mangle"),
815 ElementsAre("-A", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
816 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
817 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900818
819 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900820 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900821 datapath.StartRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
822 TrafficSource::ARC);
823}
824
825TEST(DatapathTest, StartRoutingDevice_CrosVM) {
826 MockProcessRunner runner;
827 MockFirewall firewall;
828 EXPECT_CALL(runner, iptables(StrEq("filter"),
829 ElementsAre("-A", "FORWARD", "-o", "vmtap0",
830 "-j", "ACCEPT", "-w"),
831 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900832 EXPECT_CALL(runner, iptables(StrEq("filter"),
833 ElementsAre("-A", "FORWARD", "-i", "vmtap0",
834 "-j", "ACCEPT", "-w"),
835 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900836 EXPECT_CALL(runner, iptables(StrEq("mangle"),
837 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
838 "-j", "MARK", "--set-mark",
839 "0x00002100/0x00003f00", "-w"),
840 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900841 EXPECT_CALL(runner, iptables(StrEq("mangle"),
842 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
843 "-j", "CONNMARK", "--restore-mark",
844 "--mask", "0xffff0000", "-w"),
845 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900846 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
847 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
848 "-j", "MARK", "--set-mark",
849 "0x00002100/0x00003f00", "-w"),
850 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900851 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
852 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
853 "-j", "CONNMARK", "--restore-mark",
854 "--mask", "0xffff0000", "-w"),
855 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900856 EXPECT_CALL(runner, iptables(StrEq("mangle"),
857 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
858 "-j", "apply_vpn_mark", "-w"),
859 true, nullptr));
860 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
861 ElementsAre("-A", "PREROUTING", "-i", "vmtap0",
862 "-j", "apply_vpn_mark", "-w"),
863 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900864
865 Datapath datapath(&runner, &firewall);
866 datapath.StartRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
867 TrafficSource::CROSVM);
868}
869
870TEST(DatapathTest, StopRoutingDevice_Arc) {
871 MockProcessRunner runner;
872 MockFirewall firewall;
873 EXPECT_CALL(runner, iptables(StrEq("nat"),
874 ElementsAre("-D", "PREROUTING", "-i", "eth0",
875 "-m", "socket", "--nowildcard", "-j",
876 "ACCEPT", "-w"),
877 true, nullptr));
878 EXPECT_CALL(runner, iptables(StrEq("nat"),
879 ElementsAre("-D", "PREROUTING", "-i", "eth0",
880 "-p", "tcp", "-j", "DNAT",
881 "--to-destination", "1.2.3.4", "-w"),
882 true, nullptr));
883 EXPECT_CALL(runner, iptables(StrEq("nat"),
884 ElementsAre("-D", "PREROUTING", "-i", "eth0",
885 "-p", "udp", "-j", "DNAT",
886 "--to-destination", "1.2.3.4", "-w"),
887 true, nullptr));
888 EXPECT_CALL(runner, iptables(StrEq("filter"),
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900889 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
890 "arc_eth0", "-j", "ACCEPT", "-w"),
891 true, nullptr));
892 EXPECT_CALL(runner, iptables(StrEq("filter"),
893 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
894 "-o", "eth0", "-j", "ACCEPT", "-w"),
Hugo Benichi8d622b52020-08-13 15:24:12 +0900895 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900896 EXPECT_CALL(runner, iptables(StrEq("mangle"),
897 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
898 "-j", "MARK", "--set-mark",
899 "0x00002000/0x00003f00", "-w"),
900 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900901 EXPECT_CALL(runner, iptables(StrEq("mangle"),
902 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0",
903 "-j", "MARK", "--set-mark",
904 "0x03ea0000/0xffff0000", "-w"),
905 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900906 EXPECT_CALL(
907 runner,
908 ip6tables(StrEq("mangle"),
909 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
910 "--set-mark", "0x00002000/0x00003f00", "-w"),
911 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900912 EXPECT_CALL(
913 runner,
914 ip6tables(StrEq("mangle"),
915 ElementsAre("-D", "PREROUTING", "-i", "arc_eth0", "-j", "MARK",
916 "--set-mark", "0x03ea0000/0xffff0000", "-w"),
917 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900918
919 Datapath datapath(&runner, &firewall);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900920 datapath.SetIfnameIndex("eth0", 2);
Hugo Benichi8d622b52020-08-13 15:24:12 +0900921 datapath.StopRoutingDevice("eth0", "arc_eth0", Ipv4Addr(1, 2, 3, 4),
922 TrafficSource::ARC);
923}
924
925TEST(DatapathTest, StopRoutingDevice_CrosVM) {
926 MockProcessRunner runner;
927 MockFirewall firewall;
928 EXPECT_CALL(runner, iptables(StrEq("filter"),
929 ElementsAre("-D", "FORWARD", "-o", "vmtap0",
930 "-j", "ACCEPT", "-w"),
931 true, nullptr));
Hugo Benichic6ae67c2020-08-14 15:02:13 +0900932 EXPECT_CALL(runner, iptables(StrEq("filter"),
933 ElementsAre("-D", "FORWARD", "-i", "vmtap0",
934 "-j", "ACCEPT", "-w"),
935 true, nullptr));
Hugo Benichi9be19b12020-08-14 15:33:40 +0900936 EXPECT_CALL(runner, iptables(StrEq("mangle"),
937 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
938 "-j", "MARK", "--set-mark",
939 "0x00002100/0x00003f00", "-w"),
940 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900941 EXPECT_CALL(runner, iptables(StrEq("mangle"),
942 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
943 "-j", "CONNMARK", "--restore-mark",
944 "--mask", "0xffff0000", "-w"),
945 true, nullptr));
Hugo Benichi5c9c11c2020-09-15 17:25:26 +0900946 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
947 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
948 "-j", "MARK", "--set-mark",
949 "0x00002100/0x00003f00", "-w"),
950 true, nullptr));
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900951 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
952 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
953 "-j", "CONNMARK", "--restore-mark",
954 "--mask", "0xffff0000", "-w"),
955 true, nullptr));
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900956 EXPECT_CALL(runner, iptables(StrEq("mangle"),
957 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
958 "-j", "apply_vpn_mark", "-w"),
959 true, nullptr));
960 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
961 ElementsAre("-D", "PREROUTING", "-i", "vmtap0",
962 "-j", "apply_vpn_mark", "-w"),
963 true, nullptr));
Hugo Benichi8d622b52020-08-13 15:24:12 +0900964
965 Datapath datapath(&runner, &firewall);
966 datapath.StopRoutingDevice("", "vmtap0", Ipv4Addr(1, 2, 3, 4),
967 TrafficSource::CROSVM);
968}
969
Hugo Benichid82d8832020-08-14 10:05:03 +0900970TEST(DatapathTest, StartStopIpForwarding) {
971 struct {
972 IpFamily family;
973 std::string iif;
974 std::string oif;
975 std::vector<std::string> start_args;
976 std::vector<std::string> stop_args;
977 bool result;
978 } testcases[] = {
979 {IpFamily::IPv4, "", "", {}, {}, false},
980 {IpFamily::NONE, "foo", "bar", {}, {}, false},
981 {IpFamily::IPv4,
982 "foo",
983 "bar",
984 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
985 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
986 true},
987 {IpFamily::IPv4,
988 "",
989 "bar",
990 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
991 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
992 true},
993 {IpFamily::IPv4,
994 "foo",
995 "",
996 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
997 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
998 true},
999 {IpFamily::IPv6,
1000 "foo",
1001 "bar",
1002 {"-A", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1003 {"-D", "FORWARD", "-i", "foo", "-o", "bar", "-j", "ACCEPT", "-w"},
1004 true},
1005 {IpFamily::IPv6,
1006 "",
1007 "bar",
1008 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1009 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1010 true},
1011 {IpFamily::IPv6,
1012 "foo",
1013 "",
1014 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1015 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1016 true},
1017 {IpFamily::Dual,
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::Dual,
1024 "",
1025 "bar",
1026 {"-A", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1027 {"-D", "FORWARD", "-o", "bar", "-j", "ACCEPT", "-w"},
1028 true},
1029 {IpFamily::Dual,
1030 "foo",
1031 "",
1032 {"-A", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1033 {"-D", "FORWARD", "-i", "foo", "-j", "ACCEPT", "-w"},
1034 true},
1035 };
1036
1037 for (const auto& tt : testcases) {
1038 MockProcessRunner runner;
1039 MockFirewall firewall;
1040 if (tt.result) {
1041 if (tt.family & IpFamily::IPv4) {
1042 EXPECT_CALL(runner,
1043 iptables(StrEq("filter"), tt.start_args, true, nullptr))
1044 .WillOnce(Return(0));
1045 EXPECT_CALL(runner,
1046 iptables(StrEq("filter"), tt.stop_args, true, nullptr))
1047 .WillOnce(Return(0));
1048 }
1049 if (tt.family & IpFamily::IPv6) {
1050 EXPECT_CALL(runner,
1051 ip6tables(StrEq("filter"), tt.start_args, true, nullptr))
1052 .WillOnce(Return(0));
1053 EXPECT_CALL(runner,
1054 ip6tables(StrEq("filter"), tt.stop_args, true, nullptr))
1055 .WillOnce(Return(0));
1056 }
1057 }
1058 Datapath datapath(&runner, &firewall);
1059
1060 EXPECT_EQ(tt.result, datapath.StartIpForwarding(tt.family, tt.iif, tt.oif));
1061 EXPECT_EQ(tt.result, datapath.StopIpForwarding(tt.family, tt.iif, tt.oif));
1062 }
1063}
1064
Hugo Benichi76be34a2020-08-26 22:35:54 +09001065TEST(DatapathTest, StartStopConnectionPinning) {
1066 MockProcessRunner runner;
1067 MockFirewall firewall;
1068 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1069 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1070 "-j", "CONNMARK", "--set-mark",
1071 "0x03eb0000/0xffff0000", "-w"),
1072 true, nullptr));
1073 EXPECT_CALL(runner, iptables(StrEq("mangle"),
1074 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1075 "-j", "CONNMARK", "--set-mark",
1076 "0x03eb0000/0xffff0000", "-w"),
1077 true, nullptr));
1078 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1079 ElementsAre("-A", "POSTROUTING", "-o", "eth0",
1080 "-j", "CONNMARK", "--set-mark",
1081 "0x03eb0000/0xffff0000", "-w"),
1082 true, nullptr));
1083 EXPECT_CALL(runner, ip6tables(StrEq("mangle"),
1084 ElementsAre("-D", "POSTROUTING", "-o", "eth0",
1085 "-j", "CONNMARK", "--set-mark",
1086 "0x03eb0000/0xffff0000", "-w"),
1087 true, nullptr));
1088 Datapath datapath(&runner, &firewall);
1089 datapath.SetIfnameIndex("eth0", 3);
1090 datapath.StartConnectionPinning("eth0");
1091 datapath.StopConnectionPinning("eth0");
1092}
1093
Garrick Evansf0ab7132019-06-18 14:50:42 +09001094TEST(DatapathTest, AddInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001095 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001096 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001097 EXPECT_CALL(runner, iptables(StrEq("nat"),
1098 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1099 "-m", "socket", "--nowildcard", "-j",
1100 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001101 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001102 EXPECT_CALL(runner, iptables(StrEq("nat"),
1103 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1104 "-p", "tcp", "-j", "DNAT",
1105 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001106 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001107 EXPECT_CALL(runner, iptables(StrEq("nat"),
1108 ElementsAre("-A", "PREROUTING", "-i", "eth0",
1109 "-p", "udp", "-j", "DNAT",
1110 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001111 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001112 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001113 datapath.AddInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001114}
1115
1116TEST(DatapathTest, RemoveInboundIPv4DNAT) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001117 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001118 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001119 EXPECT_CALL(runner, iptables(StrEq("nat"),
1120 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1121 "-m", "socket", "--nowildcard", "-j",
1122 "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001123 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001124 EXPECT_CALL(runner, iptables(StrEq("nat"),
1125 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1126 "-p", "tcp", "-j", "DNAT",
1127 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001128 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001129 EXPECT_CALL(runner, iptables(StrEq("nat"),
1130 ElementsAre("-D", "PREROUTING", "-i", "eth0",
1131 "-p", "udp", "-j", "DNAT",
1132 "--to-destination", "1.2.3.4", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001133 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001134 Datapath datapath(&runner, &firewall);
Garrick Evansf0ab7132019-06-18 14:50:42 +09001135 datapath.RemoveInboundIPv4DNAT("eth0", "1.2.3.4");
Garrick Evansf0ab7132019-06-18 14:50:42 +09001136}
1137
Garrick Evans664a82f2019-12-17 12:18:05 +09001138TEST(DatapathTest, MaskInterfaceFlags) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001139 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001140 MockFirewall firewall;
1141 Datapath datapath(&runner, &firewall, ioctl_req_cap);
Hugo Benichi7c342672020-09-08 09:18:14 +09001142
Garrick Evans664a82f2019-12-17 12:18:05 +09001143 bool result = datapath.MaskInterfaceFlags("foo0", IFF_DEBUG);
Taoyu Li90c13912019-11-26 17:56:54 +09001144 EXPECT_TRUE(result);
Hugo Benichie8758b52020-04-03 14:49:01 +09001145 std::vector<ioctl_req_t> expected = {SIOCGIFFLAGS, SIOCSIFFLAGS};
Taoyu Li90c13912019-11-26 17:56:54 +09001146 EXPECT_EQ(ioctl_reqs, expected);
1147 ioctl_reqs.clear();
Hugo Benichi7c342672020-09-08 09:18:14 +09001148 ioctl_rtentry_args.clear();
Taoyu Li90c13912019-11-26 17:56:54 +09001149}
1150
1151TEST(DatapathTest, AddIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001152 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001153 MockFirewall firewall;
Taoyu Lica49c832019-12-06 17:56:43 +09001154 // Return 1 on iptables -C to simulate rule not existing case
Garrick Evans8e8e3472020-01-23 14:03:50 +09001155 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1156 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1157 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001158 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001159 .WillOnce(Return(1));
1160 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1161 ElementsAre("-A", "FORWARD", "-i", "eth0", "-o",
1162 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001163 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001164 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1165 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1166 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001167 false, nullptr))
Garrick Evans8e8e3472020-01-23 14:03:50 +09001168 .WillOnce(Return(1));
1169 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1170 ElementsAre("-A", "FORWARD", "-i", "arc_eth0",
1171 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001172 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001173 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001174 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001175}
1176
Taoyu Lica49c832019-12-06 17:56:43 +09001177TEST(DatapathTest, AddIPv6ForwardingRuleExists) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001178 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001179 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001180 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1181 ElementsAre("-C", "FORWARD", "-i", "eth0", "-o",
1182 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001183 false, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001184 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1185 ElementsAre("-C", "FORWARD", "-i", "arc_eth0",
1186 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001187 false, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001188 Datapath datapath(&runner, &firewall);
Taoyu Lica49c832019-12-06 17:56:43 +09001189 datapath.AddIPv6Forwarding("eth0", "arc_eth0");
Taoyu Lica49c832019-12-06 17:56:43 +09001190}
1191
Taoyu Li90c13912019-11-26 17:56:54 +09001192TEST(DatapathTest, RemoveIPv6Forwarding) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001193 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001194 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001195 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1196 ElementsAre("-D", "FORWARD", "-i", "eth0", "-o",
1197 "arc_eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001198 true, nullptr));
Garrick Evans8e8e3472020-01-23 14:03:50 +09001199 EXPECT_CALL(runner, ip6tables(StrEq("filter"),
1200 ElementsAre("-D", "FORWARD", "-i", "arc_eth0",
1201 "-o", "eth0", "-j", "ACCEPT", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001202 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001203 Datapath datapath(&runner, &firewall);
Taoyu Li90c13912019-11-26 17:56:54 +09001204 datapath.RemoveIPv6Forwarding("eth0", "arc_eth0");
Taoyu Li90c13912019-11-26 17:56:54 +09001205}
1206
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001207TEST(DatapathTest, AddIPv6HostRoute) {
Garrick Evans8e8e3472020-01-23 14:03:50 +09001208 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001209 MockFirewall firewall;
Garrick Evans8e8e3472020-01-23 14:03:50 +09001210 EXPECT_CALL(runner,
1211 ip6(StrEq("route"), StrEq("replace"),
1212 ElementsAre("2001:da8:e00::1234/128", "dev", "eth0"), true));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001213 Datapath datapath(&runner, &firewall);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001214 datapath.AddIPv6HostRoute("eth0", "2001:da8:e00::1234", 128);
Taoyu Lieb6cc8f2019-12-09 15:53:04 +09001215}
1216
Hugo Benichie8758b52020-04-03 14:49:01 +09001217TEST(DatapathTest, AddIPv4Route) {
1218 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001219 MockFirewall firewall;
1220 Datapath datapath(&runner, &firewall, (ioctl_t)ioctl_rtentry_cap);
Hugo Benichie8758b52020-04-03 14:49:01 +09001221
1222 datapath.AddIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1223 Ipv4Addr(255, 255, 255, 0));
1224 datapath.DeleteIPv4Route(Ipv4Addr(192, 168, 1, 1), Ipv4Addr(100, 115, 93, 0),
1225 Ipv4Addr(255, 255, 255, 0));
1226 datapath.AddIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1227 Ipv4Addr(255, 255, 255, 252));
1228 datapath.DeleteIPv4Route("eth0", Ipv4Addr(100, 115, 92, 8),
1229 Ipv4Addr(255, 255, 255, 252));
1230
1231 std::vector<ioctl_req_t> expected_reqs = {SIOCADDRT, SIOCDELRT, SIOCADDRT,
1232 SIOCDELRT};
1233 EXPECT_EQ(expected_reqs, ioctl_reqs);
Hugo Benichie8758b52020-04-03 14:49:01 +09001234
1235 std::string route1 =
1236 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.93.0}, rt_genmask: "
1237 "{family: AF_INET, port: 0, addr: 255.255.255.0}, rt_gateway: {family: "
1238 "AF_INET, port: 0, addr: 192.168.1.1}, rt_dev: null, rt_flags: RTF_UP | "
1239 "RTF_GATEWAY}";
1240 std::string route2 =
1241 "{rt_dst: {family: AF_INET, port: 0, addr: 100.115.92.8}, rt_genmask: "
1242 "{family: AF_INET, port: 0, addr: 255.255.255.252}, rt_gateway: {unset}, "
1243 "rt_dev: eth0, rt_flags: RTF_UP | RTF_GATEWAY}";
1244 std::vector<std::string> captured_routes;
1245 for (const auto& route : ioctl_rtentry_args) {
1246 std::ostringstream stream;
1247 stream << route.second;
1248 captured_routes.emplace_back(stream.str());
1249 }
Hugo Benichie8758b52020-04-03 14:49:01 +09001250 EXPECT_EQ(route1, captured_routes[0]);
1251 EXPECT_EQ(route1, captured_routes[1]);
1252 EXPECT_EQ(route2, captured_routes[2]);
1253 EXPECT_EQ(route2, captured_routes[3]);
Hugo Benichi7c342672020-09-08 09:18:14 +09001254 ioctl_reqs.clear();
1255 ioctl_rtentry_args.clear();
Hugo Benichie8758b52020-04-03 14:49:01 +09001256}
1257
Garrick Evansd291af62020-05-25 10:39:06 +09001258TEST(DatapathTest, AddSNATMarkRules) {
1259 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001260 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001261 EXPECT_CALL(
1262 runner,
1263 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001264 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001265 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001266 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001267 EXPECT_CALL(runner,
1268 iptables(StrEq("filter"),
1269 ElementsAre("-A", "FORWARD", "-m", "mark", "--mark",
1270 "1/1", "-j", "ACCEPT", "-w"),
1271 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001272 EXPECT_CALL(runner,
1273 iptables(StrEq("nat"),
1274 ElementsAre("-A", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001275 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001276 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001277 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001278 datapath.AddSNATMarkRules();
1279}
1280
1281TEST(DatapathTest, RemoveSNATMarkRules) {
1282 MockProcessRunner runner;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001283 MockFirewall firewall;
Taoyu Li79871c92020-07-02 16:09:39 +09001284 EXPECT_CALL(
1285 runner,
1286 iptables(StrEq("filter"),
Hugo Benichi6c445322020-08-12 16:46:19 +09001287 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark", "1/1", "-m",
Taoyu Li79871c92020-07-02 16:09:39 +09001288 "state", "--state", "INVALID", "-j", "DROP", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001289 true, nullptr));
Hugo Benichi6c445322020-08-12 16:46:19 +09001290 EXPECT_CALL(runner,
1291 iptables(StrEq("filter"),
1292 ElementsAre("-D", "FORWARD", "-m", "mark", "--mark",
1293 "1/1", "-j", "ACCEPT", "-w"),
1294 true, nullptr));
Garrick Evansd291af62020-05-25 10:39:06 +09001295 EXPECT_CALL(runner,
1296 iptables(StrEq("nat"),
1297 ElementsAre("-D", "POSTROUTING", "-m", "mark", "--mark",
Hugo Benichi6c445322020-08-12 16:46:19 +09001298 "1/1", "-j", "MASQUERADE", "-w"),
Jie Jiangcf5ce9c2020-07-14 17:22:03 +09001299 true, nullptr));
Jason Jeremy Imana7273a32020-08-04 11:25:31 +09001300 Datapath datapath(&runner, &firewall);
Garrick Evansd291af62020-05-25 10:39:06 +09001301 datapath.RemoveSNATMarkRules();
1302}
1303
Garrick Evans2f581a02020-05-11 10:43:35 +09001304TEST(DatapathTest, ArcVethHostName) {
1305 EXPECT_EQ("vetheth0", ArcVethHostName("eth0"));
1306 EXPECT_EQ("vethrmnet0", ArcVethHostName("rmnet0"));
1307 EXPECT_EQ("vethrmnet_data0", ArcVethHostName("rmnet_data0"));
1308 EXPECT_EQ("vethifnamsiz_i0", ArcVethHostName("ifnamsiz_ifnam0"));
1309 auto ifname = ArcVethHostName("exceeds_ifnamesiz_checkanyway");
1310 EXPECT_EQ("vethexceeds_ify", ifname);
1311 EXPECT_LT(ifname.length(), IFNAMSIZ);
1312}
1313
Garrick Evans8a067562020-05-11 12:47:30 +09001314TEST(DatapathTest, ArcBridgeName) {
1315 EXPECT_EQ("arc_eth0", ArcBridgeName("eth0"));
1316 EXPECT_EQ("arc_rmnet0", ArcBridgeName("rmnet0"));
1317 EXPECT_EQ("arc_rmnet_data0", ArcBridgeName("rmnet_data0"));
1318 EXPECT_EQ("arc_ifnamsiz_i0", ArcBridgeName("ifnamsiz_ifnam0"));
1319 auto ifname = ArcBridgeName("exceeds_ifnamesiz_checkanyway");
1320 EXPECT_EQ("arc_exceeds_ify", ifname);
1321 EXPECT_LT(ifname.length(), IFNAMSIZ);
1322}
1323
Garrick Evans3388a032020-03-24 11:25:55 +09001324} // namespace patchpanel