summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2019-07-01 21:31:15 -0700
committerJunyu Lai <junyulai@google.com>2019-07-02 09:10:34 +0000
commitcfc15dd03578051f88a40d94dcb42b2597614a1f (patch)
tree3b9df12f00cecbbb81104974cdc583d1cddc3889
parent8f6f89ccd316b5ef8c52e9b235c4338ec54162a5 (diff)
downloadnetd-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.cpp24
-rw-r--r--server/ClatdController.h10
-rw-r--r--server/ClatdControllerTest.cpp36
-rw-r--r--server/Controllers.cpp1
-rw-r--r--server/ControllersTest.cpp2
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"