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 #include <sys/socket.h>
16 #include <sys/ioctl.h>
17 #include <net/if_arp.h>
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
20 #include <securec.h>
21
22 #include "multi_gateway.h"
23 #include "singleton.h"
24 #include "wifi_logger.h"
25 #include "wifi_config_center.h"
26
27 namespace OHOS {
28 namespace Wifi {
29 DEFINE_WIFILOG_LABEL("MultiGateway");
30
31 constexpr int32_t DEFAULT_ARP_TIMEOUT_MS = 1000;
32 constexpr uint32_t MULTI_GATEWAY_NUM = 2;
33 constexpr int32_t MAC_ADDRESS_LENGTH = 6;
34 constexpr int32_t MAC_INDEX_0 = 0;
35 constexpr int32_t MAC_INDEX_1 = 1;
36 constexpr int32_t MAC_INDEX_2 = 2;
37 constexpr int32_t MAC_INDEX_3 = 3;
38 constexpr int32_t MAC_INDEX_4 = 4;
39 constexpr int32_t MAC_INDEX_5 = 5;
40
MultiGateway()41 MultiGateway::MultiGateway() : m_currentIdx(0)
42 {
43 WIFI_LOGI("MultiGateway()");
44 }
45
~MultiGateway()46 MultiGateway::~MultiGateway()
47 {
48 WIFI_LOGI("~MultiGateway()");
49 }
50
GetGatewayAddr(int32_t instId)51 void MultiGateway::GetGatewayAddr(int32_t instId)
52 {
53 std::string macAddress;
54 WifiConfigCenter::GetInstance().GetMacAddress(macAddress, instId);
55 IpInfo ipInfo;
56 WifiConfigCenter::GetInstance().GetIpInfo(ipInfo, instId);
57 std::string ipAddress = IpTools::ConvertIpv4Address(ipInfo.ipAddress);
58 std::string ifName = WifiConfigCenter::GetInstance().GetStaIfaceName();
59 if (ipInfo.gateway == 0) {
60 WIFI_LOGE("gateway is null");
61 return;
62 }
63 m_gwIpAddr = IpTools::ConvertIpv4Address(ipInfo.gateway);
64
65 ArpChecker arpChecker;
66 m_currentIdx = 0;
67 arpChecker.Start(ifName, macAddress, ipAddress, m_gwIpAddr);
68 arpChecker.GetGwMacAddrList(DEFAULT_ARP_TIMEOUT_MS, true, m_gwMacLists);
69 WIFI_LOGI("get gateway num is %{public}lu", static_cast<unsigned long>(m_gwMacLists.size()));
70 }
71
IsMultiGateway()72 bool MultiGateway::IsMultiGateway()
73 {
74 return m_gwMacLists.size() >= MULTI_GATEWAY_NUM;
75 }
76
GetGatewayIp()77 std::string MultiGateway::GetGatewayIp()
78 {
79 return m_gwIpAddr;
80 }
81
GetNextGatewayMac(std::string & mac)82 void MultiGateway::GetNextGatewayMac(std::string& mac)
83 {
84 WIFI_LOGE("GetNextGatewayMac m_currentIdx: %{public}u", m_currentIdx);
85 if (m_currentIdx >= m_gwMacLists.size()) {
86 WIFI_LOGE("m_currentIdx is overflow, m_currentIdx: %{public}u, size: %{public}lu",
87 m_currentIdx, static_cast<unsigned long>(m_gwMacLists.size()));
88 return;
89 }
90 mac = m_gwMacLists[m_currentIdx];
91 m_currentIdx++;
92 }
93
SetStaticArp(const std::string & iface,const std::string & ipAddr,const std::string & macAddr)94 int32_t MultiGateway::SetStaticArp(const std::string& iface, const std::string& ipAddr, const std::string& macAddr)
95 {
96 WIFI_LOGI("SetStaticArp enter");
97 struct arpreq req;
98 struct sockaddr_in *sin = nullptr;
99
100 if (iface.empty() || ipAddr.empty() || macAddr.empty()) {
101 WIFI_LOGE("SetStaticArp arg is invalid");
102 return -1;
103 }
104
105 if (memset_s(&req, sizeof(struct arpreq), 0, sizeof(struct arpreq)) != EOK) {
106 WIFI_LOGE("DelStaticArp memset_s err");
107 return -1;
108 }
109 sin = reinterpret_cast<struct sockaddr_in *>(&req.arp_pa);
110 sin->sin_family = AF_INET;
111 sin->sin_addr.s_addr = inet_addr(ipAddr.c_str());
112 if (strncpy_s(req.arp_dev, sizeof(req.arp_dev), iface.c_str(), iface.size()) != EOK) {
113 WIFI_LOGE("strncpy_s req err");
114 return -1;
115 }
116
117 req.arp_flags = ATF_PERM | ATF_COM;
118 if (GetMacAddr(reinterpret_cast<char *>(req.arp_ha.sa_data), macAddr.c_str()) < 0) {
119 WIFI_LOGE("SetStaticArp GetMacAddr error");
120 return -1;
121 }
122 return DoArpItem(SIOCSARP, &req);
123 }
124
DelStaticArp(const std::string & iface,const std::string & ipAddr)125 int32_t MultiGateway::DelStaticArp(const std::string& iface, const std::string& ipAddr)
126 {
127 WIFI_LOGI("DelStaticArp enter");
128 struct arpreq req;
129 if (iface.empty() || ipAddr.empty()) {
130 WIFI_LOGE("DelStaticArp arg is invalid");
131 return -1;
132 }
133
134 if (memset_s(&req, sizeof(struct arpreq), 0, sizeof(struct arpreq)) != EOK) {
135 WIFI_LOGE("DelStaticArp memset_s err");
136 return -1;
137 }
138 struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&req.arp_pa);
139 sin->sin_family = AF_INET;
140 sin->sin_addr.s_addr = inet_addr(ipAddr.c_str());
141 if (strncpy_s(req.arp_dev, sizeof(req.arp_dev), iface.c_str(), iface.size()) != EOK) {
142 WIFI_LOGE("strncpy_s req err");
143 return -1;
144 }
145 return DoArpItem(SIOCDARP, &req);
146 }
147
DoArpItem(int32_t cmd,struct arpreq * req)148 int32_t MultiGateway::DoArpItem(int32_t cmd, struct arpreq *req)
149 {
150 if (req == nullptr) {
151 WIFI_LOGE("DoArpItem req is nullptr");
152 return -1;
153 }
154
155 int32_t sockFd = socket(AF_INET, SOCK_DGRAM, 0);
156 if (sockFd < 0) {
157 WIFI_LOGE("DoArpItem socket creat error");
158 return -1;
159 }
160
161 int32_t ret = ioctl(sockFd, cmd, req);
162 if (ret < 0) {
163 WIFI_LOGE("DoArpItem ioctl error");
164 }
165 close(sockFd);
166 return ret;
167 }
168
GetMacAddr(char * buff,const char * macAddr)169 int32_t MultiGateway::GetMacAddr(char *buff, const char *macAddr)
170 {
171 unsigned int addr[MAC_ADDRESS_LENGTH] = {0};
172 if (buff == nullptr || macAddr == nullptr) {
173 WIFI_LOGE("buff or macAddr is nullptr");
174 return -1;
175 }
176
177 if (sscanf_s(macAddr, "%x:%x:%x:%x:%x:%x", &addr[MAC_INDEX_0], &addr[MAC_INDEX_1], &addr[MAC_INDEX_2],
178 &addr[MAC_INDEX_3], &addr[MAC_INDEX_4], &addr[MAC_INDEX_5]) < MAC_ADDRESS_LENGTH) {
179 WIFI_LOGE("sscanf_s macAddr err");
180 return -1;
181 }
182
183 for (int32_t i = 0; i < MAC_ADDRESS_LENGTH; i++) {
184 buff[i] = addr[i];
185 }
186 return 0;
187 }
188 } // namespace Wifi
189 } // namespace OHOS
190