• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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