1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "iface_tool.h"
17094332d3Sopenharmony_ci#include <cstring>
18094332d3Sopenharmony_ci#include <net/if.h>
19094332d3Sopenharmony_ci#include <net/if_arp.h>
20094332d3Sopenharmony_ci#include <netinet/in.h>
21094332d3Sopenharmony_ci#include <sys/ioctl.h>
22094332d3Sopenharmony_ci#include <sys/socket.h>
23094332d3Sopenharmony_ci#include <linux/if_bridge.h>
24094332d3Sopenharmony_ci#include <linux/if.h>
25094332d3Sopenharmony_ci#include <unistd.h>
26094332d3Sopenharmony_ci#include <hdf_log.h>
27094332d3Sopenharmony_ci#include "unique_fd.h"
28094332d3Sopenharmony_ci#include "securec.h"
29094332d3Sopenharmony_ci
30094332d3Sopenharmony_cinamespace OHOS {
31094332d3Sopenharmony_cinamespace HDI {
32094332d3Sopenharmony_cinamespace Wlan {
33094332d3Sopenharmony_cinamespace Chip {
34094332d3Sopenharmony_cinamespace V1_0 {
35094332d3Sopenharmony_ciconst char K_WLAN0_INTERFACE_NAME[] = "wlan0";
36094332d3Sopenharmony_ciconst int MAC_LEN = 6;
37094332d3Sopenharmony_ciconst int MAC_POS_1 = 1;
38094332d3Sopenharmony_ciconst int MAC_POS_2 = 2;
39094332d3Sopenharmony_ciconst int MAC_POS_3 = 3;
40094332d3Sopenharmony_ciconst int MAC_POS_4 = 4;
41094332d3Sopenharmony_ciconst int MAC_POS_5 = 5;
42094332d3Sopenharmony_ci
43094332d3Sopenharmony_cibool GetIfState(const char* ifName, int sock, struct ifreq* ifr)
44094332d3Sopenharmony_ci{
45094332d3Sopenharmony_ci    if (memset_s(ifr, sizeof(*ifr), 0, sizeof(*ifr)) != EOK) {
46094332d3Sopenharmony_ci        HDF_LOGE("memset_s failed");
47094332d3Sopenharmony_ci        return false;
48094332d3Sopenharmony_ci    }
49094332d3Sopenharmony_ci    if (strlcpy(ifr->ifr_name, ifName, sizeof(ifr->ifr_name)) >=
50094332d3Sopenharmony_ci        sizeof(ifr->ifr_name)) {
51094332d3Sopenharmony_ci        HDF_LOGE("Interface name is too long: %{public}s", ifName);
52094332d3Sopenharmony_ci        return false;
53094332d3Sopenharmony_ci    }
54094332d3Sopenharmony_ci    if (TEMP_FAILURE_RETRY(ioctl(sock, SIOCGIFFLAGS, ifr)) != 0) {
55094332d3Sopenharmony_ci        HDF_LOGE("Could not read interface state for %{public}s, %{public}s", ifName, strerror(errno));
56094332d3Sopenharmony_ci        return false;
57094332d3Sopenharmony_ci    }
58094332d3Sopenharmony_ci    return true;
59094332d3Sopenharmony_ci}
60094332d3Sopenharmony_ci
61094332d3Sopenharmony_cibool IfaceTool::GetUpState(const char* ifName)
62094332d3Sopenharmony_ci{
63094332d3Sopenharmony_ci    UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
64094332d3Sopenharmony_ci    if (sock.Get() < 0) {
65094332d3Sopenharmony_ci        HDF_LOGE("Failed to open socket to set up/down state %{public}s", strerror(errno));
66094332d3Sopenharmony_ci        return false;
67094332d3Sopenharmony_ci    }
68094332d3Sopenharmony_ci    struct ifreq ifr;
69094332d3Sopenharmony_ci    if (!GetIfState(ifName, sock.Get(), &ifr)) {
70094332d3Sopenharmony_ci        return false;
71094332d3Sopenharmony_ci    }
72094332d3Sopenharmony_ci    return ifr.ifr_flags & IFF_UP;
73094332d3Sopenharmony_ci}
74094332d3Sopenharmony_ci
75094332d3Sopenharmony_cibool IfaceTool::SetUpState(const char* ifName, bool requestUp)
76094332d3Sopenharmony_ci{
77094332d3Sopenharmony_ci    UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
78094332d3Sopenharmony_ci    if (sock.Get() < 0) {
79094332d3Sopenharmony_ci        HDF_LOGE("Failed to open socket to set up/down state %{public}s", strerror(errno));
80094332d3Sopenharmony_ci        return false;
81094332d3Sopenharmony_ci    }
82094332d3Sopenharmony_ci    struct ifreq ifr;
83094332d3Sopenharmony_ci    if (!GetIfState(ifName, sock.Get(), &ifr)) {
84094332d3Sopenharmony_ci        return false;
85094332d3Sopenharmony_ci    }
86094332d3Sopenharmony_ci    const bool currentlyUp = ifr.ifr_flags & IFF_UP;
87094332d3Sopenharmony_ci    if (currentlyUp == requestUp) {
88094332d3Sopenharmony_ci        return true;
89094332d3Sopenharmony_ci    }
90094332d3Sopenharmony_ci    if (requestUp) {
91094332d3Sopenharmony_ci        ifr.ifr_flags |= IFF_UP;
92094332d3Sopenharmony_ci    } else {
93094332d3Sopenharmony_ci        ifr.ifr_flags &= ~IFF_UP;
94094332d3Sopenharmony_ci    }
95094332d3Sopenharmony_ci    if (TEMP_FAILURE_RETRY(ioctl(sock.Get(), SIOCSIFFLAGS, &ifr)) != 0) {
96094332d3Sopenharmony_ci        HDF_LOGE("Could not set interface flags for %{public}s, %{public}s", ifName, strerror(errno));
97094332d3Sopenharmony_ci        return false;
98094332d3Sopenharmony_ci    }
99094332d3Sopenharmony_ci    return true;
100094332d3Sopenharmony_ci}
101094332d3Sopenharmony_ci
102094332d3Sopenharmony_cibool IfaceTool::SetWifiUpState(bool requestUp)
103094332d3Sopenharmony_ci{
104094332d3Sopenharmony_ci    return SetUpState(K_WLAN0_INTERFACE_NAME, requestUp);
105094332d3Sopenharmony_ci}
106094332d3Sopenharmony_ci
107094332d3Sopenharmony_cibool IfaceTool::SetMacAddress(const char* ifName, const char* mac)
108094332d3Sopenharmony_ci{
109094332d3Sopenharmony_ci    struct ifreq ifr;
110094332d3Sopenharmony_ci
111094332d3Sopenharmony_ci    unsigned char macBin[MAC_LEN];
112094332d3Sopenharmony_ci    if (sscanf_s(mac, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
113094332d3Sopenharmony_ci        &macBin[0], &macBin[MAC_POS_1], &macBin[MAC_POS_2],
114094332d3Sopenharmony_ci        &macBin[MAC_POS_3], &macBin[MAC_POS_4], &macBin[MAC_POS_5]) == EOF) {
115094332d3Sopenharmony_ci        return false;
116094332d3Sopenharmony_ci    }
117094332d3Sopenharmony_ci    UniqueFd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
118094332d3Sopenharmony_ci    if (sock.Get() < 0) {
119094332d3Sopenharmony_ci        HDF_LOGE("Failed to open socket to set MAC address %{public}s", strerror(errno));
120094332d3Sopenharmony_ci        return false;
121094332d3Sopenharmony_ci    }
122094332d3Sopenharmony_ci    if (!GetIfState(ifName, sock.Get(), &ifr)) {
123094332d3Sopenharmony_ci        return false;
124094332d3Sopenharmony_ci    }
125094332d3Sopenharmony_ci    if (memset_s(&ifr.ifr_hwaddr, sizeof(ifr.ifr_hwaddr), 0, sizeof(ifr.ifr_hwaddr)) < 0) {
126094332d3Sopenharmony_ci        HDF_LOGE("Failed to memset");
127094332d3Sopenharmony_ci    }
128094332d3Sopenharmony_ci    ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
129094332d3Sopenharmony_ci    if (memcpy_s(ifr.ifr_hwaddr.sa_data, MAC_LEN, macBin, MAC_LEN) < 0) {
130094332d3Sopenharmony_ci        HDF_LOGE("Failed to memcpy");
131094332d3Sopenharmony_ci    }
132094332d3Sopenharmony_ci    if (TEMP_FAILURE_RETRY(ioctl(sock.Get(), SIOCSIFHWADDR, &ifr)) != 0) {
133094332d3Sopenharmony_ci        HDF_LOGE("Failed to set interface MAC address for %{public}s, %{public}s",
134094332d3Sopenharmony_ci            ifName, strerror(errno));
135094332d3Sopenharmony_ci        return false;
136094332d3Sopenharmony_ci    }
137094332d3Sopenharmony_ci    return true;
138094332d3Sopenharmony_ci}
139094332d3Sopenharmony_ci}
140094332d3Sopenharmony_ci}
141094332d3Sopenharmony_ci}
142094332d3Sopenharmony_ci}
143094332d3Sopenharmony_ci}