• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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