Home | History | Annotate | Download | only in server
      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 
     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.
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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