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 #include "wifi_direct_ip_manager.h"
16 #include <arpa/inet.h>
17 #include "securec.h"
18 #include "conn_log.h"
19 #include "net_conn_client.h"
20 #include "softbus_error_code.h"
21 #include "softbus_socket.h"
22 #include "utils/wifi_direct_anonymous.h"
23 #include "utils/wifi_direct_utils.h"
24 
25 namespace OHOS::SoftBus {
26 static constexpr int32_t U_L_BIT = 0x2;
27 static constexpr uint8_t INSERT_BYTE_0 = 0xff;
28 static constexpr uint8_t INSERT_BYTE_1 = 0xfe;
29 static constexpr int INSERT_POS = 3;
30 static constexpr int IPV6_PREFIX = 64;
31 
32 static constexpr int32_t HML_IP_NET_END = 256;
33 static constexpr char HML_IP_PREFIX[] = "172.30.";
34 static constexpr char HML_IP_SOURCE_SUFFIX[] = ".2";
35 static constexpr char HML_IP_SINK_SUFFIX[] = ".1";
36 
Init()37 void WifiDirectIpManager::Init()
38 {
39     CONN_LOGI(CONN_WIFI_DIRECT, "enter");
40 }
41 
ApplyIpv6(const std::string & mac)42 std::string WifiDirectIpManager::ApplyIpv6(const std::string &mac)
43 {
44     CONN_CHECK_AND_RETURN_RET_LOGE(!mac.empty(), "", CONN_WIFI_DIRECT, "mac is null");
45     auto array = WifiDirectUtils::MacStringToArray(mac);
46     if ((array[0] & U_L_BIT) == 0) {
47         array[0] |= U_L_BIT;
48     } else {
49         array[0] &= ~U_L_BIT;
50     }
51     array.insert(array.begin() + INSERT_POS, { INSERT_BYTE_0, INSERT_BYTE_1 });
52     char ip[IP_STR_MAX_LEN] {};
53     auto ret = sprintf_s(ip, sizeof(ip), "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x%%chba0",
54                          array[0], array[1], array[2], array[3], array[4], array[5], array[6], array[7]);
55     CONN_CHECK_AND_RETURN_RET_LOGE(ret > 0, "", CONN_WIFI_DIRECT, "format failed");
56 
57     SoftBusSockAddrIn6 addrIn6 {};
58     if (Ipv6AddrToAddrIn(&addrIn6, ip, 0) != SOFTBUS_OK) {
59         CONN_LOGE(CONN_WIFI_DIRECT, "to addrIn6 failed");
60         return "";
61     }
62     char result[IP_STR_MAX_LEN] {};
63     if (Ipv6AddrInToAddr(&addrIn6, result, sizeof(result)) != SOFTBUS_OK) {
64         CONN_LOGE(CONN_WIFI_DIRECT, "to ip string failed");
65         return "";
66     }
67     CONN_LOGI(CONN_WIFI_DIRECT, "scopeId=%{public}u", addrIn6.sin6ScopeId);
68     std::string finalResult = result;
69     if (addrIn6.sin6ScopeId == 0) {
70         finalResult += "%chba0";
71     }
72     return finalResult;
73 }
74 
ApplyIpv4(const std::vector<Ipv4Info> & localArray,const std::vector<Ipv4Info> & remoteArray,Ipv4Info & source,Ipv4Info & sink)75 int32_t WifiDirectIpManager::ApplyIpv4(
76     const std::vector<Ipv4Info> &localArray, const std::vector<Ipv4Info> &remoteArray, Ipv4Info &source, Ipv4Info &sink)
77 {
78     std::string subNet = ApplySubNet(localArray, remoteArray);
79     CONN_CHECK_AND_RETURN_RET_LOGE(
80         !subNet.empty(), SOFTBUS_CONN_APPLY_SUBNET_FAIL, CONN_WIFI_DIRECT, "apply subnet failed");
81 
82     std::string sourceIp = subNet + HML_IP_SOURCE_SUFFIX;
83     std::string sinkIp = subNet + HML_IP_SINK_SUFFIX;
84     int32_t ret = source.FromIpString(sourceIp);
85     CONN_CHECK_AND_RETURN_RET_LOGW(
86         ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "source ip to ipv4 failed");
87     ret = sink.FromIpString(sinkIp);
88     CONN_CHECK_AND_RETURN_RET_LOGW(
89         ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "sink ip to ipv4 failed");
90 
91     return SOFTBUS_OK;
92 }
93 
ApplySubNet(const std::vector<Ipv4Info> & localArray,const std::vector<Ipv4Info> & remoteArray)94 std::string WifiDirectIpManager::ApplySubNet(
95     const std::vector<Ipv4Info> &localArray, const std::vector<Ipv4Info> &remoteArray)
96 {
97     std::array<bool, HML_IP_NET_END> bookMark {};
98     bookMark[0] = true;
99     std::string subNet;
100     for (const auto &ipv4 : localArray) {
101         bookMark[ipv4.GetSubNet()] = true;
102     }
103     for (const auto &ipv4 : remoteArray) {
104         bookMark[ipv4.GetSubNet()] = true;
105     }
106     for (uint32_t i = 0; i < bookMark.size(); i++) {
107         if (!bookMark[i]) {
108             subNet = HML_IP_PREFIX + std::to_string(i);
109             return subNet;
110         }
111     }
112     return "";
113 }
114 
ConfigIpv6(const std::string & interface,const std::string & ip)115 int32_t WifiDirectIpManager::ConfigIpv6(const std::string &interface, const std::string &ip)
116 {
117     auto ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().AddInterfaceAddress(interface, ip, IPV6_PREFIX);
118     CONN_CHECK_AND_RETURN_RET_LOGE(
119         ret == 0, SOFTBUS_CONN_CONFIG_IPV6_CONFIG_IP_FAILED, CONN_WIFI_DIRECT, "add ip failed");
120     return SOFTBUS_OK;
121 }
122 
ConfigIpv4(const std::string & interface,const Ipv4Info & local,const Ipv4Info & remote,const std::string & remoteMac)123 int32_t WifiDirectIpManager::ConfigIpv4(
124     const std::string &interface, const Ipv4Info &local, const Ipv4Info &remote, const std::string &remoteMac)
125 {
126     std::string localIpStr = local.ToIpString();
127     CONN_CHECK_AND_RETURN_RET_LOGE(
128         !localIpStr.empty(), SOFTBUS_CONN_CONVERT_LOCAL_IP_FAIL, CONN_WIFI_DIRECT, "convert local ip failed");
129     std::string remoteIpStr = remote.ToIpString();
130     CONN_CHECK_AND_RETURN_RET_LOGE(
131         !remoteIpStr.empty(), SOFTBUS_CONN_CONVERT_REMOTE_IP_FAIL, CONN_WIFI_DIRECT, "convert remote ip failed");
132     CONN_LOGI(CONN_WIFI_DIRECT, "localIp=%{public}s, remoteIp=%{public}s, remoteMac=%{public}s",
133         WifiDirectAnonymizeIp(localIpStr).c_str(), WifiDirectAnonymizeIp(remoteIpStr).c_str(),
134         WifiDirectAnonymizeMac(remoteMac).c_str());
135 
136     int32_t ret = AddInterfaceAddress(interface, localIpStr, local.GetPrefixLength());
137     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "add ip failed");
138 
139     ret = AddStaticArp(interface, remoteIpStr, remoteMac);
140     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "add static arp failed");
141     return SOFTBUS_OK;
142 }
143 
ReleaseIpv4(const std::string & interface,const Ipv4Info & local,const Ipv4Info & remote,const std::string & remoteMac)144 void WifiDirectIpManager::ReleaseIpv4(
145     const std::string &interface, const Ipv4Info &local, const Ipv4Info &remote, const std::string &remoteMac)
146 {
147     std::string localIpStr = local.ToIpString();
148     CONN_CHECK_AND_RETURN_LOGE(!localIpStr.empty(), CONN_WIFI_DIRECT, "convert local ip failed");
149     std::string remoteIpStr = remote.ToIpString();
150     CONN_CHECK_AND_RETURN_LOGE(!remoteIpStr.empty(), CONN_WIFI_DIRECT, "convert remote ip failed");
151 
152     CONN_LOGI(CONN_WIFI_DIRECT, "localIp=%{public}s, remoteIp=%{public}s, remoteMac=%{public}s",
153         WifiDirectAnonymizeIp(localIpStr).c_str(), WifiDirectAnonymizeIp(remoteIpStr).c_str(),
154         WifiDirectAnonymizeMac(remoteMac).c_str());
155 
156     if (DeleteInterfaceAddress(interface, localIpStr, local.GetPrefixLength()) != SOFTBUS_OK) {
157         CONN_LOGE(CONN_WIFI_DIRECT, "delete ip failed. ip=%{public}s", WifiDirectAnonymizeIp(localIpStr).c_str());
158     }
159 
160     if (DeleteStaticArp(interface, remoteIpStr, remoteMac) != SOFTBUS_OK) {
161         CONN_LOGE(CONN_WIFI_DIRECT, "delete arp failed. remoteIp=%{public}s, remoteMac=%{public}s",
162             WifiDirectAnonymizeIp(remoteIpStr).c_str(), WifiDirectAnonymizeMac(remoteMac).c_str());
163     }
164 }
165 
ClearAllIpv4()166 void WifiDirectIpManager::ClearAllIpv4()
167 {
168     auto localIpv4Array = WifiDirectUtils::GetLocalIpv4Infos();
169     for (const auto &ipv4 : localIpv4Array) {
170         std::string ipStr = ipv4.ToIpString();
171         if (DeleteInterfaceAddress("chba0", ipStr, ipv4.GetPrefixLength()) != SOFTBUS_OK) {
172             CONN_LOGE(CONN_WIFI_DIRECT, "delete ip failed. ip=%{public}s", WifiDirectAnonymizeIp(ipStr).c_str());
173         }
174     }
175 }
176 
AddInterfaceAddress(const std::string & interface,const std::string & ipString,int32_t prefixLength)177 int32_t WifiDirectIpManager::AddInterfaceAddress(
178     const std::string &interface, const std::string &ipString, int32_t prefixLength)
179 {
180     std::string gateWay;
181     int32_t ret = GetNetworkGateWay(ipString, gateWay);
182     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "get gate way failed");
183     std::string destination;
184     ret = GetNetworkDestination(ipString, destination);
185     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_WIFI_DIRECT, "get destination failed");
186 
187     ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().AddInterfaceAddress(interface, ipString, prefixLength);
188     CONN_CHECK_AND_RETURN_RET_LOGE(
189         ret == NetManagerStandard::NETMANAGER_SUCCESS, ret, CONN_WIFI_DIRECT, "add ip failed ret=%{public}d", ret);
190     ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().AddNetworkRoute(
191         LOCAL_NETWORK_ID, interface, destination, gateWay);
192     CONN_CHECK_AND_RETURN_RET_LOGE(
193         ret == NetManagerStandard::NETMANAGER_SUCCESS, ret, CONN_WIFI_DIRECT, "add route failed ret=%{public}d", ret);
194     return SOFTBUS_OK;
195 }
196 
DeleteInterfaceAddress(const std::string & interface,const std::string & ipString,int32_t prefixLength)197 int32_t WifiDirectIpManager::DeleteInterfaceAddress(
198     const std::string &interface, const std::string &ipString, int32_t prefixLength)
199 {
200     std::string gateWay;
201     int32_t ret = GetNetworkGateWay(ipString, gateWay);
202     CONN_CHECK_AND_RETURN_RET_LOGE(ret == 0, ret, CONN_WIFI_DIRECT, "get gate way failed");
203     std::string destination;
204     ret = GetNetworkDestination(ipString, destination);
205     CONN_CHECK_AND_RETURN_RET_LOGE(ret == 0, ret, CONN_WIFI_DIRECT, "get destination failed");
206     ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().RemoveNetworkRoute(
207         LOCAL_NETWORK_ID, interface, destination, gateWay);
208     if (ret != NetManagerStandard::NETMANAGER_SUCCESS) {
209         CONN_LOGE(CONN_WIFI_DIRECT, "remove route failed ret=%{public}d", ret);
210     }
211     ret = OHOS::NetManagerStandard::NetConnClient::GetInstance().DelInterfaceAddress(interface, ipString, prefixLength);
212     if (ret != NetManagerStandard::NETMANAGER_SUCCESS) {
213         CONN_LOGE(CONN_WIFI_DIRECT, "delete ip failed ret=%{public}d", ret);
214     }
215     return SOFTBUS_OK;
216 }
217 
AddStaticArp(const std::string & interface,const std::string & ipString,const std::string & macString)218 int32_t WifiDirectIpManager::AddStaticArp(
219     const std::string &interface, const std::string &ipString, const std::string &macString)
220 {
221     return OHOS::NetManagerStandard::NetConnClient::GetInstance().AddStaticArp(ipString, macString, interface);
222 }
223 
DeleteStaticArp(const std::string & interface,const std::string & ipString,const std::string & macString)224 int32_t WifiDirectIpManager::DeleteStaticArp(
225     const std::string &interface, const std::string &ipString, const std::string &macString)
226 {
227     return OHOS::NetManagerStandard::NetConnClient::GetInstance().DelStaticArp(ipString, macString, interface);
228 }
229 
GetNetworkGateWay(const std::string & ipString,std::string & gateWay)230 int32_t WifiDirectIpManager::GetNetworkGateWay(const std::string &ipString, std::string &gateWay)
231 {
232     auto pos = ipString.find_last_of('.');
233     CONN_CHECK_AND_RETURN_RET_LOGE(
234         pos != std::string::npos, SOFTBUS_CONN_FIND_DOT_FAIL, CONN_WIFI_DIRECT, "can't find dot");
235     gateWay = ipString.substr(0, pos) + ".1";
236     CONN_LOGI(CONN_WIFI_DIRECT, "gateWay=%{public}s", WifiDirectAnonymizeIp(gateWay).c_str());
237     return SOFTBUS_OK;
238 }
239 
GetNetworkDestination(const std::string & ipString,std::string & destination)240 int32_t WifiDirectIpManager::GetNetworkDestination(const std::string &ipString, std::string &destination)
241 {
242     auto pos = ipString.find_last_of('.');
243     CONN_CHECK_AND_RETURN_RET_LOGE(
244         pos != std::string::npos, SOFTBUS_CONN_FIND_DOT_FAIL, CONN_WIFI_DIRECT, "can't find dot");
245     destination = ipString.substr(0, pos) + ".0/24";
246     CONN_LOGI(CONN_WIFI_DIRECT, "destination=%{public}s", WifiDirectAnonymizeIp(destination).c_str());
247     return SOFTBUS_OK;
248 }
249 } // namespace OHOS::SoftBus
250