Snap for 6405781 from 00e662588990034e7d08cedd79b65097fe19c8de to sdk-release
Change-Id: I1eace4f2c37720a0ee84bde7d4b570afd8fe95dd
diff --git a/Android.bp b/Android.bp
index 44f3f03..d4afc1e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,6 +1,10 @@
cc_library_headers {
name: "libnetd_client_headers",
export_include_dirs: ["include"],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.resolv",
+ ],
}
cc_defaults {
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index 9b475b1..7d33e46 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -146,8 +146,9 @@
return do_forward(skb, true);
}
-SEC("schedcls/ingress/tether_rawip")
-int sched_cls_ingress_tether_rawip(struct __sk_buff* skb) {
+DEFINE_BPF_PROG_KVER("schedcls/ingress/tether_rawip", AID_ROOT, AID_ROOT,
+ sched_cls_ingress_tether_rawip, KVER(4, 14, 0))
+(struct __sk_buff* skb) {
return do_forward(skb, false);
}
diff --git a/client/NetdClient.cpp b/client/NetdClient.cpp
index 147e63e..643188b 100644
--- a/client/NetdClient.cpp
+++ b/client/NetdClient.cpp
@@ -195,7 +195,7 @@
}
int netdClientSendmmsg(int sockfd, const mmsghdr* msgs, unsigned int msgcount, int flags) {
- if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED)) {
+ if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
const sockaddr* addr = nullptr;
if ((msgcount > 0) && (msgs != nullptr) && (msgs[0].msg_hdr.msg_name != nullptr)) {
addr = reinterpret_cast<const sockaddr*>(msgs[0].msg_hdr.msg_name);
@@ -210,7 +210,7 @@
}
ssize_t netdClientSendmsg(int sockfd, const msghdr* msg, unsigned int flags) {
- if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED)) {
+ if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
const sockaddr* addr = nullptr;
if ((msg != nullptr) && (msg->msg_name != nullptr)) {
addr = reinterpret_cast<const sockaddr*>(msg->msg_name);
@@ -226,7 +226,7 @@
int netdClientSendto(int sockfd, const void* buf, size_t bufsize, int flags, const sockaddr* addr,
socklen_t addrlen) {
- if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED)) {
+ if (propertyValueIsTrue(PROPERTY_REDIRECT_SOCKET_CALLS_HOOKED) && !checkSocket(sockfd)) {
if ((addr != nullptr) && (FwmarkCommand::isSupportedFamily(addr->sa_family))) {
FwmarkConnectInfo sendtoInfo(0, 0, addr);
FwmarkCommand command = {FwmarkCommand::ON_SENDTO, 0, 0, 0};
@@ -382,19 +382,17 @@
} // namespace
-#define CHECK_SOCKET_IS_MARKABLE(sock) \
- do { \
- int err; \
- if ((err = checkSocket(sock)) != 0) { \
- return err; \
- } \
- } while (false);
+#define CHECK_SOCKET_IS_MARKABLE(sock) \
+ do { \
+ int err = checkSocket(sock); \
+ if (err) return err; \
+ } while (false)
#define HOOK_ON_FUNC(remoteFunc, nativeFunc, localFunc) \
do { \
- if (remoteFunc && *remoteFunc) { \
- nativeFunc = *remoteFunc; \
- *remoteFunc = localFunc; \
+ if ((remoteFunc) && *(remoteFunc)) { \
+ (nativeFunc) = *(remoteFunc); \
+ *(remoteFunc) = (localFunc); \
} \
} while (false)
@@ -476,9 +474,7 @@
}
extern "C" int protectFromVpn(int socketFd) {
- if (socketFd < 0) {
- return -EBADF;
- }
+ CHECK_SOCKET_IS_MARKABLE(socketFd);
FwmarkCommand command = {FwmarkCommand::PROTECT_FROM_VPN, 0, 0, 0};
return FwmarkClient().send(&command, socketFd, nullptr);
}
diff --git a/client/NetdClientTest.cpp b/client/NetdClientTest.cpp
index b523ccc..126c7fd 100644
--- a/client/NetdClientTest.cpp
+++ b/client/NetdClientTest.cpp
@@ -74,3 +74,21 @@
unsigned* testNull = nullptr;
EXPECT_EQ(-EFAULT, getNetworkForDns(testNull));
}
+
+TEST(NetdClientTest, protectFromVpnBadFd) {
+ EXPECT_EQ(-EBADF, protectFromVpn(-1));
+}
+
+TEST(NetdClientTest, protectFromVpnUnixStream) {
+ int s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ ASSERT_GE(s, 3);
+ EXPECT_EQ(-EAFNOSUPPORT, protectFromVpn(s));
+ close(s);
+}
+
+TEST(NetdClientTest, protectFromVpnTcp6) {
+ int s = socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ ASSERT_GE(s, 3);
+ EXPECT_EQ(0, protectFromVpn(s));
+ close(s);
+}
diff --git a/libnetdutils/Android.bp b/libnetdutils/Android.bp
index c124aa7..fc9b724 100644
--- a/libnetdutils/Android.bp
+++ b/libnetdutils/Android.bp
@@ -28,6 +28,11 @@
sanitize: {
cfi: true,
},
+
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.resolv",
+ ],
}
cc_test {
diff --git a/libnetdutils/FdTest.cpp b/libnetdutils/FdTest.cpp
index 889c1b7..7080f83 100644
--- a/libnetdutils/FdTest.cpp
+++ b/libnetdutils/FdTest.cpp
@@ -102,6 +102,7 @@
UniqueFd u1(kFd);
{
UniqueFd u2(std::move(u1));
+ // NOLINTNEXTLINE bugprone-use-after-move
EXPECT_FALSE(isWellFormed(u1));
EXPECT_TRUE(isWellFormed(u2));
EXPECT_CALL(mSyscalls, close(kFd)).WillOnce(Return(status::ok));
@@ -115,10 +116,12 @@
UniqueFd u1(kFd);
{
UniqueFd u2 = std::move(u1);
+ // NOLINTNEXTLINE bugprone-use-after-move
EXPECT_FALSE(isWellFormed(u1));
EXPECT_TRUE(isWellFormed(u2));
UniqueFd u3;
u3 = std::move(u2);
+ // NOLINTNEXTLINE bugprone-use-after-move
EXPECT_FALSE(isWellFormed(u2));
EXPECT_TRUE(isWellFormed(u3));
EXPECT_CALL(mSyscalls, close(kFd)).WillOnce(Return(status::ok));
diff --git a/server/Android.bp b/server/Android.bp
index de94e23..b21b070 100644
--- a/server/Android.bp
+++ b/server/Android.bp
@@ -6,6 +6,14 @@
"binder/android/net/metrics/INetdEventListener.aidl",
],
versions: ["1"],
+ backend: {
+ ndk: {
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.resolv",
+ ],
+ },
+ },
}
// These are used in netd_integration_test
@@ -17,6 +25,7 @@
"InterfaceController.cpp",
"NetlinkCommands.cpp",
"NetlinkListener.cpp",
+ "SockDiag.cpp",
"XfrmController.cpp",
"TrafficController.cpp",
],
@@ -33,6 +42,7 @@
"binder/android/net/MarkMaskParcel.aidl",
"binder/android/net/RouteInfoParcel.aidl",
"binder/android/net/TetherConfigParcel.aidl",
+ "binder/android/net/TetherOffloadRuleParcel.aidl",
"binder/android/net/TetherStatsParcel.aidl",
"binder/android/net/UidRangeParcel.aidl",
],
@@ -40,10 +50,17 @@
cpp: {
gen_log: true,
},
+ java: {
+ apex_available: [
+ "//apex_available:platform", // used from services.net
+ "com.android.bluetooth.updatable",
+ ],
+ },
},
versions: [
"1",
"2",
+ "3",
],
}
@@ -147,7 +164,7 @@
"libselinux",
"libsysutils",
"libutils",
- "netd_aidl_interface-unstable-cpp",
+ "netd_aidl_interface-cpp",
"netd_event_listener_interface-cpp",
"oemnetd_aidl_interface-cpp",
],
@@ -243,7 +260,7 @@
"libnetd_server",
"libnetd_test_tun_interface",
"libqtaguid",
- "netd_aidl_interface-cpp",
+ "netd_aidl_interface-unstable-cpp",
"netd_event_listener_interface-cpp",
],
shared_libs: [
diff --git a/server/NdcDispatcher.cpp b/server/NdcDispatcher.cpp
index 7692a9c..e957db8 100644
--- a/server/NdcDispatcher.cpp
+++ b/server/NdcDispatcher.cpp
@@ -304,7 +304,7 @@
false);
return 0;
}
- int enable = !strncmp(argv[3], "enable", 7);
+ int enable = !strncmp(argv[3], "enable", 6);
Status status = mNetd->interfaceSetIPv6PrivacyExtensions(std::string(argv[2]), enable);
if (status.isOk()) {
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
@@ -321,7 +321,7 @@
return 0;
}
- int enable = !strncmp(argv[3], "enable", 7);
+ int enable = !strncmp(argv[3], "enable", 6);
Status status = mNetd->interfaceSetEnableIPv6(std::string(argv[2]), enable);
if (status.isOk()) {
cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
index fb7f839..b6c0d4e 100644
--- a/server/NetdNativeService.cpp
+++ b/server/NetdNativeService.cpp
@@ -52,6 +52,7 @@
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+using android::net::TetherOffloadRuleParcel;
using android::net::TetherStatsParcel;
using android::net::UidRangeParcel;
using android::netdutils::DumpWriter;
@@ -1247,20 +1248,16 @@
return binder::Status::ok();
}
-binder::Status NetdNativeService::tetherRuleAddDownstreamIpv6(
- int intIfaceIndex, int extIfaceIndex, const std::vector<uint8_t>& ipAddress,
- const std::vector<uint8_t>& srcL2Address, const std::vector<uint8_t>& dstL2Address) {
+binder::Status NetdNativeService::tetherOffloadRuleAdd(const TetherOffloadRuleParcel& rule) {
ENFORCE_NETWORK_STACK_PERMISSIONS();
- return asBinderStatus(gCtls->tetherCtrl.addDownstreamIpv6Rule(
- intIfaceIndex, extIfaceIndex, ipAddress, srcL2Address, dstL2Address));
+ return asBinderStatus(gCtls->tetherCtrl.addOffloadRule(rule));
}
-binder::Status NetdNativeService::tetherRuleRemoveDownstreamIpv6(
- int extIfaceIndex, const std::vector<uint8_t>& ipAddress) {
+binder::Status NetdNativeService::tetherOffloadRuleRemove(const TetherOffloadRuleParcel& rule) {
ENFORCE_NETWORK_STACK_PERMISSIONS();
- return asBinderStatus(gCtls->tetherCtrl.removeDownstreamIpv6Rule(extIfaceIndex, ipAddress));
+ return asBinderStatus(gCtls->tetherCtrl.removeOffloadRule(rule));
}
} // namespace net
diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h
index 0c241d7..0d95c8e 100644
--- a/server/NetdNativeService.h
+++ b/server/NetdNativeService.h
@@ -136,12 +136,9 @@
const std::string& extIface) override;
binder::Status tetherRemoveForward(const std::string& intIface,
const std::string& extIface) override;
- binder::Status tetherRuleAddDownstreamIpv6(int intIfaceIndex, int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress,
- const std::vector<uint8_t>& srcL2Address,
- const std::vector<uint8_t>& dstL2Address) override;
- binder::Status tetherRuleRemoveDownstreamIpv6(int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress) override;
+ binder::Status tetherOffloadRuleAdd(const android::net::TetherOffloadRuleParcel& rule) override;
+ binder::Status tetherOffloadRuleRemove(
+ const android::net::TetherOffloadRuleParcel& rule) override;
// Interface-related commands.
binder::Status interfaceAddAddress(const std::string &ifName,
diff --git a/server/NetlinkManager.cpp b/server/NetlinkManager.cpp
index d014443..e3c1db9 100644
--- a/server/NetlinkManager.cpp
+++ b/server/NetlinkManager.cpp
@@ -17,6 +17,7 @@
#include <errno.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
diff --git a/server/OffloadUtils.cpp b/server/OffloadUtils.cpp
index 53665f6..a743458 100644
--- a/server/OffloadUtils.cpp
+++ b/server/OffloadUtils.cpp
@@ -71,6 +71,7 @@
switch (rv) {
case ARPHRD_ETHER:
return true;
+ case ARPHRD_NONE:
case ARPHRD_RAWIP: // in Linux 4.14+ rmnet support was upstreamed and this is 519
case 530: // this is ARPHRD_RAWIP on some Android 4.9 kernels with rmnet
return false;
diff --git a/server/PppController.cpp b/server/PppController.cpp
index 80a36e9..b80e1a6 100644
--- a/server/PppController.cpp
+++ b/server/PppController.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
diff --git a/server/SockDiag.h b/server/SockDiag.h
index af96409..745c09e 100644
--- a/server/SockDiag.h
+++ b/server/SockDiag.h
@@ -34,7 +34,6 @@
struct inet_diag_msg;
struct tcp_info;
-class SockDiagTest;
namespace android {
namespace net {
diff --git a/server/TcpSocketMonitor.cpp b/server/TcpSocketMonitor.cpp
index f4b505d..c18fe92 100644
--- a/server/TcpSocketMonitor.cpp
+++ b/server/TcpSocketMonitor.cpp
@@ -70,9 +70,10 @@
// Helper macro for reading fields into struct tcp_info and handling different struct tcp_info
// versions in the kernel.
-#define TCPINFO_GET(ptr, fld, len, zero) \
- (((ptr) != nullptr && (offsetof(struct tcp_info, fld) + sizeof((ptr)->fld)) < len) ? \
- (ptr)->fld : zero)
+#define TCPINFO_GET(ptr, fld, len, zero) \
+ (((ptr) != nullptr && (offsetof(struct tcp_info, fld) + sizeof((ptr)->fld)) < (len)) \
+ ? (ptr)->fld \
+ : (zero))
static void tcpInfoPrint(DumpWriter &dw, Fwmark mark, const struct inet_diag_msg *sockinfo,
const struct tcp_info *tcpinfo, uint32_t tcpinfoLen) {
diff --git a/server/TetherController.cpp b/server/TetherController.cpp
index cc3b49c..dd8622b 100644
--- a/server/TetherController.cpp
+++ b/server/TetherController.cpp
@@ -55,6 +55,8 @@
#include "Permission.h"
#include "TetherController.h"
+#include "android/net/TetherOffloadRuleParcel.h"
+
namespace android {
namespace net {
@@ -65,6 +67,7 @@
using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::unique_fd;
+using android::net::TetherOffloadRuleParcel;
using android::netdutils::DumpWriter;
using android::netdutils::ScopedIndent;
using android::netdutils::statusFromErrno;
@@ -603,7 +606,8 @@
}
// add this if we are the first enabled nat for this upstream
- if (!isAnyForwardingEnabledOnUpstream(extIface)) {
+ bool firstDownstreamForThisUpstream = !isAnyForwardingEnabledOnUpstream(extIface);
+ if (firstDownstreamForThisUpstream) {
std::vector<std::string> v4Cmds = {
"*nat",
StringPrintf("-A %s -o %s -j MASQUERADE", LOCAL_NAT_POSTROUTING, extIface),
@@ -629,7 +633,7 @@
return -ENODEV;
}
- maybeStartBpf(extIface);
+ if (firstDownstreamForThisUpstream) maybeStartBpf(extIface);
return 0;
}
@@ -813,55 +817,68 @@
}
setForwardRules(false, intIface, extIface);
- if (!isAnyForwardingPairEnabled()) {
- setDefaults();
- }
-
- maybeStopBpf(extIface);
+ if (!isAnyForwardingEnabledOnUpstream(extIface)) maybeStopBpf(extIface);
+ if (!isAnyForwardingPairEnabled()) setDefaults();
return 0;
}
-Result<void> TetherController::addDownstreamIpv6Rule(int intIfaceIndex, int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress,
- const std::vector<uint8_t>& srcL2Address,
- const std::vector<uint8_t>& dstL2Address) {
+namespace {
+Result<void> validateOffloadRule(const TetherOffloadRuleParcel& rule) {
+ struct ethhdr hdr;
+
+ if (rule.inputInterfaceIndex <= 0) {
+ return Error(ENODEV) << "Invalid input interface " << rule.inputInterfaceIndex;
+ }
+ if (rule.outputInterfaceIndex <= 0) {
+ return Error(ENODEV) << "Invalid output interface " << rule.inputInterfaceIndex;
+ }
+ if (rule.prefixLength != 128) {
+ return Error(EINVAL) << "Prefix length must be 128, not " << rule.prefixLength;
+ }
+ if (rule.destination.size() != sizeof(in6_addr)) {
+ return Error(EAFNOSUPPORT) << "Invalid IP address length " << rule.destination.size();
+ }
+ if (rule.srcL2Address.size() != sizeof(hdr.h_source)) {
+ return Error(ENXIO) << "Invalid L2 src address length " << rule.srcL2Address.size();
+ }
+ if (rule.dstL2Address.size() != sizeof(hdr.h_dest)) {
+ return Error(ENXIO) << "Invalid L2 dst address length " << rule.dstL2Address.size();
+ }
+ return Result<void>();
+}
+} // namespace
+
+Result<void> TetherController::addOffloadRule(const TetherOffloadRuleParcel& rule) {
+ Result<void> res = validateOffloadRule(rule);
+ if (!res.ok()) return res;
+
ethhdr hdr = {
.h_proto = htons(ETH_P_IPV6),
};
- if (ipAddress.size() != sizeof(in6_addr)) {
- return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
- }
- if (srcL2Address.size() != sizeof(hdr.h_source)) {
- return Error(EINVAL) << "Invalid L2 src address length " << srcL2Address.size();
- }
- if (dstL2Address.size() != sizeof(hdr.h_dest)) {
- return Error(EINVAL) << "Invalid L2 dst address length " << dstL2Address.size();
- }
- memcpy(&hdr.h_dest, dstL2Address.data(), sizeof(hdr.h_dest));
- memcpy(&hdr.h_source, srcL2Address.data(), sizeof(hdr.h_source));
+ memcpy(&hdr.h_dest, rule.dstL2Address.data(), sizeof(hdr.h_dest));
+ memcpy(&hdr.h_source, rule.srcL2Address.data(), sizeof(hdr.h_source));
+ // Only downstream supported for now.
TetherIngressKey key = {
- .iif = static_cast<uint32_t>(extIfaceIndex),
- .neigh6 = *(const in6_addr*)ipAddress.data(),
+ .iif = static_cast<uint32_t>(rule.inputInterfaceIndex),
+ .neigh6 = *(const in6_addr*)rule.destination.data(),
};
TetherIngressValue value = {
- static_cast<uint32_t>(intIfaceIndex),
+ static_cast<uint32_t>(rule.outputInterfaceIndex),
hdr,
};
return mBpfIngressMap.writeValue(key, value, BPF_ANY);
}
-Result<void> TetherController::removeDownstreamIpv6Rule(int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress) {
- if (ipAddress.size() != sizeof(in6_addr)) {
- return Error(EINVAL) << "Invalid IP address length " << ipAddress.size();
- }
+Result<void> TetherController::removeOffloadRule(const TetherOffloadRuleParcel& rule) {
+ Result<void> res = validateOffloadRule(rule);
+ if (!res.ok()) return res;
TetherIngressKey key = {
- .iif = static_cast<uint32_t>(extIfaceIndex),
- .neigh6 = *(const in6_addr*)ipAddress.data(),
+ .iif = static_cast<uint32_t>(rule.inputInterfaceIndex),
+ .neigh6 = *(const in6_addr*)rule.destination.data(),
};
Result<void> ret = mBpfIngressMap.deleteValue(key);
diff --git a/server/TetherController.h b/server/TetherController.h
index 7835cf6..7fd7166 100644
--- a/server/TetherController.h
+++ b/server/TetherController.h
@@ -30,6 +30,8 @@
#include "bpf/BpfMap.h"
#include "netdbpf/bpf_shared.h"
+#include "android/net/TetherOffloadRuleParcel.h"
+
namespace android {
namespace net {
@@ -103,13 +105,8 @@
int disableNat(const char* intIface, const char* extIface);
int setupIptablesHooks();
- base::Result<void> addDownstreamIpv6Rule(int intIfaceIndex, int extIfaceIndex,
- const std::vector<uint8_t>& ipAddress,
- const std::vector<uint8_t>& srcL2Address,
- const std::vector<uint8_t>& dstL2Address);
-
- base::Result<void> removeDownstreamIpv6Rule(int extifaceIndex,
- const std::vector<uint8_t>& ipAddress);
+ base::Result<void> addOffloadRule(const TetherOffloadRuleParcel& rule);
+ base::Result<void> removeOffloadRule(const TetherOffloadRuleParcel& rule);
class TetherStats {
public:
diff --git a/server/TrafficController.cpp b/server/TrafficController.cpp
index 36ccf53..e2b88a6 100644
--- a/server/TrafficController.cpp
+++ b/server/TrafficController.cpp
@@ -85,12 +85,12 @@
static_assert(STATS_MAP_SIZE - TOTAL_UID_STATS_ENTRIES_LIMIT > 100,
"The limit for stats map is to high, stats data may be lost due to overflow");
-#define FLAG_MSG_TRANS(result, flag, value) \
- do { \
- if (value & flag) { \
- result.append(StringPrintf(" %s", #flag)); \
- value &= ~flag; \
- } \
+#define FLAG_MSG_TRANS(result, flag, value) \
+ do { \
+ if ((value) & (flag)) { \
+ (result).append(" " #flag); \
+ (value) &= ~(flag); \
+ } \
} while (0)
const std::string uidMatchTypeToString(uint8_t match) {
diff --git a/server/aidl_api/netd_aidl_interface/3/.hash b/server/aidl_api/netd_aidl_interface/3/.hash
new file mode 100644
index 0000000..59cf708
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/.hash
@@ -0,0 +1 @@
+e17c1f9b2068b539b22e3a4a447edea3c80aee4b
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/INetd.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/INetd.aidl
new file mode 100644
index 0000000..135b738
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/INetd.aidl
@@ -0,0 +1,161 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetd {
+ boolean isAlive();
+ boolean firewallReplaceUidChain(in @utf8InCpp String chainName, boolean isWhitelist, in int[] uids);
+ boolean bandwidthEnableDataSaver(boolean enable);
+ void networkCreatePhysical(int netId, int permission);
+ void networkCreateVpn(int netId, boolean secure);
+ void networkDestroy(int netId);
+ void networkAddInterface(int netId, in @utf8InCpp String iface);
+ void networkRemoveInterface(int netId, in @utf8InCpp String iface);
+ void networkAddUidRanges(int netId, in android.net.UidRangeParcel[] uidRanges);
+ void networkRemoveUidRanges(int netId, in android.net.UidRangeParcel[] uidRanges);
+ void networkRejectNonSecureVpn(boolean add, in android.net.UidRangeParcel[] uidRanges);
+ void socketDestroy(in android.net.UidRangeParcel[] uidRanges, in int[] exemptUids);
+ boolean tetherApplyDnsInterfaces();
+ android.net.TetherStatsParcel[] tetherGetStats();
+ void interfaceAddAddress(in @utf8InCpp String ifName, in @utf8InCpp String addrString, int prefixLength);
+ void interfaceDelAddress(in @utf8InCpp String ifName, in @utf8InCpp String addrString, int prefixLength);
+ @utf8InCpp String getProcSysNet(int ipversion, int which, in @utf8InCpp String ifname, in @utf8InCpp String parameter);
+ void setProcSysNet(int ipversion, int which, in @utf8InCpp String ifname, in @utf8InCpp String parameter, in @utf8InCpp String value);
+ void ipSecSetEncapSocketOwner(in ParcelFileDescriptor socket, int newUid);
+ int ipSecAllocateSpi(int transformId, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int spi);
+ void ipSecAddSecurityAssociation(int transformId, int mode, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int underlyingNetId, int spi, int markValue, int markMask, in @utf8InCpp String authAlgo, in byte[] authKey, in int authTruncBits, in @utf8InCpp String cryptAlgo, in byte[] cryptKey, in int cryptTruncBits, in @utf8InCpp String aeadAlgo, in byte[] aeadKey, in int aeadIcvBits, int encapType, int encapLocalPort, int encapRemotePort, int interfaceId);
+ void ipSecDeleteSecurityAssociation(int transformId, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int spi, int markValue, int markMask, int interfaceId);
+ void ipSecApplyTransportModeTransform(in ParcelFileDescriptor socket, int transformId, int direction, in @utf8InCpp String sourceAddress, in @utf8InCpp String destinationAddress, int spi);
+ void ipSecRemoveTransportModeTransform(in ParcelFileDescriptor socket);
+ void ipSecAddSecurityPolicy(int transformId, int selAddrFamily, int direction, in @utf8InCpp String tmplSrcAddress, in @utf8InCpp String tmplDstAddress, int spi, int markValue, int markMask, int interfaceId);
+ void ipSecUpdateSecurityPolicy(int transformId, int selAddrFamily, int direction, in @utf8InCpp String tmplSrcAddress, in @utf8InCpp String tmplDstAddress, int spi, int markValue, int markMask, int interfaceId);
+ void ipSecDeleteSecurityPolicy(int transformId, int selAddrFamily, int direction, int markValue, int markMask, int interfaceId);
+ void ipSecAddTunnelInterface(in @utf8InCpp String deviceName, in @utf8InCpp String localAddress, in @utf8InCpp String remoteAddress, int iKey, int oKey, int interfaceId);
+ void ipSecUpdateTunnelInterface(in @utf8InCpp String deviceName, in @utf8InCpp String localAddress, in @utf8InCpp String remoteAddress, int iKey, int oKey, int interfaceId);
+ void ipSecRemoveTunnelInterface(in @utf8InCpp String deviceName);
+ void wakeupAddInterface(in @utf8InCpp String ifName, in @utf8InCpp String prefix, int mark, int mask);
+ void wakeupDelInterface(in @utf8InCpp String ifName, in @utf8InCpp String prefix, int mark, int mask);
+ void setIPv6AddrGenMode(in @utf8InCpp String ifName, int mode);
+ void idletimerAddInterface(in @utf8InCpp String ifName, int timeout, in @utf8InCpp String classLabel);
+ void idletimerRemoveInterface(in @utf8InCpp String ifName, int timeout, in @utf8InCpp String classLabel);
+ void strictUidCleartextPenalty(int uid, int policyPenalty);
+ @utf8InCpp String clatdStart(in @utf8InCpp String ifName, in @utf8InCpp String nat64Prefix);
+ void clatdStop(in @utf8InCpp String ifName);
+ boolean ipfwdEnabled();
+ @utf8InCpp String[] ipfwdGetRequesterList();
+ void ipfwdEnableForwarding(in @utf8InCpp String requester);
+ void ipfwdDisableForwarding(in @utf8InCpp String requester);
+ void ipfwdAddInterfaceForward(in @utf8InCpp String fromIface, in @utf8InCpp String toIface);
+ void ipfwdRemoveInterfaceForward(in @utf8InCpp String fromIface, in @utf8InCpp String toIface);
+ void bandwidthSetInterfaceQuota(in @utf8InCpp String ifName, long bytes);
+ void bandwidthRemoveInterfaceQuota(in @utf8InCpp String ifName);
+ void bandwidthSetInterfaceAlert(in @utf8InCpp String ifName, long bytes);
+ void bandwidthRemoveInterfaceAlert(in @utf8InCpp String ifName);
+ void bandwidthSetGlobalAlert(long bytes);
+ void bandwidthAddNaughtyApp(int uid);
+ void bandwidthRemoveNaughtyApp(int uid);
+ void bandwidthAddNiceApp(int uid);
+ void bandwidthRemoveNiceApp(int uid);
+ void tetherStart(in @utf8InCpp String[] dhcpRanges);
+ void tetherStop();
+ boolean tetherIsEnabled();
+ void tetherInterfaceAdd(in @utf8InCpp String ifName);
+ void tetherInterfaceRemove(in @utf8InCpp String ifName);
+ @utf8InCpp String[] tetherInterfaceList();
+ void tetherDnsSet(int netId, in @utf8InCpp String[] dnsAddrs);
+ @utf8InCpp String[] tetherDnsList();
+ void networkAddRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop);
+ void networkRemoveRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop);
+ void networkAddLegacyRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop, int uid);
+ void networkRemoveLegacyRoute(int netId, in @utf8InCpp String ifName, in @utf8InCpp String destination, in @utf8InCpp String nextHop, int uid);
+ int networkGetDefault();
+ void networkSetDefault(int netId);
+ void networkClearDefault();
+ void networkSetPermissionForNetwork(int netId, int permission);
+ void networkSetPermissionForUser(int permission, in int[] uids);
+ void networkClearPermissionForUser(in int[] uids);
+ void trafficSetNetPermForUids(int permission, in int[] uids);
+ void networkSetProtectAllow(int uid);
+ void networkSetProtectDeny(int uid);
+ boolean networkCanProtect(int uid);
+ void firewallSetFirewallType(int firewalltype);
+ void firewallSetInterfaceRule(in @utf8InCpp String ifName, int firewallRule);
+ void firewallSetUidRule(int childChain, int uid, int firewallRule);
+ void firewallEnableChildChain(int childChain, boolean enable);
+ @utf8InCpp String[] interfaceGetList();
+ android.net.InterfaceConfigurationParcel interfaceGetCfg(in @utf8InCpp String ifName);
+ void interfaceSetCfg(in android.net.InterfaceConfigurationParcel cfg);
+ void interfaceSetIPv6PrivacyExtensions(in @utf8InCpp String ifName, boolean enable);
+ void interfaceClearAddrs(in @utf8InCpp String ifName);
+ void interfaceSetEnableIPv6(in @utf8InCpp String ifName, boolean enable);
+ void interfaceSetMtu(in @utf8InCpp String ifName, int mtu);
+ void tetherAddForward(in @utf8InCpp String intIface, in @utf8InCpp String extIface);
+ void tetherRemoveForward(in @utf8InCpp String intIface, in @utf8InCpp String extIface);
+ void setTcpRWmemorySize(in @utf8InCpp String rmemValues, in @utf8InCpp String wmemValues);
+ void registerUnsolicitedEventListener(android.net.INetdUnsolicitedEventListener listener);
+ void firewallAddUidInterfaceRules(in @utf8InCpp String ifName, in int[] uids);
+ void firewallRemoveUidInterfaceRules(in int[] uids);
+ void trafficSwapActiveStatsMap();
+ IBinder getOemNetd();
+ void tetherStartWithConfiguration(in android.net.TetherConfigParcel config);
+ android.net.MarkMaskParcel getFwmarkForNetwork(int netId);
+ void networkAddRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
+ void networkUpdateRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
+ void networkRemoveRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
+ void tetherOffloadRuleAdd(in android.net.TetherOffloadRuleParcel rule);
+ void tetherOffloadRuleRemove(in android.net.TetherOffloadRuleParcel rule);
+ const int IPV4 = 4;
+ const int IPV6 = 6;
+ const int CONF = 1;
+ const int NEIGH = 2;
+ const String IPSEC_INTERFACE_PREFIX = "ipsec";
+ const int IPV6_ADDR_GEN_MODE_EUI64 = 0;
+ const int IPV6_ADDR_GEN_MODE_NONE = 1;
+ const int IPV6_ADDR_GEN_MODE_STABLE_PRIVACY = 2;
+ const int IPV6_ADDR_GEN_MODE_RANDOM = 3;
+ const int IPV6_ADDR_GEN_MODE_DEFAULT = 0;
+ const int PENALTY_POLICY_ACCEPT = 1;
+ const int PENALTY_POLICY_LOG = 2;
+ const int PENALTY_POLICY_REJECT = 3;
+ const int LOCAL_NET_ID = 99;
+ const String NEXTHOP_NONE = "";
+ const String NEXTHOP_UNREACHABLE = "unreachable";
+ const String NEXTHOP_THROW = "throw";
+ const int PERMISSION_NONE = 0;
+ const int PERMISSION_NETWORK = 1;
+ const int PERMISSION_SYSTEM = 2;
+ const int NO_PERMISSIONS = 0;
+ const int PERMISSION_INTERNET = 4;
+ const int PERMISSION_UPDATE_DEVICE_STATS = 8;
+ const int PERMISSION_UNINSTALLED = -1;
+ const int FIREWALL_WHITELIST = 0;
+ const int FIREWALL_BLACKLIST = 1;
+ const int FIREWALL_RULE_ALLOW = 1;
+ const int FIREWALL_RULE_DENY = 2;
+ const int FIREWALL_CHAIN_NONE = 0;
+ const int FIREWALL_CHAIN_DOZABLE = 1;
+ const int FIREWALL_CHAIN_STANDBY = 2;
+ const int FIREWALL_CHAIN_POWERSAVE = 3;
+ const String IF_STATE_UP = "up";
+ const String IF_STATE_DOWN = "down";
+ const String IF_FLAG_BROADCAST = "broadcast";
+ const String IF_FLAG_LOOPBACK = "loopback";
+ const String IF_FLAG_POINTOPOINT = "point-to-point";
+ const String IF_FLAG_RUNNING = "running";
+ const String IF_FLAG_MULTICAST = "multicast";
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/INetdUnsolicitedEventListener.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/INetdUnsolicitedEventListener.aidl
new file mode 100644
index 0000000..4459363
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/INetdUnsolicitedEventListener.aidl
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+interface INetdUnsolicitedEventListener {
+ oneway void onInterfaceClassActivityChanged(boolean isActive, int timerLabel, long timestampNs, int uid);
+ oneway void onQuotaLimitReached(@utf8InCpp String alertName, @utf8InCpp String ifName);
+ oneway void onInterfaceDnsServerInfo(@utf8InCpp String ifName, long lifetimeS, in @utf8InCpp String[] servers);
+ oneway void onInterfaceAddressUpdated(@utf8InCpp String addr, @utf8InCpp String ifName, int flags, int scope);
+ oneway void onInterfaceAddressRemoved(@utf8InCpp String addr, @utf8InCpp String ifName, int flags, int scope);
+ oneway void onInterfaceAdded(@utf8InCpp String ifName);
+ oneway void onInterfaceRemoved(@utf8InCpp String ifName);
+ oneway void onInterfaceChanged(@utf8InCpp String ifName, boolean up);
+ oneway void onInterfaceLinkStateChanged(@utf8InCpp String ifName, boolean up);
+ oneway void onRouteChanged(boolean updated, @utf8InCpp String route, @utf8InCpp String gateway, @utf8InCpp String ifName);
+ oneway void onStrictCleartextDetected(int uid, @utf8InCpp String hex);
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/InterfaceConfigurationParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/InterfaceConfigurationParcel.aidl
new file mode 100644
index 0000000..01e0f95
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/InterfaceConfigurationParcel.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable InterfaceConfigurationParcel {
+ @utf8InCpp String ifName;
+ @utf8InCpp String hwAddr;
+ @utf8InCpp String ipv4Addr;
+ int prefixLength;
+ @utf8InCpp String[] flags;
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/MarkMaskParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/MarkMaskParcel.aidl
new file mode 100644
index 0000000..62be838
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/MarkMaskParcel.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable MarkMaskParcel {
+ int mark;
+ int mask;
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/RouteInfoParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/RouteInfoParcel.aidl
new file mode 100644
index 0000000..5e0ee62
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/RouteInfoParcel.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable RouteInfoParcel {
+ @utf8InCpp String destination;
+ @utf8InCpp String ifName;
+ @utf8InCpp String nextHop;
+ int mtu;
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/TetherConfigParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/TetherConfigParcel.aidl
new file mode 100644
index 0000000..b136454
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/TetherConfigParcel.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable TetherConfigParcel {
+ boolean usingLegacyDnsProxy;
+ @utf8InCpp String[] dhcpRanges;
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/TetherOffloadRuleParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/TetherOffloadRuleParcel.aidl
new file mode 100644
index 0000000..3abf0f8
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/TetherOffloadRuleParcel.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable TetherOffloadRuleParcel {
+ int inputInterfaceIndex;
+ int outputInterfaceIndex;
+ byte[] destination;
+ int prefixLength;
+ byte[] srcL2Address;
+ byte[] dstL2Address;
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/TetherStatsParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/TetherStatsParcel.aidl
new file mode 100644
index 0000000..71ffb9b
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/TetherStatsParcel.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable TetherStatsParcel {
+ @utf8InCpp String iface;
+ long rxBytes;
+ long rxPackets;
+ long txBytes;
+ long txPackets;
+}
diff --git a/server/aidl_api/netd_aidl_interface/3/android/net/UidRangeParcel.aidl b/server/aidl_api/netd_aidl_interface/3/android/net/UidRangeParcel.aidl
new file mode 100644
index 0000000..84ff457
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/3/android/net/UidRangeParcel.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable UidRangeParcel {
+ int start;
+ int stop;
+}
diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
index 7ba363c..135b738 100644
--- a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
+++ b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
@@ -117,8 +117,8 @@
void networkAddRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
void networkUpdateRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
void networkRemoveRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
- void tetherRuleAddDownstreamIpv6(int intIfaceIndex, int extIfaceIndex, in byte[] ipAddress, in byte[] srcL2Address, in byte[] dstL2Address);
- void tetherRuleRemoveDownstreamIpv6(int extIfaceIndex, in byte[] ipAddress);
+ void tetherOffloadRuleAdd(in android.net.TetherOffloadRuleParcel rule);
+ void tetherOffloadRuleRemove(in android.net.TetherOffloadRuleParcel rule);
const int IPV4 = 4;
const int IPV6 = 6;
const int CONF = 1;
diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/TetherOffloadRuleParcel.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/TetherOffloadRuleParcel.aidl
new file mode 100644
index 0000000..3abf0f8
--- /dev/null
+++ b/server/aidl_api/netd_aidl_interface/current/android/net/TetherOffloadRuleParcel.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
+// edit this file. It looks like you are doing that because you have modified
+// an AIDL interface in a backward-incompatible way, e.g., deleting a function
+// from an interface or a field from a parcelable and it broke the build. That
+// breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+/* @hide */
+parcelable TetherOffloadRuleParcel {
+ int inputInterfaceIndex;
+ int outputInterfaceIndex;
+ byte[] destination;
+ int prefixLength;
+ byte[] srcL2Address;
+ byte[] dstL2Address;
+}
diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
index fa18aea..dff021c 100644
--- a/server/binder/android/net/INetd.aidl
+++ b/server/binder/android/net/INetd.aidl
@@ -21,6 +21,7 @@
import android.net.MarkMaskParcel;
import android.net.RouteInfoParcel;
import android.net.TetherConfigParcel;
+import android.net.TetherOffloadRuleParcel;
import android.net.TetherStatsParcel;
import android.net.UidRangeParcel;
@@ -1245,28 +1246,27 @@
void networkRemoveRouteParcel(int netId, in android.net.RouteInfoParcel routeInfo);
/**
- * Adds or updates a tethering rule to forward downstream IPv6 traffic.
+ * Adds a tethering offload rule, or updates it if it already exists.
*
- * @param intifaceIndex the interface index of the internal interface.
- * @param extifaceIndex the interface index of the external interface.
- * @param ipAddress the IPv6 address as a byte array.
- * @param srcL2Address the source (i.e., local) L2 address as a byte array. Currently, must be a
- * 6-byte MAC address.
- * @param dstL2Address the destination L2 address as a byte array. Currently, must be a 6-byte
- * MAC address.
+ * Currently, only downstream /128 IPv6 entries are supported. An existing rule will be updated
+ * if the input interface and destination prefix match. Otherwise, a new rule will be created.
+ *
+ * @param rule The rule to add or update.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- void tetherRuleAddDownstreamIpv6(int intIfaceIndex, int extIfaceIndex, in byte[] ipAddress,
- in byte[] srcL2Address, in byte[] dstL2Address);
+ void tetherOffloadRuleAdd(in TetherOffloadRuleParcel rule);
/**
- * Removes a tethering rule to forward downstream IPv6 traffic.
+ * Deletes a tethering offload rule.
*
- * @param extifaceIndex the interface index of the external interface.
- * @param ipAddress the IPv6 address as a byte array.
+ * Currently, only downstream /128 IPv6 entries are supported. An existing rule will be deleted
+ * if the destination IP address and the source interface match. It is not an error if there is
+ * no matching rule to delete.
+ *
+ * @param rule The rule to delete.
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- void tetherRuleRemoveDownstreamIpv6(int extIfaceIndex, in byte[] ipAddress);
+ void tetherOffloadRuleRemove(in TetherOffloadRuleParcel rule);
}
diff --git a/server/binder/android/net/TetherOffloadRuleParcel.aidl b/server/binder/android/net/TetherOffloadRuleParcel.aidl
new file mode 100644
index 0000000..5577bfb
--- /dev/null
+++ b/server/binder/android/net/TetherOffloadRuleParcel.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/**
+ * Represents a forwarding rule for tethering offload.
+ *
+ * {@hide}
+ */
+parcelable TetherOffloadRuleParcel {
+ /** The interface index of the input interface. */
+ int inputInterfaceIndex;
+
+ /** The interface index of the output interface. */
+ int outputInterfaceIndex;
+
+ /** The base IP address of the destination prefix as a byte array. */
+ byte[] destination;
+
+ /** The destination prefix length. */
+ int prefixLength;
+
+ /** The source link-layer address. Currently, must be a 6-byte MAC address.*/
+ byte[] srcL2Address;
+
+ /** The destination link-layer address. Currently, must be a 6-byte MAC address. */
+ byte[] dstL2Address;
+}
diff --git a/tests/Android.bp b/tests/Android.bp
index 4734c21..1b8f1f6 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -62,7 +62,7 @@
name: "netd_integration_test",
test_suites: [
"device-tests",
- "vts-core"
+ "vts",
],
require_root: true,
defaults: ["netd_defaults"],
diff --git a/tests/binder_test.cpp b/tests/binder_test.cpp
index 4f6fc07..baea57d 100644
--- a/tests/binder_test.cpp
+++ b/tests/binder_test.cpp
@@ -35,12 +35,14 @@
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
+#include <netinet/tcp.h>
#include <openssl/base64.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <android-base/file.h>
#include <android-base/macros.h>
+#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android/multinetwork.h>
@@ -58,6 +60,7 @@
#include "NetdClient.h"
#include "NetdConstants.h"
#include "NetworkController.h"
+#include "SockDiag.h"
#include "TestUnsolService.h"
#include "XfrmController.h"
#include "android/net/INetd.h"
@@ -84,6 +87,7 @@
using android::String16;
using android::String8;
using android::base::Join;
+using android::base::make_scope_guard;
using android::base::ReadFileToString;
using android::base::StartsWith;
using android::base::StringPrintf;
@@ -93,9 +97,12 @@
using android::net::InterfaceConfigurationParcel;
using android::net::InterfaceController;
using android::net::MarkMaskParcel;
+using android::net::SockDiag;
+using android::net::TetherOffloadRuleParcel;
using android::net::TetherStatsParcel;
using android::net::TunInterface;
using android::net::UidRangeParcel;
+using android::netdutils::IPAddress;
using android::netdutils::ScopedAddrinfo;
using android::netdutils::sSyscalls;
using android::netdutils::Stopwatch;
@@ -104,6 +111,7 @@
static const char* IP_RULE_V6 = "-6";
static const int TEST_NETID1 = 65501;
static const int TEST_NETID2 = 65502;
+static const char* DNSMASQ = "dnsmasq";
// Use maximum reserved appId for applications to avoid conflict with existing
// uids.
@@ -2075,8 +2083,6 @@
TEST_F(BinderTest, TetherStartStopStatus) {
std::vector<std::string> noDhcpRange = {};
- static const char dnsdName[] = "dnsmasq";
-
for (bool usingLegacyDnsProxy : {true, false}) {
android::net::TetherConfigParcel config;
config.usingLegacyDnsProxy = usingLegacyDnsProxy;
@@ -2085,9 +2091,9 @@
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
SCOPED_TRACE(StringPrintf("usingLegacyDnsProxy: %d", usingLegacyDnsProxy));
if (usingLegacyDnsProxy == true) {
- expectProcessExists(dnsdName);
+ expectProcessExists(DNSMASQ);
} else {
- expectProcessDoesNotExist(dnsdName);
+ expectProcessDoesNotExist(DNSMASQ);
}
bool tetherEnabled;
@@ -2097,7 +2103,7 @@
status = mNetd->tetherStop();
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
- expectProcessDoesNotExist(dnsdName);
+ expectProcessDoesNotExist(DNSMASQ);
status = mNetd->tetherIsEnabled(&tetherEnabled);
EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
@@ -2142,6 +2148,135 @@
namespace {
+std::vector<IPAddress> findDnsSockets(SockDiag* sd, unsigned numExpected) {
+ std::vector<IPAddress> listenAddrs;
+
+ // Callback lambda that finds all IPv4 sockets with source port 53.
+ auto findDnsSockets = [&](uint8_t /* proto */, const inet_diag_msg* msg) {
+ // Always return false, which means do not destroy this socket.
+ if (msg->id.idiag_sport != htons(53)) return false;
+ IPAddress addr(*(in_addr*)msg->id.idiag_src);
+ listenAddrs.push_back(addr);
+ return false;
+ };
+
+ // There is no way to know if dnsmasq has finished processing the update_interfaces command and
+ // opened listening sockets. So, just spin a few times and return the first list of sockets
+ // that is at least numExpected long.
+ // Pick a relatively large timeout to avoid flaky tests. Testing suggests that 5 attempts are
+ // sufficient for the test to pass 500 times in a row on crosshatch-eng. Pick 10 to be safe.
+ constexpr int kMaxAttempts = 10;
+ constexpr int kSleepMs = 100;
+ for (int i = 0; i < kMaxAttempts; i++) {
+ listenAddrs.clear();
+ EXPECT_EQ(0, sd->sendDumpRequest(IPPROTO_TCP, AF_INET, 1 << TCP_LISTEN))
+ << "Failed to dump sockets, attempt " << i << " of " << kMaxAttempts;
+ sd->readDiagMsg(IPPROTO_TCP, findDnsSockets);
+ if (listenAddrs.size() >= numExpected) {
+ break;
+ }
+ usleep(kSleepMs * 1000);
+ }
+
+ return listenAddrs;
+}
+
+} // namespace
+
+// Checks that when starting dnsmasq on an interface that no longer exists, it doesn't attempt to
+// start on other interfaces instead.
+TEST_F(BinderTest, TetherDeletedInterface) {
+ // Do this first so we don't need to clean up anything else if it fails.
+ SockDiag sd;
+ ASSERT_TRUE(sd.open()) << "Failed to open SOCK_DIAG socket";
+
+ // Create our own TunInterfaces (so we can delete them without affecting other tests), and add
+ // IP addresses to them. They must be IPv4 because tethering an interface disables and
+ // re-enables IPv6 on the interface, which clears all addresses.
+ TunInterface tun1, tun2;
+ ASSERT_EQ(0, tun1.init());
+ ASSERT_EQ(0, tun2.init());
+
+ // Clean up. It is safe to call TunInterface::destroy multiple times.
+ auto guard = android::base::make_scope_guard([&] {
+ tun1.destroy();
+ tun2.destroy();
+ mNetd->tetherStop();
+ mNetd->tetherInterfaceRemove(tun1.name());
+ mNetd->tetherInterfaceRemove(tun2.name());
+ });
+
+ IPAddress addr1, addr2;
+ ASSERT_TRUE(IPAddress::forString("192.0.2.1", &addr1));
+ ASSERT_TRUE(IPAddress::forString("192.0.2.2", &addr2));
+ EXPECT_EQ(0, tun1.addAddress(addr1.toString(), 32));
+ EXPECT_EQ(0, tun2.addAddress(addr2.toString(), 32));
+
+ // Stop tethering.
+ binder::Status status = mNetd->tetherStop();
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Start dnsmasq on an interface that doesn't exist.
+ // First, tether our tun interface...
+ status = mNetd->tetherInterfaceAdd(tun1.name());
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ expectTetherInterfaceConfigureForIPv6Router(tun1.name());
+
+ // ... then delete it...
+ tun1.destroy();
+
+ // ... then start dnsmasq.
+ android::net::TetherConfigParcel config;
+ config.usingLegacyDnsProxy = true;
+ config.dhcpRanges = {};
+ status = mNetd->tetherStartWithConfiguration(config);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ // Wait for dnsmasq to start.
+ expectProcessExists(DNSMASQ);
+
+ // Make sure that netd thinks the interface is tethered (even though it doesn't exist).
+ std::vector<std::string> ifList;
+ status = mNetd->tetherInterfaceList(&ifList);
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+ ASSERT_EQ(1U, ifList.size());
+ EXPECT_EQ(tun1.name(), ifList[0]);
+
+ // Give dnsmasq some time to start up.
+ usleep(200 * 1000);
+
+ // Check that dnsmasq is not listening on any IP addresses. It shouldn't, because it was only
+ // told to run on tun1, and tun1 does not exist. Ensure it stays running and doesn't listen on
+ // any IP addresses.
+ std::vector<IPAddress> listenAddrs = findDnsSockets(&sd, 0);
+ EXPECT_EQ(0U, listenAddrs.size()) << "Unexpectedly found IPv4 socket(s) listening on port 53";
+
+ // Now add an interface to dnsmasq and check that we can see the sockets. This confirms that
+ // findDnsSockets is actually able to see sockets when they exist.
+ status = mNetd->tetherInterfaceAdd(tun2.name());
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ in_addr loopback = {htonl(INADDR_LOOPBACK)};
+ listenAddrs = findDnsSockets(&sd, 2);
+ EXPECT_EQ(2U, listenAddrs.size()) << "Expected exactly 2 IPv4 sockets listening on port 53";
+ EXPECT_EQ(1, std::count(listenAddrs.begin(), listenAddrs.end(), addr2));
+ EXPECT_EQ(1, std::count(listenAddrs.begin(), listenAddrs.end(), IPAddress(loopback)));
+
+ // Clean up.
+ status = mNetd->tetherStop();
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ expectProcessDoesNotExist(DNSMASQ);
+
+ status = mNetd->tetherInterfaceRemove(tun1.name());
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+
+ status = mNetd->tetherInterfaceRemove(tun2.name());
+ EXPECT_TRUE(status.isOk()) << status.exceptionMessage();
+}
+
+namespace {
+
constexpr char FIREWALL_INPUT[] = "fw_INPUT";
constexpr char FIREWALL_OUTPUT[] = "fw_OUTPUT";
constexpr char FIREWALL_FORWARD[] = "fw_FORWARD";
@@ -3372,7 +3507,26 @@
EXPECT_TRUE(mNetd->networkDestroy(TEST_NETID1).isOk());
}
-TEST_F(BinderTest, TetherRuleDownstreamIpv6) {
+namespace {
+
+TetherOffloadRuleParcel makeTetherOffloadRule(int inputInterfaceIndex, int outputInterfaceIndex,
+ const std::vector<uint8_t>& destination,
+ int prefixLength,
+ const std::vector<uint8_t>& srcL2Address,
+ const std::vector<uint8_t>& dstL2Address) {
+ android::net::TetherOffloadRuleParcel parcel;
+ parcel.inputInterfaceIndex = inputInterfaceIndex;
+ parcel.outputInterfaceIndex = outputInterfaceIndex;
+ parcel.destination = destination;
+ parcel.prefixLength = prefixLength;
+ parcel.srcL2Address = srcL2Address;
+ parcel.dstL2Address = dstL2Address;
+ return parcel;
+}
+
+} // namespace
+
+TEST_F(BinderTest, TetherOffloadRule) {
SKIP_IF_BPF_NOT_SUPPORTED;
// TODO: Perhaps verify invalid interface index once the netd handle the error in methods.
@@ -3389,33 +3543,56 @@
const std::vector<uint8_t> kInvalidMac = {0xde, 0xad, 0xbe, 0xef}; // should be 6-byte length
// Invalid IP address, add rule
- auto status = mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kInvalidAddr4 /*bad*/,
- kSrcMac, kDstMac);
+ TetherOffloadRuleParcel rule = makeTetherOffloadRule(
+ kIfaceExt, kIfaceInt, kInvalidAddr4 /*bad*/, 128, kSrcMac, kDstMac);
+ auto status = mNetd->tetherOffloadRuleAdd(rule);
EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_EQ(EAFNOSUPPORT, status.serviceSpecificErrorCode());
// Invalid source L2 address, add rule
- status = mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kAddr6, kInvalidMac /*bad*/,
- kDstMac);
+ rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kInvalidMac /*bad*/, kDstMac);
+ status = mNetd->tetherOffloadRuleAdd(rule);
EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_EQ(ENXIO, status.serviceSpecificErrorCode());
// Invalid destination L2 address, add rule
- status = mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kAddr6, kSrcMac,
- kInvalidMac /*bad*/);
+ rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kInvalidMac /*bad*/);
+ status = mNetd->tetherOffloadRuleAdd(rule);
EXPECT_FALSE(status.isOk());
- EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ EXPECT_EQ(ENXIO, status.serviceSpecificErrorCode());
// Invalid IP address, remove rule
- status = mNetd->tetherRuleRemoveDownstreamIpv6(kIfaceExt, kInvalidAddr4 /*bad*/);
+ rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kInvalidAddr4 /*bad*/, 128, kSrcMac,
+ kDstMac);
+ status = mNetd->tetherOffloadRuleRemove(rule);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(EAFNOSUPPORT, status.serviceSpecificErrorCode());
+
+ // Invalid prefix length
+ rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 64 /*bad*/, kSrcMac, kDstMac);
+ status = mNetd->tetherOffloadRuleAdd(rule);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ status = mNetd->tetherOffloadRuleRemove(rule);
EXPECT_FALSE(status.isOk());
EXPECT_EQ(EINVAL, status.serviceSpecificErrorCode());
+ // Invalid interface index
+ rule = makeTetherOffloadRule(kIfaceExt, 0, kAddr6, 128, kSrcMac, kDstMac);
+ status = mNetd->tetherOffloadRuleAdd(rule);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode());
+ rule = makeTetherOffloadRule(0, kIfaceInt, kAddr6, 64, kSrcMac, kDstMac);
+ status = mNetd->tetherOffloadRuleRemove(rule);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(ENODEV, status.serviceSpecificErrorCode());
+
// Remove non existent rule. Expect that silently return success if the rule did not exist.
- EXPECT_TRUE(mNetd->tetherRuleRemoveDownstreamIpv6(kIfaceNonExistent, kAddr6).isOk());
+ rule = makeTetherOffloadRule(kIfaceNonExistent, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac);
+ EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk());
// Add and remove rule normally.
- EXPECT_TRUE(mNetd->tetherRuleAddDownstreamIpv6(kIfaceInt, kIfaceExt, kAddr6, kSrcMac, kDstMac)
- .isOk());
- EXPECT_TRUE(mNetd->tetherRuleRemoveDownstreamIpv6(kIfaceExt, kAddr6).isOk());
+ rule = makeTetherOffloadRule(kIfaceExt, kIfaceInt, kAddr6, 128, kSrcMac, kDstMac);
+ EXPECT_TRUE(mNetd->tetherOffloadRuleAdd(rule).isOk());
+ EXPECT_TRUE(mNetd->tetherOffloadRuleRemove(rule).isOk());
}