#include <android-base/stringprintf.h>
#include <cutils/log.h>
+#include <cutils/properties.h>
#include <utils/Errors.h>
+#include <utils/String16.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include "Controllers.h"
#include "DumpWriter.h"
+#include "EventReporter.h"
+#include "InterfaceController.h"
#include "NetdConstants.h"
#include "NetdNativeService.h"
+#include "RouteController.h"
+#include "SockDiag.h"
+#include "UidRanges.h"
using android::base::StringPrintf;
}
}
+#define ENFORCE_DEBUGGABLE() { \
+ char value[PROPERTY_VALUE_MAX + 1]; \
+ if (property_get("ro.debuggable", value, NULL) != 1 \
+ || value[0] != '1') { \
+ return binder::Status::fromExceptionCode( \
+ binder::Status::EX_SECURITY, \
+ String8("Not available in production builds.") \
+ ); \
+ } \
+}
+
#define ENFORCE_PERMISSION(permission) { \
binder::Status status = checkPermission((permission)); \
if (!status.isOk()) { \
android::RWLock::AutoWLock _lock(lock);
#define NETD_BIG_LOCK_RPC(permission) NETD_LOCKING_RPC((permission), gBigNetdLock)
-
} // namespace
return binder::Status::ok();
}
+binder::Status NetdNativeService::networkRejectNonSecureVpn(bool add,
+ const std::vector<UidRange>& uidRangeArray) {
+ // TODO: elsewhere RouteController is only used from the tethering and network controllers, so
+ // it should be possible to use the same lock as NetworkController. However, every call through
+ // the CommandListener "network" command will need to hold this lock too, not just the ones that
+ // read/modify network internal state (that is sufficient for ::dump() because it doesn't
+ // look at routes, but it's not enough here).
+ NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
+
+ UidRanges uidRanges(uidRangeArray);
+
+ int err;
+ if (add) {
+ err = RouteController::addUsersToRejectNonSecureNetworkRule(uidRanges);
+ } else {
+ err = RouteController::removeUsersFromRejectNonSecureNetworkRule(uidRanges);
+ }
+
+ if (err != 0) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("RouteController error: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::socketDestroy(const std::vector<UidRange>& uids,
+ const std::vector<int32_t>& skipUids) {
+
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+
+ SockDiag sd;
+ if (!sd.open()) {
+ return binder::Status::fromServiceSpecificError(EIO,
+ String8("Could not open SOCK_DIAG socket"));
+ }
+
+ UidRanges uidRanges(uids);
+ int err = sd.destroySockets(uidRanges, std::set<uid_t>(skipUids.begin(), skipUids.end()),
+ true /* excludeLoopback */);
+
+ if (err) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("destroySockets: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::setResolverConfiguration(int32_t netId,
+ const std::vector<std::string>& servers, const std::vector<std::string>& domains,
+ const std::vector<int32_t>& params) {
+ // This function intentionally does not lock within Netd, as Bionic is thread-safe.
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+
+ int err = gCtls->resolverCtrl.setResolverConfiguration(netId, servers, domains, params);
+ if (err != 0) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("ResolverController error: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::getResolverInfo(int32_t netId,
+ std::vector<std::string>* servers, std::vector<std::string>* domains,
+ std::vector<int32_t>* params, std::vector<int32_t>* stats) {
+ // This function intentionally does not lock within Netd, as Bionic is thread-safe.
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+
+ int err = gCtls->resolverCtrl.getResolverInfo(netId, servers, domains, params, stats);
+ if (err != 0) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("ResolverController error: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::tetherApplyDnsInterfaces(bool *ret) {
+ NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
+
+ *ret = gCtls->tetherCtrl.applyDnsInterfaces();
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::interfaceAddAddress(const std::string &ifName,
+ const std::string &addrString, int prefixLength) {
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+
+ const int err = InterfaceController::addAddress(
+ ifName.c_str(), addrString.c_str(), prefixLength);
+ if (err != 0) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("InterfaceController error: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::interfaceDelAddress(const std::string &ifName,
+ const std::string &addrString, int prefixLength) {
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+
+ const int err = InterfaceController::delAddress(
+ ifName.c_str(), addrString.c_str(), prefixLength);
+ if (err != 0) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("InterfaceController error: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::setProcSysNet(
+ int32_t family, int32_t which, const std::string &ifname, const std::string ¶meter,
+ const std::string &value) {
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+
+ const char *familyStr;
+ switch (family) {
+ case INetd::IPV4:
+ familyStr = "ipv4";
+ break;
+ case INetd::IPV6:
+ familyStr = "ipv6";
+ break;
+ default:
+ return binder::Status::fromServiceSpecificError(EAFNOSUPPORT, String8("Bad family"));
+ }
+
+ const char *whichStr;
+ switch (which) {
+ case INetd::CONF:
+ whichStr = "conf";
+ break;
+ case INetd::NEIGH:
+ whichStr = "neigh";
+ break;
+ default:
+ return binder::Status::fromServiceSpecificError(EINVAL, String8("Bad category"));
+ }
+
+ const int err = InterfaceController::setParameter(
+ familyStr, whichStr, ifname.c_str(), parameter.c_str(),
+ value.c_str());
+ if (err != 0) {
+ return binder::Status::fromServiceSpecificError(-err,
+ String8::format("ResolverController error: %s", strerror(-err)));
+ }
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::getMetricsReportingLevel(int *reportingLevel) {
+ // This function intentionally does not lock, since the only thing it does is one read from an
+ // atomic_int.
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+ ENFORCE_DEBUGGABLE();
+
+ *reportingLevel = gCtls->eventReporter.getMetricsReportingLevel();
+ return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::setMetricsReportingLevel(const int reportingLevel) {
+ // This function intentionally does not lock, since the only thing it does is one write to an
+ // atomic_int.
+ ENFORCE_PERMISSION(CONNECTIVITY_INTERNAL);
+ ENFORCE_DEBUGGABLE();
+
+ return (gCtls->eventReporter.setMetricsReportingLevel(reportingLevel) == 0)
+ ? binder::Status::ok()
+ : binder::Status::fromExceptionCode(binder::Status::EX_ILLEGAL_ARGUMENT);
+}
+
} // namespace net
} // namespace android