1/*
2 * Copyright (c) 2021-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 "interface_manager.h"
17
18#include <arpa/inet.h>
19#include <cerrno>
20#include <cstdlib>
21#include <cstring>
22#include <dirent.h>
23#include <fcntl.h>
24#include <linux/if_ether.h>
25#include <net/if.h>
26#include <netinet/in.h>
27#include <sys/ioctl.h>
28#include <sys/socket.h>
29#include <sys/types.h>
30#include <system_error>
31#include <unistd.h>
32#include <regex>
33
34#include "netlink_manager.h"
35#include "netlink_msg.h"
36#include "netlink_socket.h"
37#include "netlink_socket_diag.h"
38#include "net_manager_constants.h"
39#include "netmanager_base_common_utils.h"
40#include "netnative_log_wrapper.h"
41#include "securec.h"
42
43namespace OHOS {
44namespace nmd {
45using namespace NetManagerStandard;
46using namespace NetManagerStandard::CommonUtils;
47
48namespace {
49constexpr const char *SYS_NET_PATH = "/sys/class/net/";
50constexpr const char *MTU_PATH = "/mtu";
51constexpr int32_t FILE_PERMISSION = 0666;
52constexpr uint32_t ARRAY_OFFSET_1_INDEX = 1;
53constexpr uint32_t ARRAY_OFFSET_2_INDEX = 2;
54constexpr uint32_t ARRAY_OFFSET_3_INDEX = 3;
55constexpr uint32_t ARRAY_OFFSET_4_INDEX = 4;
56constexpr uint32_t ARRAY_OFFSET_5_INDEX = 5;
57constexpr uint32_t MOVE_BIT_LEFT31 = 31;
58constexpr uint32_t BIT_MAX = 32;
59constexpr uint32_t IOCTL_RETRY_TIME = 32;
60constexpr int32_t MAX_MTU_LEN = 11;
61constexpr int32_t MAC_ADDRESS_STR_LEN = 18;
62constexpr int32_t MAC_ADDRESS_INT_LEN = 6;
63constexpr int32_t MAC_SSCANF_SPACE = 3;
64const std::regex REGEX_CMD_MAC_ADDRESS("^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$");
65
66bool CheckFilePath(const std::string &fileName, std::string &realPath)
67{
68    char tmpPath[PATH_MAX] = {0};
69    if (!realpath(fileName.c_str(), tmpPath)) {
70        NETNATIVE_LOGE("file name is illegal");
71        return false;
72    }
73    realPath = tmpPath;
74    return true;
75}
76} // namespace
77
78int InterfaceManager::GetMtu(const char *interfaceName)
79{
80    if (interfaceName == nullptr) {
81        NETNATIVE_LOGE("interfaceName is null");
82        return -1;
83    }
84
85    if (!CheckIfaceName(interfaceName)) {
86        NETNATIVE_LOGE("GetMtu isIfaceName fail %{public}d", errno);
87        return -1;
88    }
89    std::string mtuPath = std::string(SYS_NET_PATH).append(interfaceName).append(MTU_PATH);
90    std::string realPath;
91    if (!CheckFilePath(mtuPath, realPath)) {
92        NETNATIVE_LOGE("file does not exist! ");
93        return -1;
94    }
95    int fd = open(realPath.c_str(), 0, FILE_PERMISSION);
96    if (fd == -1) {
97        NETNATIVE_LOGE("GetMtu open fail %{public}d", errno);
98        return -1;
99    }
100
101    char originMtuValue[MAX_MTU_LEN] = {0};
102    int nread = read(fd, originMtuValue, (sizeof(char) * (MAX_MTU_LEN - 1)));
103    if (nread == -1 || nread == 0) {
104        NETNATIVE_LOGE("GetMtu read fail %{public}d", errno);
105        close(fd);
106        return -1;
107    }
108    close(fd);
109
110    int32_t mtu = -1;
111    mtu = StrToInt(originMtuValue);
112    return mtu;
113}
114
115int InterfaceManager::SetMtu(const char *interfaceName, const char *mtuValue)
116{
117    if (interfaceName == nullptr || mtuValue == nullptr) {
118        NETNATIVE_LOGE("interfaceName or mtuValue is null");
119        return -1;
120    }
121
122    if (!CheckIfaceName(interfaceName)) {
123        NETNATIVE_LOGE("SetMtu isIfaceName fail %{public}d", errno);
124    }
125    int32_t sockfd = socket(AF_INET, SOCK_DGRAM, 0);
126    if (sockfd < 0) {
127        NETNATIVE_LOGE("SetMtu socket fail %{public}d", errno);
128        return -1;
129    }
130
131    struct ifreq ifr;
132    if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
133        close(sockfd);
134        return -1;
135    }
136    if (strncpy_s(ifr.ifr_name, IFNAMSIZ, interfaceName, strlen(interfaceName)) != EOK) {
137        close(sockfd);
138        return -1;
139    }
140
141    int32_t mtu = StrToInt(mtuValue);
142    ifr.ifr_mtu = mtu;
143
144    if (ioctl(sockfd, SIOCSIFMTU, &ifr) < 0) {
145        NETNATIVE_LOGE("SetMtu ioctl fail %{public}d", errno);
146        close(sockfd);
147        return -1;
148    }
149
150    close(sockfd);
151    return 0;
152}
153
154std::vector<std::string> InterfaceManager::GetInterfaceNames()
155{
156    std::vector<std::string> ifaceNames;
157    DIR *dir(nullptr);
158    struct dirent *de(nullptr);
159
160    dir = opendir(SYS_NET_PATH);
161    if (dir == nullptr) {
162        NETNATIVE_LOGE("GetInterfaceNames opendir fail %{public}d", errno);
163        return ifaceNames;
164    }
165
166    de = readdir(dir);
167    while (de != nullptr) {
168        if ((de->d_name[0] != '.') && ((de->d_type == DT_DIR) || (de->d_type == DT_LNK))) {
169            ifaceNames.push_back(std::string(de->d_name));
170        }
171        de = readdir(dir);
172    }
173    closedir(dir);
174
175    return ifaceNames;
176}
177
178int InterfaceManager::ModifyAddress(uint32_t action, const char *interfaceName, const char *addr, int prefixLen)
179{
180    if (interfaceName == nullptr || addr == nullptr) {
181        return -1;
182    }
183    uint32_t index = if_nametoindex(interfaceName);
184    if (index == 0) {
185        NETNATIVE_LOGE("ModifyAddress, if_nametoindex error %{public}d", errno);
186        return -errno;
187    }
188    auto family = CommonUtils::GetAddrFamily(addr);
189    if (family != AF_INET && family != AF_INET6) {
190        NETNATIVE_LOGE("Ivalid ip address: %{public}s", CommonUtils::ToAnonymousIp(addr).c_str());
191        return NETMANAGER_ERR_PARAMETER_ERROR;
192    }
193
194    ifaddrmsg ifm = {static_cast<uint8_t>(family), static_cast<uint8_t>(prefixLen), 0, 0, index};
195    nmd::NetlinkMsg nlmsg(NLM_F_CREATE | NLM_F_EXCL, nmd::NETLINK_MAX_LEN, getpid());
196    nlmsg.AddAddress(action, ifm);
197
198    if (family == AF_INET6) {
199        in6_addr in6Addr;
200        if (inet_pton(AF_INET6, addr, &in6Addr) == -1) {
201            NETNATIVE_LOGE("Modify ipv6 address, inet_pton error %{public}d", errno);
202            return NETMANAGER_ERR_INTERNAL;
203        }
204        nlmsg.AddAttr(IFA_LOCAL, &in6Addr, sizeof(in6Addr));
205    } else {
206        in_addr inAddr;
207        if (inet_pton(AF_INET, addr, &inAddr) == -1) {
208            NETNATIVE_LOGE("Modify ipv4 address, inet_pton error %{public}d", errno);
209            return NETMANAGER_ERR_INTERNAL;
210        }
211        nlmsg.AddAttr(IFA_LOCAL, &inAddr, sizeof(inAddr));
212        if (action == RTM_NEWADDR) {
213            inAddr.s_addr |= htonl((1U << (BIT_MAX - prefixLen)) - 1);
214            nlmsg.AddAttr(IFA_BROADCAST, &inAddr, sizeof(inAddr));
215        }
216    }
217
218    NETNATIVE_LOGI("ModifyAddress:%{public}u %{public}s %{public}s %{public}d", action, interfaceName,
219                   ToAnonymousIp(addr).c_str(), prefixLen);
220
221    return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage());
222}
223
224int InterfaceManager::AddAddress(const char *interfaceName, const char *addr, int prefixLen)
225{
226    return ModifyAddress(RTM_NEWADDR, interfaceName, addr, prefixLen);
227}
228
229int InterfaceManager::DelAddress(const char *interfaceName, const char *addr, int prefixLen)
230{
231    NetLinkSocketDiag socketDiag;
232    socketDiag.DestroyLiveSockets(addr, true);
233    return ModifyAddress(RTM_DELADDR, interfaceName, addr, prefixLen);
234}
235
236int InterfaceManager::DelAddress(const char *interfaceName, const char *addr, int prefixLen,
237                                 const std::string &netCapabilities)
238{
239    NetLinkSocketDiag socketDiag;
240    socketDiag.SetSocketDestroyType(netCapabilities);
241    socketDiag.DestroyLiveSockets(addr, true);
242    return 0;
243}
244
245int Ipv4NetmaskToPrefixLength(in_addr_t mask)
246{
247    int prefixLength = 0;
248    uint32_t m = ntohl(mask);
249    const uint32_t referenceValue = 1;
250    while (m & (referenceValue << MOVE_BIT_LEFT31)) {
251        prefixLength++;
252        m = m << referenceValue;
253    }
254    return prefixLength;
255}
256
257std::string HwAddrToStr(char *hwaddr)
258{
259    char buf[64] = {'\0'};
260    if (hwaddr != nullptr) {
261        errno_t result =
262            sprintf_s(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", hwaddr[0], hwaddr[ARRAY_OFFSET_1_INDEX],
263                      hwaddr[ARRAY_OFFSET_2_INDEX], hwaddr[ARRAY_OFFSET_3_INDEX], hwaddr[ARRAY_OFFSET_4_INDEX],
264                      hwaddr[ARRAY_OFFSET_5_INDEX]);
265        if (result != 0) {
266            NETNATIVE_LOGE("[hwAddrToStr]: result %{public}d", result);
267        }
268    }
269    return std::string(buf);
270}
271
272void UpdateIfaceConfigFlags(unsigned flags, nmd::InterfaceConfigurationParcel &ifaceConfig)
273{
274    ifaceConfig.flags.emplace_back(flags & IFF_UP ? "up" : "down");
275    if (flags & IFF_BROADCAST) {
276        ifaceConfig.flags.emplace_back("broadcast");
277    }
278    if (flags & IFF_LOOPBACK) {
279        ifaceConfig.flags.emplace_back("loopback");
280    }
281    if (flags & IFF_POINTOPOINT) {
282        ifaceConfig.flags.emplace_back("point-to-point");
283    }
284    if (flags & IFF_RUNNING) {
285        ifaceConfig.flags.emplace_back("running");
286    }
287    if (flags & IFF_MULTICAST) {
288        ifaceConfig.flags.emplace_back("multicast");
289    }
290}
291
292InterfaceConfigurationParcel InterfaceManager::GetIfaceConfig(const std::string &ifName)
293{
294    NETNATIVE_LOGI("GetIfaceConfig in. ifName %{public}s", ifName.c_str());
295    struct in_addr addr = {};
296    nmd::InterfaceConfigurationParcel ifaceConfig;
297
298    int fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
299    struct ifreq ifr = {};
300    auto ret = strncpy_s(ifr.ifr_name, IFNAMSIZ, ifName.c_str(), ifName.length());
301    if (ret != 0) {
302        NETNATIVE_LOGW("IfName copy failed, no need to return.");
303    }
304
305    ifaceConfig.ifName = ifName;
306    if (ioctl(fd, SIOCGIFADDR, &ifr) != -1) {
307        addr.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
308        ifaceConfig.ipv4Addr = std::string(inet_ntoa(addr));
309    }
310    if (ioctl(fd, SIOCGIFNETMASK, &ifr) != -1) {
311        ifaceConfig.prefixLength = Ipv4NetmaskToPrefixLength(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr);
312    }
313    if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1) {
314        UpdateIfaceConfigFlags(ifr.ifr_flags, ifaceConfig);
315    }
316    if (ioctl(fd, SIOCGIFHWADDR, &ifr) != -1) {
317        ifaceConfig.hwAddr = HwAddrToStr(ifr.ifr_hwaddr.sa_data);
318    }
319    close(fd);
320    return ifaceConfig;
321}
322
323int InterfaceManager::SetIfaceConfig(const nmd::InterfaceConfigurationParcel &ifaceConfig)
324{
325    struct ifreq ifr = {};
326    if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifaceConfig.ifName.c_str(), ifaceConfig.ifName.length()) != 0) {
327        NETNATIVE_LOGE("ifaceConfig strncpy_s error.");
328        return -1;
329    }
330
331    if (ifaceConfig.flags.empty()) {
332        NETNATIVE_LOGE("ifaceConfig flags is empty.");
333        return -1;
334    }
335    int fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
336    if (fd < 0) {
337        NETNATIVE_LOGE("ifaceConfig socket error, errno[%{public}d]", errno);
338        return -1;
339    }
340    if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
341        char errmsg[INTERFACE_ERR_MAX_LEN] = {0};
342        strerror_r(errno, errmsg, INTERFACE_ERR_MAX_LEN);
343        NETNATIVE_LOGE("fail to set interface config. strerror[%{public}s]", errmsg);
344        close(fd);
345        return -1;
346    }
347    short flags = ifr.ifr_flags;
348    auto fit = std::find(ifaceConfig.flags.begin(), ifaceConfig.flags.end(), "up");
349    if (fit != std::end(ifaceConfig.flags)) {
350        uint16_t ifrFlags = static_cast<uint16_t>(ifr.ifr_flags);
351        ifrFlags = ifrFlags | IFF_UP;
352        ifr.ifr_flags = static_cast<short>(ifrFlags);
353    }
354    fit = std::find(ifaceConfig.flags.begin(), ifaceConfig.flags.end(), "down");
355    if (fit != std::end(ifaceConfig.flags)) {
356        ifr.ifr_flags = (short)((uint16_t)ifr.ifr_flags & (~IFF_UP));
357    }
358    if (ifr.ifr_flags == flags) {
359        close(fd);
360        return 1;
361    }
362    uint32_t retry = 0;
363    do {
364        if (ioctl(fd, SIOCSIFFLAGS, &ifr) != -1) {
365            break;
366        }
367        ++retry;
368    } while (errno == ETIMEDOUT && retry < IOCTL_RETRY_TIME);
369    NETNATIVE_LOGI("set ifr flags=[%{public}d] strerror=[%{public}s] retry=[%{public}u]", ifr.ifr_flags,
370                   strerror(errno), retry);
371    close(fd);
372    return 1;
373}
374
375int InterfaceManager::SetIpAddress(const std::string &ifaceName, const std::string &ipAddress)
376{
377    struct ifreq ifr;
378    struct in_addr ipv4Addr = {INADDR_ANY};
379
380    if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
381        NETNATIVE_LOGE("memset is false");
382        return -1;
383    }
384    if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifaceName.c_str(), strlen(ifaceName.c_str())) != EOK) {
385        NETNATIVE_LOGE("strncpy is false");
386        return -1;
387    }
388    if (inet_aton(ipAddress.c_str(), &ipv4Addr) == 0) {
389        NETNATIVE_LOGE("set net ip is false");
390        return -1;
391    }
392    sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&ifr.ifr_addr);
393    sin->sin_family = AF_INET;
394    sin->sin_port = 0;
395    sin->sin_addr = ipv4Addr;
396    int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0);
397    if (ioctl(inetSocket, SIOCSIFADDR, &ifr) < 0) {
398        NETNATIVE_LOGE("set ip address ioctl SIOCSIFADDR error: %{public}s", strerror(errno));
399        close(inetSocket);
400        return -1;
401    }
402    close(inetSocket);
403    return 0;
404}
405
406int InterfaceManager::SetIffUp(const std::string &ifaceName)
407{
408    struct ifreq ifr;
409
410    if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
411        NETNATIVE_LOGE("memset is false");
412        return -1;
413    }
414    if (strncpy_s(ifr.ifr_name, IFNAMSIZ, ifaceName.c_str(), strlen(ifaceName.c_str())) != EOK) {
415        NETNATIVE_LOGE("strncpy is false");
416        return -1;
417    }
418    uint32_t flagVal = (IFF_UP | IFF_MULTICAST);
419    ifr.ifr_flags = static_cast<short int>(flagVal);
420
421    int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0);
422    if (ioctl(inetSocket, SIOCSIFFLAGS, &ifr) < 0) {
423        NETNATIVE_LOGE("set iface up ioctl SIOCSIFFLAGS error: %{public}s", strerror(errno));
424        close(inetSocket);
425        return -1;
426    }
427    close(inetSocket);
428    return 0;
429}
430
431int32_t InterfaceManager::AddStaticArp(const std::string &ipAddr, const std::string &macAddr,
432                                       const std::string &ifName)
433{
434    arpreq req = {};
435    req.arp_flags = ATF_PERM;
436    int32_t res = AssembleArp(ipAddr, macAddr, ifName, req);
437    if (res != NETMANAGER_SUCCESS) {
438        NETNATIVE_LOGE("AssembleArp error");
439        return res;
440    }
441
442    int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0);
443    if (ioctl(inetSocket, SIOCSARP, &req) < 0) {
444        NETNATIVE_LOGE("AddStaticArp ioctl SIOCSARP error: %{public}s", strerror(errno));
445        close(inetSocket);
446        return NETMANAGER_ERR_OPERATION_FAILED;
447    }
448    close(inetSocket);
449    return NETMANAGER_SUCCESS;
450}
451
452int32_t InterfaceManager::DelStaticArp(const std::string &ipAddr, const std::string &macAddr,
453                                       const std::string &ifName)
454{
455    arpreq req = {};
456    req.arp_flags = ATF_PERM;
457    int32_t res = AssembleArp(ipAddr, macAddr, ifName, req);
458    if (res != NETMANAGER_SUCCESS) {
459        NETNATIVE_LOGE("AssembleArp error");
460        return res;
461    }
462
463    int32_t inetSocket = socket(AF_INET, SOCK_DGRAM, 0);
464    if (ioctl(inetSocket, SIOCDARP, &req) < 0) {
465        NETNATIVE_LOGE("DelStaticArp ioctl SIOCDARP error: %{public}s", strerror(errno));
466        close(inetSocket);
467        return NETMANAGER_ERR_OPERATION_FAILED;
468    }
469    close(inetSocket);
470    return NETMANAGER_SUCCESS;
471}
472
473int32_t InterfaceManager::AssembleArp(const std::string &ipAddr, const std::string &macAddr,
474                                      const std::string &ifName, arpreq &req)
475{
476    if (!IsValidIPV4(ipAddr)) {
477        NETNATIVE_LOGE("ipAddr error");
478        return NETMANAGER_ERR_PARAMETER_ERROR;
479    }
480
481    if (!regex_match(macAddr, REGEX_CMD_MAC_ADDRESS)) {
482        NETNATIVE_LOGE("macAddr error");
483        return NETMANAGER_ERR_PARAMETER_ERROR;
484    }
485
486    sockaddr& ethAddrStruct = req.arp_ha;
487    ethAddrStruct.sa_family = ARPHRD_ETHER;
488    if (MacStringToArray(macAddr, ethAddrStruct) != 0) {
489        NETNATIVE_LOGE("macStringToArray error");
490        return NETMANAGER_ERR_OPERATION_FAILED;
491    }
492
493    in_addr ipv4Addr = {};
494    if (inet_aton(ipAddr.c_str(), &ipv4Addr) == 0) {
495        NETNATIVE_LOGE("addr inet_aton error");
496        return NETMANAGER_ERR_OPERATION_FAILED;
497    }
498    auto sin = reinterpret_cast<sockaddr_in *>(&req.arp_pa);
499    sin->sin_family = AF_INET;
500    sin->sin_addr = ipv4Addr;
501
502    if (strncpy_s(req.arp_dev, sizeof(req.arp_dev),
503                  ifName.c_str(), ifName.size()) != 0) {
504        NETNATIVE_LOGE("strncpy_s is false");
505        return NETMANAGER_ERR_OPERATION_FAILED;
506    }
507
508    auto uFlags = static_cast<unsigned int>(req.arp_flags);
509    uFlags |= ATF_COM;
510    req.arp_flags = static_cast<int>(uFlags);
511
512    return NETMANAGER_SUCCESS;
513}
514
515int32_t InterfaceManager::MacStringToArray(const std::string &macAddr, sockaddr &macSock)
516{
517    char strMac[MAC_ADDRESS_INT_LEN] = {};
518    char strAddr[MAC_ADDRESS_STR_LEN] = {};
519    uint32_t v = 0;
520    if (memcpy_s(strAddr, MAC_ADDRESS_STR_LEN, macAddr.c_str(), macAddr.size()) != 0) {
521        NETNATIVE_LOGE("memcpy_s is false");
522        return NETMANAGER_ERR_OPERATION_FAILED;
523    }
524
525    for (int i = 0; i < MAC_ADDRESS_INT_LEN; i++) {
526        if (sscanf_s(strAddr+MAC_SSCANF_SPACE*i, "%2x", &v) <= 0) {
527            NETNATIVE_LOGE("sscanf_s is false");
528            return NETMANAGER_ERR_OPERATION_FAILED;
529        }
530        strMac[i] = (char)v;
531    }
532
533    if (memcpy_s(macSock.sa_data, sizeof(macSock.sa_data),
534                  strMac, MAC_ADDRESS_INT_LEN) != 0) {
535        NETNATIVE_LOGE("memcpy_s is false");
536        return NETMANAGER_ERR_OPERATION_FAILED;
537    }
538
539    return NETMANAGER_SUCCESS;
540}
541} // namespace nmd
542} // namespace OHOS
543