• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2022 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 <numeric>
18  #include <string>
19  
20  #include <android-base/logging.h>
21  #include <android-base/strings.h>
22  #include <netdb.h>
23  
24  #include "Offload.h"
25  
26  namespace aidl::android::hardware::tetheroffload::impl::example {
27  
28  using ::android::base::Join;
29  
addDownstream(const std::string & in_iface,const std::string & in_prefix)30  ndk::ScopedAStatus Offload::addDownstream(const std::string& in_iface,
31                                            const std::string& in_prefix) {
32      LOG(VERBOSE) << __func__ << " Interface: " << in_iface << ", Prefix: " << in_prefix;
33      if (!isInitialized()) {
34          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
35                  EX_ILLEGAL_STATE, "Tetheroffload HAL not initialized");
36      }
37      if (!isValidInterface(in_iface)) {
38          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
39                                                                  "Invalid interface name");
40      }
41      if (!isValidIpPrefix(in_prefix)) {
42          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
43                                                                  "Invalid IP prefix");
44      }
45      return ndk::ScopedAStatus::ok();
46  }
47  
getForwardedStats(const std::string & in_upstream,ForwardedStats * _aidl_return)48  ndk::ScopedAStatus Offload::getForwardedStats(const std::string& in_upstream,
49                                                ForwardedStats* _aidl_return) {
50      LOG(VERBOSE) << __func__ << " Upstream: " << in_upstream;
51      ForwardedStats stats;
52      stats.rxBytes = 0;
53      stats.txBytes = 0;
54      *_aidl_return = std::move(stats);
55      return ndk::ScopedAStatus::ok();
56  }
57  
initOffload(const ndk::ScopedFileDescriptor & in_fd1,const ndk::ScopedFileDescriptor & in_fd2,const std::shared_ptr<ITetheringOffloadCallback> & in_cb)58  ndk::ScopedAStatus Offload::initOffload(const ndk::ScopedFileDescriptor& in_fd1,
59                                          const ndk::ScopedFileDescriptor& in_fd2,
60                                          const std::shared_ptr<ITetheringOffloadCallback>& in_cb) {
61      LOG(VERBOSE) << __func__ << " FileDescriptor1: " << std::to_string(in_fd1.get())
62                   << ", FileDescriptor2: " << std::to_string(in_fd2.get())
63                   << ", ITetheringOffloadCallback: " << in_cb;
64      if (isInitialized()) {
65          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
66                  EX_ILLEGAL_STATE, "Tetheroffload HAL already initialized");
67      }
68      int fd1 = in_fd1.get();
69      int fd2 = in_fd2.get();
70      if (fd1 < 0 || fd2 < 0) {
71          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
72                                                                  "Invalid file descriptors");
73      }
74      mFd1 = ndk::ScopedFileDescriptor(dup(fd1));
75      mFd2 = ndk::ScopedFileDescriptor(dup(fd2));
76      mInitialized = true;
77      return ndk::ScopedAStatus::ok();
78  }
79  
removeDownstream(const std::string & in_iface,const std::string & in_prefix)80  ndk::ScopedAStatus Offload::removeDownstream(const std::string& in_iface,
81                                               const std::string& in_prefix) {
82      LOG(VERBOSE) << __func__ << " Interface: " << in_iface << ", Prefix: " << in_prefix;
83      if (!isInitialized()) {
84          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
85                  EX_ILLEGAL_STATE, "Tetheroffload HAL not initialized");
86      }
87      if (!isValidIpPrefix(in_prefix)) {
88          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
89                                                                  "Invalid IP prefix");
90      }
91      if (!isValidInterface(in_iface)) {
92          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
93                                                                  "Invalid interface name");
94      }
95      return ndk::ScopedAStatus::ok();
96  }
97  
setDataWarningAndLimit(const std::string & in_upstream,int64_t in_warningBytes,int64_t in_limitBytes)98  ndk::ScopedAStatus Offload::setDataWarningAndLimit(const std::string& in_upstream,
99                                                     int64_t in_warningBytes, int64_t in_limitBytes) {
100      LOG(VERBOSE) << __func__ << " Upstream: " << in_upstream
101                   << ", WarningBytes: " << in_warningBytes << ", LimitBytes: " << in_limitBytes;
102      if (!isInitialized()) {
103          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
104                  EX_ILLEGAL_STATE, "Tetheroffload HAL not initialized");
105      }
106      if (!isValidInterface(in_upstream)) {
107          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
108                                                                  "Invalid interface name");
109      }
110      if (in_warningBytes < 0 || in_limitBytes < 0) {
111          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
112                                                                  "Threshold must be non-negative");
113      }
114      return ndk::ScopedAStatus::ok();
115  }
116  
setLocalPrefixes(const std::vector<std::string> & in_prefixes)117  ndk::ScopedAStatus Offload::setLocalPrefixes(const std::vector<std::string>& in_prefixes) {
118      LOG(VERBOSE) << __func__ << " Prefixes: " << Join(in_prefixes, ',');
119      if (!isInitialized()) {
120          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
121                  EX_ILLEGAL_STATE, "Tetheroffload HAL not initialized");
122      }
123      if (in_prefixes.empty()) {
124          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
125                                                                  "No IP prefix");
126      }
127      for (std::string prefix : in_prefixes) {
128          if (!isValidIpPrefix(prefix)) {
129              return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
130                                                                      "Invalid IP prefix");
131          }
132      }
133      return ndk::ScopedAStatus::ok();
134  }
135  
setUpstreamParameters(const std::string & in_iface,const std::string & in_v4Addr,const std::string & in_v4Gw,const std::vector<std::string> & in_v6Gws)136  ndk::ScopedAStatus Offload::setUpstreamParameters(const std::string& in_iface,
137                                                    const std::string& in_v4Addr,
138                                                    const std::string& in_v4Gw,
139                                                    const std::vector<std::string>& in_v6Gws) {
140      LOG(VERBOSE) << __func__ << " Interface: " << in_iface << ", IPv4Address: " << in_v4Addr
141                   << ", IPv4Gateway: " << in_v4Gw << ", IPv6Gateways: " << Join(in_v6Gws, ',');
142      if (!isInitialized()) {
143          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
144                  EX_ILLEGAL_STATE, "Tetheroffload HAL not initialized");
145      }
146      if (!isValidInterface(in_iface)) {
147          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
148                                                                  "Invalid interface name");
149      }
150      if (in_v4Addr.empty() && in_v4Gw.empty() && in_v6Gws.empty()) {
151          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
152                                                                  "No upstream IP address");
153      }
154      if (!in_v4Addr.empty() && !in_v4Gw.empty()) {
155          if (!isValidIpv4Address(in_v4Addr) || !isValidIpv4Address(in_v4Gw)) {
156              return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
157                                                                      "Invalid IP address");
158          }
159      }
160      for (std::string ip : in_v6Gws) {
161          if (!isValidIpv6Address(ip)) {
162              return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
163                                                                      "Invalid IP address");
164          }
165      }
166      return ndk::ScopedAStatus::ok();
167  }
168  
stopOffload()169  ndk::ScopedAStatus Offload::stopOffload() {
170      LOG(VERBOSE) << __func__;
171      if (!isInitialized()) {
172          return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
173                  EX_ILLEGAL_STATE, "Tetheroffload HAL not initialized");
174      }
175      mInitialized = false;
176      return ndk::ScopedAStatus::ok();
177  };
178  
isInitialized()179  bool Offload::isInitialized() {
180      return (mInitialized == true);
181  }
182  
isValidInterface(const std::string & iface)183  bool Offload::isValidInterface(const std::string& iface) {
184      return !iface.empty() && iface != "invalid";
185  }
186  
isValidIpv4Address(const std::string & repr)187  bool Offload::isValidIpv4Address(const std::string& repr) {
188      return validateIpAddressOrPrefix(repr, AF_INET, false);
189  }
190  
isValidIpv4Prefix(const std::string & repr)191  bool Offload::isValidIpv4Prefix(const std::string& repr) {
192      return validateIpAddressOrPrefix(repr, AF_INET, true);
193  }
194  
isValidIpv6Address(const std::string & repr)195  bool Offload::isValidIpv6Address(const std::string& repr) {
196      return validateIpAddressOrPrefix(repr, AF_INET6, false);
197  }
198  
isValidIpv6Prefix(const std::string & repr)199  bool Offload::isValidIpv6Prefix(const std::string& repr) {
200      return validateIpAddressOrPrefix(repr, AF_INET6, true);
201  }
202  
isValidIpAddress(const std::string & repr)203  bool Offload::isValidIpAddress(const std::string& repr) {
204      return isValidIpv4Address(repr) || isValidIpv6Address(repr);
205  }
206  
isValidIpPrefix(const std::string & repr)207  bool Offload::isValidIpPrefix(const std::string& repr) {
208      return isValidIpv4Prefix(repr) || isValidIpv6Prefix(repr);
209  }
210  
211  // Refer to libnetdutils's IPAddress and IPPrefix classes.
212  // Can't use them directly because libnetdutils is not "vendor_available".
validateIpAddressOrPrefix(const std::string & repr,const int expectedFamily,const bool isPrefix)213  bool Offload::validateIpAddressOrPrefix(const std::string& repr, const int expectedFamily,
214                                          const bool isPrefix) {
215      const addrinfo hints = {
216              .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
217      };
218      addrinfo* res;
219      size_t index = repr.find('/');
220      if (isPrefix && index == std::string::npos) return false;
221  
222      // Parse the IP address.
223      const std::string ipAddress = isPrefix ? repr.substr(0, index) : repr;
224      const int ret = getaddrinfo(ipAddress.c_str(), nullptr, &hints, &res);
225      if (ret != 0) return false;
226  
227      // Check the address family.
228      int family = res[0].ai_family;
229      freeaddrinfo(res);
230      if (family != expectedFamily) return false;
231      if (!isPrefix) return true;
232  
233      // Parse the prefix length.
234      const char* prefixString = repr.c_str() + index + 1;
235      if (!isdigit(*prefixString)) return false;
236      char* endptr;
237      unsigned long prefixlen = strtoul(prefixString, &endptr, 10);
238      if (*endptr != '\0') return false;
239  
240      uint8_t maxlen = (family == AF_INET) ? 32 : 128;
241      if (prefixlen > maxlen) return false;
242  
243      return true;
244  }
245  
246  }  // namespace aidl::android::hardware::tetheroffload::impl::example
247