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 "iface_tool.h"
17#include <cstring>
18#include <net/if.h>
19#include <net/if_arp.h>
20#include <netinet/in.h>
21#include <sys/ioctl.h>
22#include <sys/socket.h>
23#include <linux/if_bridge.h>
24#include <linux/if.h>
25#include <unistd.h>
26#include <hdf_log.h>
27#include "unique_fd.h"
28#include "securec.h"
29
30namespace OHOS {
31namespace HDI {
32namespace Wlan {
33namespace Chip {
34namespace V1_0 {
35const char K_WLAN0_INTERFACE_NAME[] = "wlan0";
36const int MAC_LEN = 6;
37const int MAC_POS_1 = 1;
38const int MAC_POS_2 = 2;
39const int MAC_POS_3 = 3;
40const int MAC_POS_4 = 4;
41const int MAC_POS_5 = 5;
42
43bool GetIfState(const char* ifName, int sock, struct ifreq* ifr)
44{
45    if (memset_s(ifr, sizeof(*ifr), 0, sizeof(*ifr)) != EOK) {
46        HDF_LOGE("memset_s failed");
47        return false;
48    }
49    if (strlcpy(ifr->ifr_name, ifName, sizeof(ifr->ifr_name)) >=
50        sizeof(ifr->ifr_name)) {
51        HDF_LOGE("Interface name is too long: %{public}s", ifName);
52        return false;
53    }
54    if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCGIFFLAGS, ifr)) != 0) {
55        HDF_LOGE("Could not read interface state for %{public}s, %{public}s", ifName, strerror(errno));
56        return false;
57    }
58    return true;
59}
60
61bool IfaceTool::GetUpState(const char* ifName)
62{
63    UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
64    if (sock.Get() < 0) {
65        HDF_LOGE("Failed to open socket to set up/down state %{public}s", strerror(errno));
66        return false;
67    }
68    struct ifreq ifr;
69    if (!GetIfState(ifName, sock.Get(), &ifr)) {
70        return false;
71    }
72    return ifr.ifr_flags & IFF_UP;
73}
74
75bool IfaceTool::SetUpState(const char* ifName, bool requestUp)
76{
77    UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
78    if (sock.Get() < 0) {
79        HDF_LOGE("Failed to open socket to set up/down state %{public}s", strerror(errno));
80        return false;
81    }
82    struct ifreq ifr;
83    if (!GetIfState(ifName, sock.Get(), &ifr)) {
84        return false;
85    }
86    const bool currentlyUp = ifr.ifr_flags & IFF_UP;
87    if (currentlyUp == requestUp) {
88        return true;
89    }
90    if (requestUp) {
91        ifr.ifr_flags |= IFF_UP;
92    } else {
93        ifr.ifr_flags &= ~IFF_UP;
94    }
95    if (TEMP_FAILURE_RETRY(ioctl(sock.Get(), SIOCSIFFLAGS, &ifr)) != 0) {
96        HDF_LOGE("Could not set interface flags for %{public}s, %{public}s", ifName, strerror(errno));
97        return false;
98    }
99    return true;
100}
101
102bool IfaceTool::SetWifiUpState(bool requestUp)
103{
104    return SetUpState(K_WLAN0_INTERFACE_NAME, requestUp);
105}
106
107bool IfaceTool::SetMacAddress(const char* ifName, const char* mac)
108{
109    struct ifreq ifr;
110
111    unsigned char macBin[MAC_LEN];
112    if (sscanf_s(mac, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
113        &macBin[0], &macBin[MAC_POS_1], &macBin[MAC_POS_2],
114        &macBin[MAC_POS_3], &macBin[MAC_POS_4], &macBin[MAC_POS_5]) == EOF) {
115        return false;
116    }
117    UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
118    if (sock.Get() < 0) {
119        HDF_LOGE("Failed to open socket to set MAC address %{public}s", strerror(errno));
120        return false;
121    }
122    if (!GetIfState(ifName, sock.Get(), &ifr)) {
123        return false;
124    }
125    if (memset_s(&ifr.ifr_hwaddr, sizeof(ifr.ifr_hwaddr), 0, sizeof(ifr.ifr_hwaddr)) < 0) {
126        HDF_LOGE("Failed to memset");
127    }
128    ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
129    if (memcpy_s(ifr.ifr_hwaddr.sa_data, MAC_LEN, macBin, MAC_LEN) < 0) {
130        HDF_LOGE("Failed to memcpy");
131    }
132    if (TEMP_FAILURE_RETRY(ioctl(sock.Get(), SIOCSIFHWADDR, &ifr)) != 0) {
133        HDF_LOGE("Failed to set interface MAC address for %{public}s, %{public}s",
134            ifName, strerror(errno));
135        return false;
136    }
137    return true;
138}
139}
140}
141}
142}
143}