diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-08-01 07:26:40 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-08-01 07:26:40 +0000 |
commit | 20ab733813d5ef723708cab5d75a4d58ef92159d (patch) | |
tree | 41e92d8381891d99b0d639bf37fb3f9cf849c197 | |
parent | daa9470d743eeb670e049967f449f0ac628baa66 (diff) | |
parent | 7c184931f87c8e0b657dc9073d73e15114e9ef24 (diff) | |
download | netd-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.mk | 4 | ||||
-rw-r--r-- | server/CommandListener.cpp | 6 | ||||
-rw-r--r-- | server/NetdHwService.cpp | 96 | ||||
-rw-r--r-- | server/NetdHwService.h | 39 | ||||
-rw-r--r-- | server/NetworkController.cpp | 42 | ||||
-rw-r--r-- | server/NetworkController.h | 34 | ||||
-rw-r--r-- | server/main.cpp | 11 |
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(); |