diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2019-07-01 21:31:15 -0700 |
---|---|---|
committer | Junyu Lai <junyulai@google.com> | 2019-07-02 09:10:34 +0000 |
commit | cfc15dd03578051f88a40d94dcb42b2597614a1f (patch) | |
tree | 3b9df12f00cecbbb81104974cdc583d1cddc3889 | |
parent | 8f6f89ccd316b5ef8c52e9b235c4338ec54162a5 (diff) | |
download | netd-cfc15dd03578051f88a40d94dcb42b2597614a1f.tar.gz |
Drop packets to the clat address.android10-dev
These packets are not needed for 464xlat to function because
clatd reads packets from packet sockets, which run before
iptables, and the TC action also happens before packet sockets.
Their existence complicates data usage accounting, and in
certain situations results in applications receiving duplicate
UDP packets.
Bug: 65674744
Bug: 136193260
Test: atest netd_unit_test
Merged-In: I26bd8a1e7a54dbac86971b4e62f88f46ae5466f1
Change-Id: Iab2a64d8a8a380a2448170c9af5109b969527861
(cherry picked from commit 906da1d1ca4b3c61f2f46359480105f647ba4aa8)
-rw-r--r-- | server/ClatdController.cpp | 24 | ||||
-rw-r--r-- | server/ClatdController.h | 10 | ||||
-rw-r--r-- | server/ClatdControllerTest.cpp | 36 | ||||
-rw-r--r-- | server/Controllers.cpp | 1 | ||||
-rw-r--r-- | server/ControllersTest.cpp | 2 |
5 files changed, 70 insertions, 3 deletions
diff --git a/server/ClatdController.cpp b/server/ClatdController.cpp index d82198b1..5a5566b3 100644 --- a/server/ClatdController.cpp +++ b/server/ClatdController.cpp @@ -36,6 +36,7 @@ #include "android-base/properties.h" #include "android-base/scopeguard.h" +#include "android-base/stringprintf.h" #include "android-base/unique_fd.h" #include "bpf/BpfMap.h" #include "netdbpf/bpf_shared.h" @@ -59,6 +60,7 @@ static const char* kV4AddrString = "192.0.0.4"; static const in_addr kV4Addr = {inet_addr(kV4AddrString)}; static const int kV4AddrLen = 29; +using android::base::StringPrintf; using android::base::unique_fd; using android::bpf::BpfMap; using android::netdutils::DumpWriter; @@ -312,6 +314,18 @@ void ClatdController::maybeStartBpf(const ClatdTracker& tracker) { // success } +void ClatdController::maybeSetIptablesDropRule(bool add, const char* pfx96Str, const char* v6Str) { + if (mClatEbpfMode == ClatEbpfDisabled) return; + + std::string cmd = StringPrintf( + "*raw\n" + "%s %s -s %s/96 -d %s -j DROP\n" + "COMMIT\n", + (add ? "-A" : "-D"), LOCAL_RAW_PREROUTING, pfx96Str, v6Str); + + iptablesRestoreFunction(V6, cmd); +} + void ClatdController::maybeStopBpf(const ClatdTracker& tracker) { if (mClatEbpfMode == ClatEbpfDisabled) return; @@ -502,14 +516,17 @@ int ClatdController::startClatd(const std::string& interface, const std::string& return -res; } - // 11. actually perform vfork/dup2/execve + // 11. If necessary, add the drop rule for iptables. + maybeSetIptablesDropRule(true, tracker.pfx96String, tracker.v6Str); + + // 12. actually perform vfork/dup2/execve res = posix_spawn(&tracker.pid, kClatdPath, &fa, &attr, (char* const*)args, nullptr); if (res) { ALOGE("posix_spawn failed (%s)", strerror(res)); return -res; } - // 12. configure eBPF offload - if possible + // 13. configure eBPF offload - if possible maybeStartBpf(tracker); mClatdTrackers[interface] = tracker; @@ -534,6 +551,8 @@ int ClatdController::stopClatd(const std::string& interface) { kill(tracker->pid, SIGTERM); waitpid(tracker->pid, nullptr, 0); + + maybeSetIptablesDropRule(false, tracker->pfx96String, tracker->v6Str); mClatdTrackers.erase(interface); ALOGD("clatd on %s stopped", interface.c_str()); @@ -593,6 +612,7 @@ void ClatdController::dump(DumpWriter& dw) { } auto ClatdController::isIpv4AddressFreeFunc = isIpv4AddressFree; +auto ClatdController::iptablesRestoreFunction = execIptablesRestore; } // namespace net } // namespace android diff --git a/server/ClatdController.h b/server/ClatdController.h index a00f7133..8648f17e 100644 --- a/server/ClatdController.h +++ b/server/ClatdController.h @@ -52,6 +52,8 @@ class ClatdController { void dump(netdutils::DumpWriter& dw) EXCLUDES(mutex); + static constexpr const char LOCAL_RAW_PREROUTING[] = "clat_raw_PREROUTING"; + private: struct ClatdTracker { pid_t pid = -1; @@ -91,17 +93,25 @@ class ClatdController { ClatEbpfEnabled, // >=4.9 kernel && >=Q api shipping level -- must work }; eClatEbpfMode mClatEbpfMode GUARDED_BY(mutex); + eClatEbpfMode getEbpfMode() EXCLUDES(mutex) { + std::lock_guard guard(mutex); + return mClatEbpfMode; + } + base::unique_fd mNetlinkFd GUARDED_BY(mutex); bpf::BpfMap<ClatIngressKey, ClatIngressValue> mClatIngressMap GUARDED_BY(mutex); void maybeStartBpf(const ClatdTracker& tracker) REQUIRES(mutex); void maybeStopBpf(const ClatdTracker& tracker) REQUIRES(mutex); + void maybeSetIptablesDropRule(bool add, const char* pfx96Str, const char* v6Str) + REQUIRES(mutex); // For testing. friend class ClatdControllerTest; static bool (*isIpv4AddressFreeFunc)(in_addr_t); static bool isIpv4AddressFree(in_addr_t addr); + static int (*iptablesRestoreFunction)(IptablesTarget target, const std::string& commands); }; } // namespace net diff --git a/server/ClatdControllerTest.cpp b/server/ClatdControllerTest.cpp index a4a271ad..e90dd1a9 100644 --- a/server/ClatdControllerTest.cpp +++ b/server/ClatdControllerTest.cpp @@ -31,6 +31,8 @@ extern "C" { } #include "ClatdController.h" +#include "IptablesBaseTest.h" +#include "NetworkController.h" #include "tun_interface.h" static const char kIPv4LocalAddr[] = "192.0.0.4"; @@ -57,11 +59,21 @@ bool only10Free(in_addr_t addr) { return (ntohl(addr) & 0xff) == 10; } -class ClatdControllerTest : public ::testing::Test { +class ClatdControllerTest : public IptablesBaseTest { public: + ClatdControllerTest() : mClatdCtrl(nullptr) { + ClatdController::iptablesRestoreFunction = fakeExecIptablesRestore; + } + void SetUp() { resetIpv4AddressFreeFunc(); } protected: + ClatdController mClatdCtrl; + bool isEbpfDisabled() { return mClatdCtrl.getEbpfMode() == ClatdController::ClatEbpfDisabled; } + void maybeSetIptablesDropRule(bool a, const char* b, const char* c) { + std::lock_guard guard(mClatdCtrl.mutex); + return mClatdCtrl.maybeSetIptablesDropRule(a, b, c); + } void setIpv4AddressFreeFunc(bool (*func)(in_addr_t)) { ClatdController::isIpv4AddressFreeFunc = func; } @@ -175,5 +187,27 @@ TEST_F(ClatdControllerTest, MakeChecksumNeutral) { EXPECT_GE(3210000, onebits); } +TEST_F(ClatdControllerTest, AddRemoveIptablesRule) { + if (isEbpfDisabled()) return; + + ExpectedIptablesCommands expected = { + {V6, + "*raw\n" + "-A clat_raw_PREROUTING -s 64:ff9b::/96 -d 2001:db8::1:2:3:4 -j DROP\n" + "COMMIT\n"}, + }; + maybeSetIptablesDropRule(true, "64:ff9b::", "2001:db8::1:2:3:4"); + expectIptablesRestoreCommands(expected); + + expected = { + {V6, + "*raw\n" + "-D clat_raw_PREROUTING -s 64:ff9b::/96 -d 2001:db8::a:b:c:d -j DROP\n" + "COMMIT\n"}, + }; + maybeSetIptablesDropRule(false, "64:ff9b::", "2001:db8::a:b:c:d"); + expectIptablesRestoreCommands(expected); +} + } // namespace net } // namespace android diff --git a/server/Controllers.cpp b/server/Controllers.cpp index 01eae773..c941a804 100644 --- a/server/Controllers.cpp +++ b/server/Controllers.cpp @@ -73,6 +73,7 @@ static const std::vector<const char*> FILTER_OUTPUT = { }; static const std::vector<const char*> RAW_PREROUTING = { + ClatdController::LOCAL_RAW_PREROUTING, BandwidthController::LOCAL_RAW_PREROUTING, IdletimerController::LOCAL_RAW_PREROUTING, TetherController::LOCAL_RAW_PREROUTING, diff --git a/server/ControllersTest.cpp b/server/ControllersTest.cpp index cc8b1aaa..ebaa38f6 100644 --- a/server/ControllersTest.cpp +++ b/server/ControllersTest.cpp @@ -96,6 +96,8 @@ TEST_F(ControllersTest, TestInitIptablesRules) { "*raw\n" ":PREROUTING -\n" "-F PREROUTING\n" + ":clat_raw_PREROUTING -\n" + "-A PREROUTING -j clat_raw_PREROUTING\n" ":bw_raw_PREROUTING -\n" "-A PREROUTING -j bw_raw_PREROUTING\n" ":idletimer_raw_PREROUTING -\n" |