1 /*
2 * Copyright (c) 2023 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 "wifi_direct_network_utils.h"
17 #include <string.h>
18 #include <strings.h>
19 #include <arpa/inet.h>
20 #include <net/if.h>
21 #include <netinet/in.h>
22 #include <sys/socket.h>
23 #include <sys/ioctl.h>
24 #include <unistd.h>
25 #include <ifaddrs.h>
26
27 #include "securec.h"
28 #include "softbus_log.h"
29 #include "softbus_error_code.h"
30 #include "softbus_adapter_mem.h"
31 #include "wifi_direct_types.h"
32 #include "wifi_direct_ipv4_info.h"
33 #include "wifi_direct_anonymous.h"
34
35 #define LOG_LABEL "[WifiDirect] WifiDirectNetworkUtils: "
36
SplitString(char * input,char * splitter,char ** outputArray,size_t * outputArraySize)37 static int32_t SplitString(char *input, char *splitter, char **outputArray, size_t *outputArraySize)
38 {
39 char *context = NULL;
40 char *subString = strtok_s(input, splitter, &context);
41 CONN_CHECK_AND_RETURN_RET_LOG(subString != NULL, SOFTBUS_ERR, LOG_LABEL "split failed");
42
43 size_t count = 0;
44 do {
45 outputArray[count] = subString;
46 subString = strtok_s(NULL, splitter, &context);
47 count++;
48 } while (subString && count < *outputArraySize);
49
50 *outputArraySize = count;
51 return SOFTBUS_OK;
52 }
53
ChannelToFrequency(int32_t channel)54 static int32_t ChannelToFrequency(int32_t channel)
55 {
56 CLOGI(LOG_LABEL "channel=%d", channel);
57 if (channel >= CHANNEL_2G_FIRST && channel <= CHANNEL_2G_LAST) {
58 return (channel - CHANNEL_2G_FIRST) * FREQUENCY_STEP + FREQUENCY_2G_FIRST;
59 } else if (channel >= CHANNEL_5G_FIRST && channel <= CHANNEL_5G_LAST) {
60 return (channel - CHANNEL_5G_FIRST) * FREQUENCY_STEP + FREQUENCY_5G_FIRST;
61 } else {
62 return FREQUENCY_INVALID;
63 }
64 }
65
ChannelListToString(int32_t * channelArray,size_t channelArraySize,char * channelListString,size_t inSize)66 static int32_t ChannelListToString(int32_t *channelArray, size_t channelArraySize,
67 char *channelListString, size_t inSize)
68 {
69 int32_t ret;
70 size_t outLen = 0;
71 for (size_t i = 0; i < channelArraySize; i++) {
72 if (i == 0) {
73 ret = sprintf_s(channelListString + outLen, inSize - outLen, "%d", channelArray[i]);
74 } else {
75 ret = sprintf_s(channelListString + outLen, inSize - outLen, "##%d", channelArray[i]);
76 }
77 CONN_CHECK_AND_RETURN_RET_LOG(ret > 0, SOFTBUS_ERR, LOG_LABEL "format channel failed");
78 outLen += (size_t)ret;
79 }
80
81 return SOFTBUS_OK;
82 }
83
StringToChannelList(char * channelListString,int32_t * channelArray,size_t * channelArraySize)84 static int32_t StringToChannelList(char *channelListString, int32_t *channelArray, size_t *channelArraySize)
85 {
86 CONN_CHECK_AND_RETURN_RET_LOG(*channelArraySize <= CHANNEL_ARRAY_NUM_MAX, SOFTBUS_INVALID_PARAM,
87 LOG_LABEL "size too large");
88
89 CLOGI(LOG_LABEL "%s", channelListString);
90 char *channelStrings[CHANNEL_ARRAY_NUM_MAX];
91 int32_t ret = SplitString(channelListString, "##", channelStrings, channelArraySize);
92 CONN_CHECK_AND_RETURN_RET_LOG(ret == SOFTBUS_OK, ret, LOG_LABEL "split channel failed");
93 CLOGI(LOG_LABEL "%d", *channelArraySize);
94
95 char *end = NULL;
96 for (size_t i = 0; i < *channelArraySize; i++) {
97 channelArray[i] = (int32_t)strtol(channelStrings[i], &end, DECIMAL_BASE);
98 CONN_CHECK_AND_RETURN_RET_LOG(channelArray[i] > 0, SOFTBUS_ERR, LOG_LABEL "convert to int failed");
99 }
100 return SOFTBUS_OK;
101 }
102
Is2GBand(int32_t frequency)103 static bool Is2GBand(int32_t frequency)
104 {
105 return frequency >= FREQUENCY_2G_FIRST && frequency <= FREQUENCY_2G_LAST;
106 }
107
Is5GBand(int32_t frequency)108 static bool Is5GBand(int32_t frequency)
109 {
110 return frequency >= FREQUENCY_5G_FIRST && frequency <= FREQUENCY_5G_LAST;
111 }
112
FrequencyToChannel(int32_t frequency)113 static int32_t FrequencyToChannel(int32_t frequency)
114 {
115 if (Is2GBand(frequency)) {
116 return (frequency - FREQUENCY_2G_FIRST) / FREQUENCY_STEP + CHANNEL_2G_FIRST;
117 } else if (Is5GBand(frequency)) {
118 return (frequency - FREQUENCY_5G_FIRST) / FREQUENCY_STEP + CHANNEL_5G_FIRST;
119 } else {
120 return CHANNEL_INVALID;
121 }
122 }
123
IsInChannelList(int32_t channel,const int32_t * channelArray,size_t channelNum)124 static bool IsInChannelList(int32_t channel, const int32_t *channelArray, size_t channelNum)
125 {
126 for (size_t i = 0; i < channelNum; i++) {
127 if (channel == channelArray[i]) {
128 return true;
129 }
130 }
131 return false;
132 }
133
GetInterfaceIpString(const char * interface,char * ipString,int32_t ipStringSize)134 static int32_t GetInterfaceIpString(const char *interface, char *ipString, int32_t ipStringSize)
135 {
136 CONN_CHECK_AND_RETURN_RET_LOG(interface, SOFTBUS_INVALID_PARAM, "interface is null");
137 CONN_CHECK_AND_RETURN_RET_LOG(ipString, SOFTBUS_INVALID_PARAM, "ipString is null");
138 CLOGI(LOG_LABEL "interface=%s", interface);
139
140 int32_t socketFd = socket(AF_INET, SOCK_DGRAM, 0);
141 CONN_CHECK_AND_RETURN_RET_LOG(socketFd >= 0, SOFTBUS_ERR, LOG_LABEL "open socket failed");
142
143 struct ifreq request;
144 (void)memset_s(&request, sizeof(request), 0, sizeof(request));
145 int32_t ret = strcpy_s(request.ifr_name, sizeof(request.ifr_name), interface);
146 if (ret != EOK) {
147 CLOGE(LOG_LABEL "copy interface name failed");
148 close(socketFd);
149 return SOFTBUS_ERR;
150 }
151
152 ret = ioctl(socketFd, SIOCGIFADDR, &request);
153 close(socketFd);
154 CONN_CHECK_AND_RETURN_RET_LOG(ret >= 0, SOFTBUS_ERR, LOG_LABEL "get ifr conf failed ret=%d", ret);
155
156 struct sockaddr_in *sockAddrIn = (struct sockaddr_in *)&request.ifr_addr;
157 if (!inet_ntop(sockAddrIn->sin_family, &sockAddrIn->sin_addr, ipString, ipStringSize)) {
158 CLOGE(LOG_LABEL "inet_ntop failed");
159 return SOFTBUS_ERR;
160 }
161 return SOFTBUS_OK;
162 }
163
IpAddrToString(uint32_t addr,char * addrString,size_t addrStringSize)164 int32_t IpAddrToString(uint32_t addr, char *addrString, size_t addrStringSize)
165 {
166 addr = ntohl(addr);
167 const char *ret = inet_ntop(AF_INET, &addr, addrString, addrStringSize);
168 CONN_CHECK_AND_RETURN_RET_LOG(ret, SOFTBUS_ERR, LOG_LABEL "inet_ntop failed");
169 return SOFTBUS_OK;
170 }
171
IpStringToAddr(const char * addrString,uint32_t * addrArray)172 static int32_t IpStringToAddr(const char *addrString, uint32_t *addrArray)
173 {
174 if (inet_pton(AF_INET, addrString, addrArray) == 1) {
175 *addrArray = htonl(*addrArray);
176 return SOFTBUS_OK;
177 }
178 CLOGE(LOG_LABEL "inet_pton failed");
179 return SOFTBUS_ERR;
180 }
181
IpStringToIntArray(const char * addrString,uint32_t * addrArray,size_t addrArraySize)182 static int32_t IpStringToIntArray(const char *addrString, uint32_t *addrArray, size_t addrArraySize)
183 {
184 CONN_CHECK_AND_RETURN_RET_LOG(addrString, SOFTBUS_INVALID_PARAM, "addrString is null");
185 CONN_CHECK_AND_RETURN_RET_LOG(addrArraySize >= IPV4_ADDR_ARRAY_LEN, SOFTBUS_INVALID_PARAM, "array to small");
186 CLOGI(LOG_LABEL, "%s", addrString);
187
188 int32_t ret = sscanf_s(addrString, "%u.%u.%u.%u", addrArray, addrArray + 1, addrArray + 2, addrArray + 3);
189 CONN_CHECK_AND_RETURN_RET_LOG(ret > 0, SOFTBUS_ERR, LOG_LABEL "scan ip number failed");
190 return SOFTBUS_OK;
191 }
192
MacStringToArray(const char * macString,uint8_t * array,size_t * arraySize)193 static int32_t MacStringToArray(const char *macString, uint8_t *array, size_t *arraySize)
194 {
195 CONN_CHECK_AND_RETURN_RET_LOG(*arraySize >= MAC_ADDR_ARRAY_SIZE, SOFTBUS_INVALID_PARAM, LOG_LABEL "size too small");
196 char *subStrings[MAC_ADDR_ARRAY_SIZE];
197 size_t subStringsSize = MAC_ADDR_ARRAY_SIZE;
198
199 char *macStringCopy = strdup(macString);
200 CONN_CHECK_AND_RETURN_RET_LOG(macStringCopy, SOFTBUS_ERR, LOG_LABEL "dup mac string failed");
201 int32_t ret = SplitString(macStringCopy, ":", subStrings, &subStringsSize);
202 if (ret != SOFTBUS_OK) {
203 CLOGE("split string failed");
204 SoftBusFree(macStringCopy);
205 return SOFTBUS_ERR;
206 }
207
208 char *end = NULL;
209 for (size_t i = 0; i < subStringsSize; i++) {
210 ret = (int32_t)strtol(subStrings[i], &end, HEX_BASE);
211 if (ret < 0) {
212 CLOGE("convert to number failed");
213 SoftBusFree(macStringCopy);
214 return SOFTBUS_ERR;
215 }
216 array[i] = (uint8_t)ret;
217 }
218
219 SoftBusFree(macStringCopy);
220 *arraySize = subStringsSize;
221 return SOFTBUS_OK;
222 }
223
MacArrayToString(const uint8_t * array,size_t arraySize,char * macString,size_t macStringSize)224 static int32_t MacArrayToString(const uint8_t *array, size_t arraySize, char *macString, size_t macStringSize)
225 {
226 CONN_CHECK_AND_RETURN_RET_LOG(arraySize >= MAC_ADDR_ARRAY_SIZE, SOFTBUS_INVALID_PARAM, LOG_LABEL "mac len invalid");
227 size_t ret = sprintf_s(macString, macStringSize, "%02x:%02x:%02x:%02x:%02x:%02x",
228 array[0], array[1], array[2], array[3], array[4], array[5]);
229 CONN_CHECK_AND_RETURN_RET_LOG(ret > 0, SOFTBUS_ERR, LOG_LABEL "format mac failed");
230 return SOFTBUS_OK;
231 }
232
GetLocalIpv4InfoArray(struct WifiDirectIpv4Info * info,size_t * size)233 static int32_t GetLocalIpv4InfoArray(struct WifiDirectIpv4Info *info, size_t *size)
234 {
235 struct ifaddrs *ifAddr = NULL;
236 if (getifaddrs(&ifAddr) == -1) {
237 CLOGE(LOG_LABEL "getifaddrs failed, errno: %d", errno);
238 return SOFTBUS_ERR;
239 }
240
241 struct ifaddrs *ifa = NULL;
242 size_t count = 0;
243 for (ifa = ifAddr; ifa != NULL && count < *size; ifa = ifa->ifa_next) {
244 if (ifa->ifa_addr == NULL || ifa->ifa_addr->sa_family != AF_INET || ifa->ifa_netmask == NULL) {
245 continue;
246 }
247
248 char addrString[IP_ADDR_STR_LEN];
249 struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
250 info[count].address = ntohl(addr->sin_addr.s_addr);
251 inet_ntop(AF_INET, &addr->sin_addr.s_addr, addrString, sizeof(addrString));
252
253 addr = (struct sockaddr_in *)ifa->ifa_netmask;
254 info[count].prefixLength = IP_MASK_MAX - (ffs((int32_t)ntohl(addr->sin_addr.s_addr)) - 1);
255
256 CLOGI(LOG_LABEL "name=%s %s/%hhu", ifa->ifa_name, WifiDirectAnonymizeIp(addrString), info[count].prefixLength);
257 count++;
258 }
259
260 *size = count;
261 freeifaddrs(ifAddr);
262 return SOFTBUS_OK;
263 }
264
GetInterfaceMacAddr(const char * ifName,uint8_t * macAddrArray,size_t * macAddrArraySize)265 static int32_t GetInterfaceMacAddr(const char *ifName, uint8_t *macAddrArray, size_t *macAddrArraySize)
266 {
267 struct ifreq ifr;
268 (void)memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr));
269
270 int32_t ret = strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName);
271 CONN_CHECK_AND_RETURN_RET_LOG(ret == EOK, SOFTBUS_ERR, LOG_LABEL "copy interface name failed");
272
273 int32_t fd = socket(AF_INET, SOCK_DGRAM, 0);
274 CONN_CHECK_AND_RETURN_RET_LOG(fd > 0, SOFTBUS_ERR, LOG_LABEL "open socket failed");
275
276 ret = ioctl(fd, SIOCGIFHWADDR, &ifr);
277 close(fd);
278
279 if (ret != 0) {
280 CLOGE(LOG_LABEL "ioctl get hw addr failed ret=%d", ret);
281 close(fd);
282 return SOFTBUS_ERR;
283 }
284
285 ret = memcpy_s(macAddrArray, *macAddrArraySize, ifr.ifr_hwaddr.sa_data, MAC_ADDR_ARRAY_SIZE);
286 if (ret != EOK) {
287 CLOGE(LOG_LABEL "copy mac addr failed");
288 return SOFTBUS_ERR;
289 }
290
291 *macAddrArraySize = MAC_ADDR_ARRAY_SIZE;
292 return SOFTBUS_OK;
293 }
294
295 static struct WifiDirectNetWorkUtils g_networkUtils = {
296 .getLocalIpv4InfoArray = GetLocalIpv4InfoArray,
297 .channelToFrequency = ChannelToFrequency,
298 .frequencyToChannel = FrequencyToChannel,
299 .channelListToString = ChannelListToString,
300 .stringToChannelList = StringToChannelList,
301 .is2GBand = Is2GBand,
302 .is5GBand = Is5GBand,
303 .isInChannelList = IsInChannelList,
304 .getInterfaceIpString = GetInterfaceIpString,
305 .ipAddrToString = IpAddrToString,
306 .ipStringToAddr = IpStringToAddr,
307 .ipStringToIntArray = IpStringToIntArray,
308 .splitString = SplitString,
309 .macStringToArray = MacStringToArray,
310 .macArrayToString = MacArrayToString,
311 .getInterfaceMacAddr = GetInterfaceMacAddr,
312 };
313
GetWifiDirectNetWorkUtils(void)314 struct WifiDirectNetWorkUtils* GetWifiDirectNetWorkUtils(void)
315 {
316 return &g_networkUtils;
317 }