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
GetInstance()51 MultiGateway& MultiGateway::GetInstance()
52 {
53 static MultiGateway instance;
54 return instance;
55 }
56
GetGatewayAddr(int32_t instId)57 void MultiGateway::GetGatewayAddr(int32_t instId)
58 {
59 std::string macAddress;
60 WifiConfigCenter::GetInstance().GetMacAddress(macAddress, instId);
61 IpInfo ipInfo;
62 WifiConfigCenter::GetInstance().GetIpInfo(ipInfo, instId);
63 std::string ipAddress = IpTools::ConvertIpv4Address(ipInfo.ipAddress);
64 std::string ifName = WifiConfigCenter::GetInstance().GetStaIfaceName();
65 if (ipInfo.gateway == 0) {
66 WIFI_LOGE("gateway is null");
67 return;
68 }
69 m_gwIpAddr = IpTools::ConvertIpv4Address(ipInfo.gateway);
70
71 ArpChecker arpChecker;
72 m_currentIdx = 0;
73 arpChecker.Start(ifName, macAddress, ipAddress, m_gwIpAddr);
74 arpChecker.GetGwMacAddrList(DEFAULT_ARP_TIMEOUT_MS, true, m_gwMacLists);
75 WIFI_LOGI("get gateway num is %{public}lu", static_cast<unsigned long>(m_gwMacLists.size()));
76 }
77
IsMultiGateway()78 bool MultiGateway::IsMultiGateway()
79 {
80 return m_gwMacLists.size() >= MULTI_GATEWAY_NUM;
81 }
82
GetGatewayNum()83 int32_t MultiGateway::GetGatewayNum()
84 {
85 return m_gwMacLists.size();
86 }
87
GetGatewayIp()88 std::string MultiGateway::GetGatewayIp()
89 {
90 return m_gwIpAddr;
91 }
92
GetNextGatewayMac(std::string & mac)93 void MultiGateway::GetNextGatewayMac(std::string& mac)
94 {
95 WIFI_LOGE("GetNextGatewayMac m_currentIdx: %{public}u", m_currentIdx);
96 if (m_currentIdx >= m_gwMacLists.size()) {
97 WIFI_LOGE("m_currentIdx is overflow, m_currentIdx: %{public}u, size: %{public}lu",
98 m_currentIdx, static_cast<unsigned long>(m_gwMacLists.size()));
99 return;
100 }
101 mac = m_gwMacLists[m_currentIdx];
102 m_currentIdx++;
103 }
104
SetStaticArp(const std::string & iface,const std::string & ipAddr,const std::string & macAddr)105 int32_t MultiGateway::SetStaticArp(const std::string& iface, const std::string& ipAddr, const std::string& macAddr)
106 {
107 WIFI_LOGI("SetStaticArp enter");
108 struct arpreq req;
109 struct sockaddr_in *sin = nullptr;
110
111 if (iface.empty() || ipAddr.empty() || macAddr.empty()) {
112 WIFI_LOGE("SetStaticArp arg is invalid");
113 return -1;
114 }
115
116 if (memset_s(&req, sizeof(struct arpreq), 0, sizeof(struct arpreq)) != EOK) {
117 WIFI_LOGE("DelStaticArp memset_s err");
118 return -1;
119 }
120 sin = reinterpret_cast<struct sockaddr_in *>(&req.arp_pa);
121 sin->sin_family = AF_INET;
122 sin->sin_addr.s_addr = inet_addr(ipAddr.c_str());
123 if (strncpy_s(req.arp_dev, sizeof(req.arp_dev), iface.c_str(), iface.size()) != EOK) {
124 WIFI_LOGE("strncpy_s req err");
125 return -1;
126 }
127
128 req.arp_flags = ATF_PERM | ATF_COM;
129 if (GetMacAddr(reinterpret_cast<char *>(req.arp_ha.sa_data), macAddr.c_str()) < 0) {
130 WIFI_LOGE("SetStaticArp GetMacAddr error");
131 return -1;
132 }
133 return DoArpItem(SIOCSARP, &req);
134 }
135
DelStaticArp(const std::string & iface,const std::string & ipAddr)136 int32_t MultiGateway::DelStaticArp(const std::string& iface, const std::string& ipAddr)
137 {
138 WIFI_LOGI("DelStaticArp enter");
139 struct arpreq req;
140 if (iface.empty() || ipAddr.empty()) {
141 WIFI_LOGE("DelStaticArp arg is invalid");
142 return -1;
143 }
144
145 if (memset_s(&req, sizeof(struct arpreq), 0, sizeof(struct arpreq)) != EOK) {
146 WIFI_LOGE("DelStaticArp memset_s err");
147 return -1;
148 }
149 struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(&req.arp_pa);
150 sin->sin_family = AF_INET;
151 sin->sin_addr.s_addr = inet_addr(ipAddr.c_str());
152 if (strncpy_s(req.arp_dev, sizeof(req.arp_dev), iface.c_str(), iface.size()) != EOK) {
153 WIFI_LOGE("strncpy_s req err");
154 return -1;
155 }
156 return DoArpItem(SIOCDARP, &req);
157 }
158
DoArpItem(int32_t cmd,struct arpreq * req)159 int32_t MultiGateway::DoArpItem(int32_t cmd, struct arpreq *req)
160 {
161 if (req == nullptr) {
162 WIFI_LOGE("DoArpItem req is nullptr");
163 return -1;
164 }
165
166 int32_t sockFd = socket(AF_INET, SOCK_DGRAM, 0);
167 if (sockFd < 0) {
168 WIFI_LOGE("DoArpItem socket creat error");
169 return -1;
170 }
171
172 int32_t ret = ioctl(sockFd, cmd, req);
173 if (ret < 0) {
174 WIFI_LOGE("DoArpItem ioctl error");
175 }
176 close(sockFd);
177 return ret;
178 }
179
GetMacAddr(char * buff,const char * macAddr)180 int32_t MultiGateway::GetMacAddr(char *buff, const char *macAddr)
181 {
182 unsigned int addr[MAC_ADDRESS_LENGTH] = {0};
183 if (buff == nullptr || macAddr == nullptr) {
184 WIFI_LOGE("buff or macAddr is nullptr");
185 return -1;
186 }
187
188 if (sscanf_s(macAddr, "%x:%x:%x:%x:%x:%x", &addr[MAC_INDEX_0], &addr[MAC_INDEX_1], &addr[MAC_INDEX_2],
189 &addr[MAC_INDEX_3], &addr[MAC_INDEX_4], &addr[MAC_INDEX_5]) < MAC_ADDRESS_LENGTH) {
190 WIFI_LOGE("sscanf_s macAddr err");
191 return -1;
192 }
193
194 for (int32_t i = 0; i < MAC_ADDRESS_LENGTH; i++) {
195 buff[i] = addr[i];
196 }
197 return 0;
198 }
199 } // namespace Wifi
200 } // namespace OHOS
201