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