OSDN Git Service

DO NOT MERGE Adding EventReporter class
[android-x86/system-netd.git] / server / NetdNativeService.cpp
index 678d19a..a575642 100644 (file)
 
 #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 "android/net/BnNetd.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;
 
@@ -38,6 +46,7 @@ namespace net {
 namespace {
 
 const char CONNECTIVITY_INTERNAL[] = "android.permission.CONNECTIVITY_INTERNAL";
+const char DUMP[] = "android.permission.DUMP";
 
 binder::Status checkPermission(const char *permission) {
     pid_t pid;
@@ -51,6 +60,17 @@ binder::Status checkPermission(const char *permission) {
     }
 }
 
+#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()) {                                   \
@@ -63,7 +83,6 @@ binder::Status checkPermission(const char *permission) {
     android::RWLock::AutoWLock _lock(lock);
 
 #define NETD_BIG_LOCK_RPC(permission) NETD_LOCKING_RPC((permission), gBigNetdLock)
-
 }  // namespace
 
 
@@ -79,6 +98,24 @@ status_t NetdNativeService::start() {
     return android::OK;
 }
 
+status_t NetdNativeService::dump(int fd, const Vector<String16> & /* args */) {
+    const binder::Status dump_permission = checkPermission(DUMP);
+    if (!dump_permission.isOk()) {
+        const String8 msg(dump_permission.toString8());
+        write(fd, msg.string(), msg.size());
+        return PERMISSION_DENIED;
+    }
+
+    // This method does not grab any locks. If individual classes need locking
+    // their dump() methods MUST handle locking appropriately.
+    DumpWriter dw(fd);
+    dw.blankline();
+    gCtls->netCtrl.dump(dw);
+    dw.blankline();
+
+    return NO_ERROR;
+}
+
 binder::Status NetdNativeService::isAlive(bool *alive) {
     NETD_BIG_LOCK_RPC(CONNECTIVITY_INTERNAL);
 
@@ -94,7 +131,183 @@ binder::Status NetdNativeService::firewallReplaceUidChain(const android::String1
     int err = gCtls->firewallCtrl.replaceUidChain(name.string(), isWhitelist, uids);
     *ret = (err == 0);
     return binder::Status::ok();
+}
+
+binder::Status NetdNativeService::bandwidthEnableDataSaver(bool enable, bool *ret) {
+    NETD_LOCKING_RPC(CONNECTIVITY_INTERNAL, gCtls->bandwidthCtrl.lock);
+
+    int err = gCtls->bandwidthCtrl.enableDataSaver(enable);
+    *ret = (err == 0);
+    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 &parameter,
+        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