summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-08-01 07:26:40 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-08-01 07:26:40 +0000
commit20ab733813d5ef723708cab5d75a4d58ef92159d (patch)
tree41e92d8381891d99b0d639bf37fb3f9cf849c197
parentdaa9470d743eeb670e049967f449f0ac628baa66 (diff)
parent7c184931f87c8e0b657dc9073d73e15114e9ef24 (diff)
downloadnetd-20ab733813d5ef723708cab5d75a4d58ef92159d.tar.gz
release-request-9f4f667d-7182-482d-8948-dc901f7b3ba0-for-git_oc-mr1-release-4233774 snap-temp-L05100000087867725
Change-Id: Ib0416f035d1e6f24af02bb0c849ad516376c73de
-rw-r--r--server/Android.mk4
-rw-r--r--server/CommandListener.cpp6
-rw-r--r--server/NetdHwService.cpp96
-rw-r--r--server/NetdHwService.h39
-rw-r--r--server/NetworkController.cpp42
-rw-r--r--server/NetworkController.h34
-rw-r--r--server/main.cpp11
7 files changed, 228 insertions, 4 deletions
diff --git a/server/Android.mk b/server/Android.mk
index 8c3d648b..71c22c67 100644
--- a/server/Android.mk
+++ b/server/Android.mk
@@ -63,10 +63,13 @@ endif
LOCAL_INIT_RC := netd.rc
LOCAL_SHARED_LIBRARIES := \
+ android.system.net.netd@1.0 \
libbinder \
libcrypto \
libcutils \
libdl \
+ libhidlbase \
+ libhidltransport \
liblog \
liblogwrap \
libmdnssd \
@@ -99,6 +102,7 @@ LOCAL_SRC_FILES := \
NatController.cpp \
NetdCommand.cpp \
NetdConstants.cpp \
+ NetdHwService.cpp \
NetdNativeService.cpp \
NetlinkHandler.cpp \
NetlinkManager.cpp \
diff --git a/server/CommandListener.cpp b/server/CommandListener.cpp
index 5b9fa8a3..d191c05d 100644
--- a/server/CommandListener.cpp
+++ b/server/CommandListener.cpp
@@ -69,6 +69,12 @@ unsigned stringToNetId(const char* arg) {
return NetworkController::MIN_OEM_ID + n;
}
return NETID_UNSET;
+ } else if (!strncmp(arg, "handle", 6)) {
+ unsigned n = netHandleToNetId((net_handle_t)strtoull(arg + 6, NULL, 10));
+ if (NetworkController::MIN_OEM_ID <= n && n <= NetworkController::MAX_OEM_ID) {
+ return n;
+ }
+ return NETID_UNSET;
}
// strtoul() returns 0 on errors, which is fine because 0 is an invalid netId.
return strtoul(arg, NULL, 0);
diff --git a/server/NetdHwService.cpp b/server/NetdHwService.cpp
new file mode 100644
index 00000000..6fb67003
--- /dev/null
+++ b/server/NetdHwService.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <binder/IPCThreadState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hwbinder/IPCThreadState.h>
+#include "Controllers.h"
+#include "Fwmark.h"
+#include "NetdHwService.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::IPCThreadState;
+using android::hardware::Void;
+
+namespace android {
+namespace net {
+
+/**
+ * This lock exists to make NetdHwService RPCs (which come in on multiple HwBinder threads)
+ * coexist with the commands in CommandListener.cpp. These are presumed not thread-safe because
+ * CommandListener has only one user (NetworkManagementService), which is connected through a
+ * FrameworkListener that passes in commands one at a time.
+ */
+extern android::RWLock gBigNetdLock;
+
+static INetd::StatusCode toHalStatus(int ret) {
+ switch(ret) {
+ case 0:
+ return INetd::StatusCode::OK;
+ case -EINVAL:
+ return INetd::StatusCode::INVALID_ARGUMENTS;
+ case -EEXIST:
+ return INetd::StatusCode::ALREADY_EXISTS;
+ case -ENONET:
+ return INetd::StatusCode::NO_NETWORK;
+ case -EPERM:
+ return INetd::StatusCode::PERMISSION_DENIED;
+ default:
+ ALOGE("HAL service error=%d", ret);
+ return INetd::StatusCode::UNKNOWN_ERROR;
+ }
+}
+
+// Minimal service start.
+status_t NetdHwService::start() {
+ IPCThreadState::self()->disableBackgroundScheduling(true);
+ // Usage of this HAL is anticipated to be thin; one thread should suffice.
+ configureRpcThreadpool(1, false /* callerWillNotJoin */);
+ // Register hardware service with ServiceManager.
+ return INetd::registerAsService();
+}
+
+Return<void> NetdHwService::createOemNetwork(createOemNetwork_cb _hidl_cb) {
+ unsigned netId;
+ Permission permission = PERMISSION_SYSTEM;
+
+ android::RWLock::AutoWLock _lock(gBigNetdLock);
+ int ret = gCtls->netCtrl.createPhysicalOemNetwork(permission, &netId);
+
+ Fwmark fwmark;
+ fwmark.netId = netId;
+ fwmark.explicitlySelected = true;
+ fwmark.protectedFromVpn = true;
+ fwmark.permission = PERMISSION_SYSTEM;
+ _hidl_cb(netIdToNetHandle(netId), fwmark.intValue, toHalStatus(ret));
+
+ return Void();
+}
+
+Return<INetd::StatusCode> NetdHwService::destroyOemNetwork(uint64_t netHandle) {
+ unsigned netId = netHandleToNetId(netHandle);
+ if ((netId < NetworkController::MIN_OEM_ID) ||
+ (netId > NetworkController::MAX_OEM_ID)) {
+ return INetd::StatusCode::INVALID_ARGUMENTS;
+ }
+
+ android::RWLock::AutoWLock _lock(gBigNetdLock);
+
+ return toHalStatus(gCtls->netCtrl.destroyNetwork(netId));
+}
+
+} // namespace net
+} // namespace android
diff --git a/server/NetdHwService.h b/server/NetdHwService.h
new file mode 100644
index 00000000..f938dd65
--- /dev/null
+++ b/server/NetdHwService.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_NET_HW_SERVICE_H
+#define ANDROID_NET_HW_SERVICE_H
+
+#include <android/system/net/netd/1.0/INetd.h>
+
+using android::hardware::Return;
+using android::system::net::netd::V1_0::INetd;
+
+namespace android {
+namespace net {
+
+class NetdHwService : public INetd {
+public:
+ status_t start();
+ Return<void> createOemNetwork(createOemNetwork_cb _hidl_cb) override;
+ Return<INetd::StatusCode> destroyOemNetwork(uint64_t netHandle) override;
+};
+
+} // namespace net
+} // namespace android
+
+#endif // ANDROID_NET_HW_SERVICE_H
+
diff --git a/server/NetworkController.cpp b/server/NetworkController.cpp
index b90976b6..ecb4ceed 100644
--- a/server/NetworkController.cpp
+++ b/server/NetworkController.cpp
@@ -321,14 +321,14 @@ bool NetworkController::isVirtualNetwork(unsigned netId) const {
return network && network->getType() == Network::VIRTUAL;
}
-int NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
+int NetworkController::createPhysicalNetworkLocked(unsigned netId, Permission permission) {
if (!((MIN_NET_ID <= netId && netId <= MAX_NET_ID) ||
(MIN_OEM_ID <= netId && netId <= MAX_OEM_ID))) {
ALOGE("invalid netId %u", netId);
return -EINVAL;
}
- if (isValidNetwork(netId)) {
+ if (isValidNetworkLocked(netId)) {
ALOGE("duplicate netId %u", netId);
return -EEXIST;
}
@@ -340,11 +340,41 @@ int NetworkController::createPhysicalNetwork(unsigned netId, Permission permissi
return ret;
}
- android::RWLock::AutoWLock lock(mRWLock);
mNetworks[netId] = physicalNetwork;
return 0;
}
+int NetworkController::createPhysicalNetwork(unsigned netId, Permission permission) {
+ android::RWLock::AutoWLock lock(mRWLock);
+ return createPhysicalNetworkLocked(netId, permission);
+}
+
+int NetworkController::createPhysicalOemNetwork(Permission permission, unsigned *pNetId) {
+ if (pNetId == NULL) {
+ return -EINVAL;
+ }
+
+ android::RWLock::AutoWLock lock(mRWLock);
+ for (*pNetId = MIN_OEM_ID; *pNetId <= MAX_OEM_ID; (*pNetId)++) {
+ if (!isValidNetworkLocked(*pNetId)) {
+ break;
+ }
+ }
+
+ if (*pNetId > MAX_OEM_ID) {
+ ALOGE("No free network ID");
+ *pNetId = 0;
+ return -ENONET;
+ }
+
+ int ret = createPhysicalNetworkLocked(*pNetId, permission);
+ if (ret) {
+ *pNetId = 0;
+ }
+
+ return ret;
+}
+
int NetworkController::createVirtualNetwork(unsigned netId, bool hasDns, bool secure) {
if (!(MIN_NET_ID <= netId && netId <= MAX_NET_ID)) {
ALOGE("invalid netId %u", netId);
@@ -564,9 +594,13 @@ void NetworkController::dump(DumpWriter& dw) {
dw.decIndent();
}
+bool NetworkController::isValidNetworkLocked(unsigned netId) const {
+ return getNetworkLocked(netId);
+}
+
bool NetworkController::isValidNetwork(unsigned netId) const {
android::RWLock::AutoRLock lock(mRWLock);
- return getNetworkLocked(netId);
+ return isValidNetworkLocked(netId);
}
Network* NetworkController::getNetworkLocked(unsigned netId) const {
diff --git a/server/NetworkController.h b/server/NetworkController.h
index d5451ee8..ceb538e5 100644
--- a/server/NetworkController.h
+++ b/server/NetworkController.h
@@ -17,6 +17,7 @@
#ifndef NETD_SERVER_NETWORK_CONTROLLER_H
#define NETD_SERVER_NETWORK_CONTROLLER_H
+#include <android/multinetwork.h>
#include "NetdConstants.h"
#include "Permission.h"
@@ -33,6 +34,36 @@ struct android_net_context;
namespace android {
namespace net {
+// Utility to convert from netId to net_handle_t. Doing this here as opposed to exporting
+// from net.c as it may have NDK implications. Besides no conversion available in net.c for
+// obtaining handle given netId.
+// TODO: Use getnetidfromhandle() in net.c.
+static inline unsigned netHandleToNetId(net_handle_t fromNetHandle) {
+ const uint32_t k32BitMask = 0xffffffff;
+ // This value MUST be kept in sync with the corresponding value in
+ // the android.net.Network#getNetworkHandle() implementation.
+ const uint32_t kHandleMagic = 0xfacade;
+
+ // Check for minimum acceptable version of the API in the low bits.
+ if (fromNetHandle != NETWORK_UNSPECIFIED &&
+ (fromNetHandle & k32BitMask) != kHandleMagic) {
+ return 0;
+ }
+
+ return ((fromNetHandle >> (CHAR_BIT * sizeof(k32BitMask))) & k32BitMask);
+}
+
+// Utility to convert from nethandle to netid, keep in sync with getNetworkHandle
+// in Network.java.
+static inline net_handle_t netIdToNetHandle(unsigned fromNetId) {
+ const net_handle_t HANDLE_MAGIC = 0xfacade;
+
+ if (!fromNetId) {
+ return NETWORK_UNSPECIFIED;
+ }
+ return (((net_handle_t)fromNetId << 32) | HANDLE_MAGIC);
+}
+
class DumpWriter;
class Network;
class UidRanges;
@@ -67,6 +98,7 @@ public:
bool isVirtualNetwork(unsigned netId) const;
int createPhysicalNetwork(unsigned netId, Permission permission) WARN_UNUSED_RESULT;
+ int createPhysicalOemNetwork(Permission permission, unsigned *netId) WARN_UNUSED_RESULT;
int createVirtualNetwork(unsigned netId, bool hasDns, bool secure) WARN_UNUSED_RESULT;
int destroyNetwork(unsigned netId) WARN_UNUSED_RESULT;
@@ -100,10 +132,12 @@ public:
private:
bool isValidNetwork(unsigned netId) const;
+ bool isValidNetworkLocked(unsigned netId) const;
Network* getNetworkLocked(unsigned netId) const;
VirtualNetwork* getVirtualNetworkForUserLocked(uid_t uid) const;
Permission getPermissionForUserLocked(uid_t uid) const;
int checkUserNetworkAccessLocked(uid_t uid, unsigned netId) const;
+ int createPhysicalNetworkLocked(unsigned netId, Permission permission) WARN_UNUSED_RESULT;
int modifyRoute(unsigned netId, const char* interface, const char* destination,
const char* nexthop, bool add, bool legacy, uid_t uid) WARN_UNUSED_RESULT;
diff --git a/server/main.cpp b/server/main.cpp
index 27596f7d..176d3218 100644
--- a/server/main.cpp
+++ b/server/main.cpp
@@ -42,6 +42,7 @@
#include "MDnsSdListener.h"
#include "NFLogListener.h"
#include "NetdConstants.h"
+#include "NetdHwService.h"
#include "NetdNativeService.h"
#include "NetlinkManager.h"
#include "Stopwatch.h"
@@ -54,6 +55,7 @@ using android::defaultServiceManager;
using android::net::CommandListener;
using android::net::DnsProxyListener;
using android::net::FwmarkServer;
+using android::net::NetdHwService;
using android::net::NetdNativeService;
using android::net::NetlinkManager;
using android::net::NFLogListener;
@@ -150,6 +152,15 @@ int main() {
write_pid_file();
+ // Now that netd is ready to process commands, advertise service
+ // availability for HAL clients.
+ NetdHwService mHwSvc;
+ if ((ret = mHwSvc.start()) != android::OK) {
+ ALOGE("Unable to start NetdHwService: %d", ret);
+ exit(1);
+ }
+ ALOGI("Registering NetdHwService: %.1fms", subTime.getTimeAndReset());
+
ALOGI("Netd started in %dms", static_cast<int>(s.timeTaken()));
IPCThreadState::self()->joinThreadPool();