1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <binder/IPCThreadState.h> 18 #include <hidl/HidlTransportSupport.h> 19 #include <hwbinder/IPCThreadState.h> 20 #include "Controllers.h" 21 #include "Fwmark.h" 22 #include "NetdHwService.h" 23 #include "RouteController.h" 24 #include "TetherController.h" 25 26 using android::hardware::configureRpcThreadpool; 27 using android::hardware::IPCThreadState; 28 using android::hardware::Void; 29 30 // Tells TetherController::enableForwarding who is requesting forwarding, so that TetherController 31 // can manage/refcount requests to enable forwarding by multiple parties such as the framework, this 32 // hwbinder interface, and the legacy "ndc ipfwd enable <requester>" commands. 33 namespace { 34 constexpr const char* FORWARDING_REQUESTER = "NetdHwService"; 35 } 36 37 namespace android { 38 namespace net { 39 toHalStatus(int ret)40 static StatusCode toHalStatus(int ret) { 41 switch(ret) { 42 case 0: 43 return StatusCode::OK; 44 case -EINVAL: 45 return StatusCode::INVALID_ARGUMENTS; 46 case -EEXIST: 47 return StatusCode::ALREADY_EXISTS; 48 case -ENONET: 49 return StatusCode::NO_NETWORK; 50 case -EPERM: 51 return StatusCode::PERMISSION_DENIED; 52 default: 53 ALOGE("HAL service error=%d", ret); 54 return StatusCode::UNKNOWN_ERROR; 55 } 56 } 57 58 // Minimal service start. start()59 status_t NetdHwService::start() { 60 IPCThreadState::self()->disableBackgroundScheduling(true); 61 // Usage of this HAL is anticipated to be thin; one thread should suffice. 62 configureRpcThreadpool(1, false /* callerWillNotJoin */); 63 // Register hardware service with ServiceManager. 64 return INetd::registerAsService(); 65 } 66 createOemNetwork(createOemNetwork_cb _hidl_cb)67 Return<void> NetdHwService::createOemNetwork(createOemNetwork_cb _hidl_cb) { 68 unsigned netId; 69 Permission permission = PERMISSION_SYSTEM; 70 71 int ret = gCtls->netCtrl.createPhysicalOemNetwork(permission, &netId); 72 73 Fwmark fwmark; 74 fwmark.netId = netId; 75 fwmark.explicitlySelected = true; 76 fwmark.protectedFromVpn = true; 77 fwmark.permission = PERMISSION_SYSTEM; 78 _hidl_cb(netIdToNetHandle(netId), fwmark.intValue, toHalStatus(ret)); 79 80 return Void(); 81 } 82 83 // Vendor code can only modify OEM networks. All other networks are managed by ConnectivityService. 84 #define RETURN_IF_NOT_OEM_NETWORK(netId) \ 85 if (((netId) < NetworkController::MIN_OEM_ID) || \ 86 ((netId) > NetworkController::MAX_OEM_ID)) { \ 87 return StatusCode::INVALID_ARGUMENTS; \ 88 } 89 destroyOemNetwork(uint64_t netHandle)90 Return<StatusCode> NetdHwService::destroyOemNetwork(uint64_t netHandle) { 91 unsigned netId = netHandleToNetId(netHandle); 92 RETURN_IF_NOT_OEM_NETWORK(netId); 93 94 return toHalStatus(gCtls->netCtrl.destroyNetwork(netId)); 95 } 96 maybeNullString(const hidl_string & nexthop)97 const char* maybeNullString(const hidl_string& nexthop) { 98 // HIDL strings can't be null, but RouteController wants null instead of an empty string. 99 const char* nh = nexthop.c_str(); 100 if (nh && !*nh) { 101 nh = nullptr; 102 } 103 return nh; 104 } 105 addRouteToOemNetwork(uint64_t networkHandle,const hidl_string & ifname,const hidl_string & destination,const hidl_string & nexthop)106 Return <StatusCode> NetdHwService::addRouteToOemNetwork( 107 uint64_t networkHandle, const hidl_string& ifname, const hidl_string& destination, 108 const hidl_string& nexthop) { 109 unsigned netId = netHandleToNetId(networkHandle); 110 RETURN_IF_NOT_OEM_NETWORK(netId); 111 112 return toHalStatus(gCtls->netCtrl.addRoute(netId, ifname.c_str(), destination.c_str(), 113 maybeNullString(nexthop), false, INVALID_UID)); 114 } 115 removeRouteFromOemNetwork(uint64_t networkHandle,const hidl_string & ifname,const hidl_string & destination,const hidl_string & nexthop)116 Return <StatusCode> NetdHwService::removeRouteFromOemNetwork( 117 uint64_t networkHandle, const hidl_string& ifname, const hidl_string& destination, 118 const hidl_string& nexthop) { 119 unsigned netId = netHandleToNetId(networkHandle); 120 RETURN_IF_NOT_OEM_NETWORK(netId); 121 122 return toHalStatus(gCtls->netCtrl.removeRoute(netId, ifname.c_str(), destination.c_str(), 123 maybeNullString(nexthop), false, INVALID_UID)); 124 } 125 addInterfaceToOemNetwork(uint64_t networkHandle,const hidl_string & ifname)126 Return <StatusCode> NetdHwService::addInterfaceToOemNetwork(uint64_t networkHandle, 127 const hidl_string& ifname) { 128 unsigned netId = netHandleToNetId(networkHandle); 129 RETURN_IF_NOT_OEM_NETWORK(netId); 130 131 return toHalStatus(gCtls->netCtrl.addInterfaceToNetwork(netId, ifname.c_str())); 132 } 133 removeInterfaceFromOemNetwork(uint64_t networkHandle,const hidl_string & ifname)134 Return <StatusCode> NetdHwService::removeInterfaceFromOemNetwork(uint64_t networkHandle, 135 const hidl_string& ifname) { 136 unsigned netId = netHandleToNetId(networkHandle); 137 RETURN_IF_NOT_OEM_NETWORK(netId); 138 139 return toHalStatus(gCtls->netCtrl.removeInterfaceFromNetwork(netId, ifname.c_str())); 140 } 141 setIpForwardEnable(bool enable)142 Return <StatusCode> NetdHwService::setIpForwardEnable(bool enable) { 143 android::RWLock::AutoWLock _lock(gCtls->tetherCtrl.lock); 144 145 bool success = enable ? gCtls->tetherCtrl.enableForwarding(FORWARDING_REQUESTER) : 146 gCtls->tetherCtrl.disableForwarding(FORWARDING_REQUESTER); 147 148 return success ? StatusCode::OK : StatusCode::UNKNOWN_ERROR; 149 } 150 setForwardingBetweenInterfaces(const hidl_string & inputIfName,const hidl_string & outputIfName,bool enable)151 Return <StatusCode> NetdHwService::setForwardingBetweenInterfaces( 152 const hidl_string& inputIfName, const hidl_string& outputIfName, bool enable) { 153 android::RWLock::AutoWLock _lock(gCtls->tetherCtrl.lock); 154 155 // TODO: check that one interface is an OEM interface and the other is another OEM interface, an 156 // IPsec interface or a dummy interface. 157 int ret = enable ? RouteController::enableTethering(inputIfName.c_str(), outputIfName.c_str()) : 158 RouteController::disableTethering(inputIfName.c_str(), outputIfName.c_str()); 159 return toHalStatus(ret); 160 } 161 162 } // namespace net 163 } // namespace android 164