1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <algorithm>
17 #include <map>
18 #include <net/if.h>
19 #include <sys/socket.h>
20 #include <tuple>
21 #include <utility>
22
23 #include "clat_constants.h"
24 #include "clat_manager.h"
25 #include "clat_utils.h"
26 #include "clatd.h"
27 #include "fwmark.h"
28 #include "net_manager_constants.h"
29 #include "net_manager_native.h"
30 #include "netnative_log_wrapper.h"
31 #include "network_permission.h"
32
33 namespace OHOS {
34 namespace nmd {
35 using namespace OHOS::NetManagerStandard;
36 ClatManager::ClatManager() = default;
37
ClatStart(const std::string & v6Iface,int32_t netId,const std::string & nat64PrefixStr,NetManagerNative * netsysService)38 int32_t ClatManager::ClatStart(const std::string &v6Iface, int32_t netId, const std::string &nat64PrefixStr,
39 NetManagerNative *netsysService)
40 {
41 NETNATIVE_LOGI("Start Clatd on %{public}s", v6Iface.c_str());
42 if (clatdTrackers_.find(v6Iface) != clatdTrackers_.end()) {
43 NETNATIVE_LOGW("Clatd is already running on %{public}s", v6Iface.c_str());
44 return NETMANAGER_ERR_OPERATION_FAILED;
45 }
46
47 if (netsysService == nullptr) {
48 NETNATIVE_LOGW("NetManagerNative pointer is null");
49 return NETMANAGER_ERR_INVALID_PARAMETER;
50 }
51
52 uint32_t fwmark = GetFwmark(netId);
53 INetAddr v4Addr;
54 INetAddr v6Addr;
55 int32_t ret = GenerateClatSrcAddr(v6Iface, fwmark, nat64PrefixStr, v4Addr, v6Addr);
56 if (ret != NETMANAGER_SUCCESS) {
57 NETNATIVE_LOGW("Fail to get source addresses for clat");
58 return ret;
59 }
60
61 int tunFd = -1;
62 std::string tunIface = std::string(CLAT_PREFIX) + v6Iface;
63 ret = CreateAndConfigureTunIface(v6Iface, tunIface, v4Addr, netsysService, tunFd);
64 if (ret != NETMANAGER_SUCCESS) {
65 NETNATIVE_LOGW("Fail to create and configure tun interface for clat");
66 return ret;
67 }
68
69 int readSock6 = -1;
70 int writeSock6 = -1;
71 ret = CreateAndConfigureClatSocket(v6Iface, v6Addr, fwmark, readSock6, writeSock6);
72 if (ret != NETMANAGER_SUCCESS) {
73 close(tunFd);
74 NETNATIVE_LOGW("Fail to create and configure read/write sockets for clat");
75 return ret;
76 }
77
78 clatds_.emplace(
79 std::piecewise_construct, std::forward_as_tuple(v6Iface),
80 std::forward_as_tuple(tunFd, readSock6, writeSock6, v6Iface, nat64PrefixStr, v4Addr.address_, v6Addr.address_));
81 clatds_[v6Iface].Start();
82
83 ret = RouteManager::AddClatTunInterface(tunIface, DEFAULT_V4_ADDR, v4Addr.address_);
84 if (ret != NETMANAGER_SUCCESS) {
85 close(tunFd);
86 close(readSock6);
87 close(writeSock6);
88 NETNATIVE_LOGW("Add route on %{public}s failed", tunIface.c_str());
89 return NETMANAGER_ERR_OPERATION_FAILED;
90 }
91
92 clatdTrackers_[v6Iface] = {v6Iface, tunIface, v4Addr, v6Addr, nat64PrefixStr, tunFd, readSock6, writeSock6};
93
94 return NETMANAGER_SUCCESS;
95 }
96
ClatStop(const std::string & v6Iface)97 int32_t ClatManager::ClatStop(const std::string &v6Iface)
98 {
99 NETNATIVE_LOGI("Stop Clatd on %{public}s", v6Iface.c_str());
100 if (clatdTrackers_.find(v6Iface) == clatdTrackers_.end()) {
101 NETNATIVE_LOGW("Clatd has not started on %{public}s", v6Iface.c_str());
102 return NETMANAGER_ERR_OPERATION_FAILED;
103 }
104 NETNATIVE_LOGI("Stopping clatd on %{public}s", v6Iface.c_str());
105
106 RouteManager::RemoveClatTunInterface(clatdTrackers_[v6Iface].tunIface);
107
108 clatds_[v6Iface].Stop();
109 clatds_.erase(v6Iface);
110
111 FreeTunV4Addr(clatdTrackers_[v6Iface].v4Addr.address_);
112
113 close(clatdTrackers_[v6Iface].tunFd);
114 close(clatdTrackers_[v6Iface].readSock6);
115 close(clatdTrackers_[v6Iface].writeSock6);
116 clatdTrackers_.erase(v6Iface);
117
118 NETNATIVE_LOGI("clatd on %{public}s stopped", v6Iface.c_str());
119 return NETMANAGER_SUCCESS;
120 }
121
GetFwmark(int32_t netId)122 uint32_t ClatManager::GetFwmark(int32_t netId)
123 {
124 Fwmark mark;
125 mark.netId = static_cast<uint16_t>(netId);
126 mark.explicitlySelected = true;
127 mark.protectedFromVpn = true;
128 NetworkPermission permission = NetworkPermission::PERMISSION_SYSTEM;
129 mark.permission = permission;
130 mark.uidBillingDone = false;
131 return mark.intValue;
132 }
133
GenerateClatSrcAddr(const std::string & v6Iface,uint32_t fwmark,const std::string & nat64PrefixStr,INetAddr & v4Addr,INetAddr & v6Addr)134 int32_t ClatManager::GenerateClatSrcAddr(const std::string &v6Iface, uint32_t fwmark, const std::string &nat64PrefixStr,
135 INetAddr &v4Addr, INetAddr &v6Addr)
136 {
137 std::string v4AddrStr;
138 int32_t ret = SelectIpv4Address(std::string(INIT_V4ADDR_STRING), INIT_V4ADDR_PREFIX_BIT_LEN, v4AddrStr);
139 if (ret != NETMANAGER_SUCCESS) {
140 NETNATIVE_LOGW("no IPv4 addresses were available for clat");
141 return ret;
142 }
143 v4Addr.type_ = INetAddr::IPV4;
144 v4Addr.family_ = AF_INET;
145 v4Addr.address_ = v4AddrStr;
146
147 std::string v6AddrStr;
148 ret = GenerateIpv6Address(v6Iface, v4AddrStr, nat64PrefixStr, fwmark, v6AddrStr);
149 if (ret != NETMANAGER_SUCCESS) {
150 NETNATIVE_LOGW("no IPv6 addresses were available for clat");
151 return ret;
152 }
153 v6Addr.type_ = INetAddr::IPV6;
154 v6Addr.family_ = AF_INET6;
155 v6Addr.address_ = v6AddrStr;
156
157 return NETMANAGER_SUCCESS;
158 }
159
CreateAndConfigureTunIface(const std::string & v6Iface,const std::string & tunIface,const INetAddr & v4Addr,NetManagerNative * netsysService,int & tunFd)160 int32_t ClatManager::CreateAndConfigureTunIface(const std::string &v6Iface, const std::string &tunIface,
161 const INetAddr &v4Addr, NetManagerNative *netsysService, int &tunFd)
162 {
163 int32_t ret = CreateTunInterface(tunIface, tunFd);
164 if (ret != NETMANAGER_SUCCESS) {
165 NETNATIVE_LOGW("Create tun interface %{public}s failed", tunIface.c_str());
166 return ret;
167 }
168
169 uint32_t tunIfIndex = if_nametoindex(tunIface.c_str());
170 if (tunIfIndex == INVALID_IFINDEX) {
171 close(tunFd);
172 NETNATIVE_LOGW("Fail to get interface index for interface %{public}s", tunIface.c_str());
173 return NETMANAGER_ERR_OPERATION_FAILED;
174 }
175
176 ret = netsysService->SetEnableIpv6(tunIface, 0);
177 if (ret != NETMANAGER_SUCCESS) {
178 close(tunFd);
179 NETNATIVE_LOGW("SetEnableIpv6 on %{public}s failed", tunIface.c_str());
180 return NETMANAGER_ERR_OPERATION_FAILED;
181 }
182
183 int mtu = CLAT_IPV6_MIN_MTU - MTU_DELTA;
184 ret = netsysService->SetInterfaceMtu(tunIface, mtu);
185 if (ret != NETMANAGER_SUCCESS) {
186 close(tunFd);
187 NETNATIVE_LOGW("Set MTU on %{public}s failed", tunIface.c_str());
188 return NETMANAGER_ERR_OPERATION_FAILED;
189 }
190
191 int v4AddrPrefixLen = V4ADDR_BIT_LEN;
192
193 OHOS::nmd::InterfaceConfigurationParcel ifConfig;
194 ifConfig.ifName = tunIface;
195 ifConfig.hwAddr = "";
196 ifConfig.ipv4Addr = v4Addr.address_;
197 ifConfig.prefixLength = v4AddrPrefixLen;
198
199 ifConfig.flags.emplace_back(IFACE_LINK_UP);
200 netsysService->SetInterfaceConfig(ifConfig);
201
202 ret = SetTunInterfaceAddress(tunIface, v4Addr.address_, v4AddrPrefixLen);
203 if (ret != NETMANAGER_SUCCESS) {
204 close(tunFd);
205 NETNATIVE_LOGW("Set tun interface address on %{public}s failed", tunIface.c_str());
206 return NETMANAGER_ERR_OPERATION_FAILED;
207 }
208
209 return NETMANAGER_SUCCESS;
210 }
211
CreateAndConfigureClatSocket(const std::string & v6Iface,const INetAddr & v6Addr,uint32_t fwmark,int & readSock6,int & writeSock6)212 int32_t ClatManager::CreateAndConfigureClatSocket(const std::string &v6Iface, const INetAddr &v6Addr, uint32_t fwmark,
213 int &readSock6, int &writeSock6)
214 {
215 int32_t ret = OpenPacketSocket(readSock6);
216 if (ret != NETMANAGER_SUCCESS) {
217 NETNATIVE_LOGW("Open packet socket failed");
218 return ret;
219 }
220
221 ret = OpenRawSocket6(fwmark, writeSock6);
222 if (ret != NETMANAGER_SUCCESS) {
223 close(readSock6);
224 NETNATIVE_LOGW("Open raw socket failed");
225 return ret;
226 }
227
228 uint32_t v6IfIndex = if_nametoindex(v6Iface.c_str());
229 if (v6IfIndex == INVALID_IFINDEX) {
230 close(readSock6);
231 close(writeSock6);
232 NETNATIVE_LOGW("Fail to get interface index for interface %{public}s", v6Iface.c_str());
233 return NETMANAGER_ERR_OPERATION_FAILED;
234 }
235
236 ret = ConfigureWriteSocket(writeSock6, v6Iface);
237 if (ret != NETMANAGER_SUCCESS) {
238 close(readSock6);
239 close(writeSock6);
240 NETNATIVE_LOGW("Configure write sockopt failed");
241 return ret;
242 }
243
244 ret = ConfigureReadSocket(readSock6, v6Addr.address_, v6IfIndex);
245 if (ret != NETMANAGER_SUCCESS) {
246 close(readSock6);
247 close(writeSock6);
248 NETNATIVE_LOGW("Configure read socket failed");
249 return ret;
250 }
251
252 return NETMANAGER_SUCCESS;
253 }
254 } // namespace nmd
255 } // namespace OHOS