• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }