1 /*
2 * Copyright (C) 2021-2022 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 "mac_address.h"
17 #include <unistd.h>
18 #include <algorithm>
19 #include <cctype>
20 #include <cstdlib>
21 #include <securec.h>
22 #include <net/if.h>
23 #include <net/if_arp.h>
24 #include <netinet/if_ether.h>
25 #include <sys/ioctl.h>
26 #include <sys/socket.h>
27 #include "wifi_log.h"
28
29 #undef LOG_TAG
30 #define LOG_TAG "OHWIFI_UTIL_MacAddress"
31
32 static constexpr char INVALID_MAC[MAC_STRING_LENGTH + 1] = "00:00:00:00:00:00"; /* Indicates an invalid MAC address. */
33 static constexpr int MAC_BLOCK = 2;
34 constexpr int INTERVAL = 3; /* MAC addresses:character spacing */
35 constexpr int HEX_BASE = 16;
36
37 namespace OHOS {
38 namespace Wifi {
39 const MacAddress MacAddress::INVALID_MAC_ADDRESS = MacAddress(INVALID_MAC);
40
IsValidMac(const std::string & mac)41 bool MacAddress::IsValidMac(const std::string &mac)
42 {
43 if (mac.length() != MAC_STRING_LENGTH) {
44 return false;
45 }
46
47 if (INVALID_MAC_ADDRESS.GetMacAddressWifiString() == mac) {
48 return false;
49 }
50
51 std::string macBuf = mac;
52 std::transform(macBuf.begin(), macBuf.end(), macBuf.begin(), ::tolower);
53
54 for (size_t i = 0; i < MAC_STRING_LENGTH; i++) {
55 if (i % INTERVAL == MAC_BLOCK) {
56 if (macBuf[i] != ':') {
57 return false;
58 }
59 } else {
60 if ((macBuf[i] < '0' || macBuf[i] > '9') && (macBuf[i] < 'a' || macBuf[i] > 'f')) {
61 return false;
62 }
63 }
64 }
65
66 return true;
67 }
68
Create(const std::string & mac)69 MacAddress MacAddress::Create(const std::string &mac)
70 {
71 if (IsValidMac(mac)) {
72 std::string macBuf = mac;
73 std::transform(macBuf.begin(), macBuf.end(), macBuf.begin(), ::tolower);
74 return MacAddress(macBuf);
75 }
76
77 return INVALID_MAC_ADDRESS;
78 }
79
Create(const sockaddr & hwAddr)80 MacAddress MacAddress::Create(const sockaddr &hwAddr)
81 {
82 char mac[MAC_STRING_LENGTH + 1];
83 if (snprintf_s(mac,
84 sizeof(mac),
85 sizeof(mac) - 1,
86 "%02x:%02x:%02x:%02x:%02x:%02x",
87 (unsigned char)hwAddr.sa_data[ZERO],
88 (unsigned char)hwAddr.sa_data[ONE],
89 (unsigned char)hwAddr.sa_data[TWO],
90 (unsigned char)hwAddr.sa_data[THREE],
91 (unsigned char)hwAddr.sa_data[FOUR],
92 (unsigned char)hwAddr.sa_data[FIVE]) < 0) {
93 return INVALID_MAC_ADDRESS;
94 }
95
96 return Create(mac);
97 }
98
MacAddress(const std::string & mac)99 MacAddress::MacAddress(const std::string &mac) : mac_(mac)
100 {}
101
operator ==(const MacAddress & mac) const102 bool MacAddress::operator==(const MacAddress &mac) const
103 {
104 return mac_ == mac.mac_;
105 }
106
operator ==(const struct sockaddr & hwAddr) const107 bool MacAddress::operator==(const struct sockaddr &hwAddr) const
108 {
109 MacAddress mac = Create(hwAddr);
110 return mac_ == mac.mac_;
111 }
112
IsValid() const113 bool MacAddress::IsValid() const
114 {
115 return IsValidMac(mac_);
116 }
117
Dump() const118 void MacAddress::Dump() const
119 {
120 LOGI("MAC: [%{private}s]", mac_.c_str());
121 }
122
GetMacAddressWifiString() const123 const std::string &MacAddress::GetMacAddressWifiString() const
124 {
125 return mac_;
126 }
127
GetMacAddressWifiSockaddr() const128 struct sockaddr MacAddress::GetMacAddressWifiSockaddr() const
129 {
130 struct sockaddr hwAddr = {0};
131 hwAddr.sa_family = 1; /* Ethernet 10Mbps */
132
133 for (size_t i = 0; i < mac_.length(); i += INTERVAL) {
134 std::string byte = mac_.substr(i, MAC_BLOCK);
135 hwAddr.sa_data[i / INTERVAL] = static_cast<char>(strtol(byte.c_str(), nullptr, HEX_BASE));
136 }
137 return hwAddr;
138 }
139
GetMacAddr(const std::string & ifName,unsigned char macAddr[MAC_LEN])140 bool MacAddress::GetMacAddr(const std::string& ifName, unsigned char macAddr[MAC_LEN])
141 {
142 struct ifreq ifr;
143 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK ||
144 strcpy_s(ifr.ifr_name, sizeof(ifr.ifr_name), ifName.c_str()) != EOK) {
145 LOGE("Init the ifreq struct failed!");
146 return false;
147 }
148 int fd = socket(AF_INET, SOCK_DGRAM, 0);
149 if (fd < 0) {
150 LOGE("get mac addr socket error");
151 return false;
152 }
153
154 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
155 if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
156 LOGE("get mac addr ioctl SIOCGIFHWADDR error");
157 close(fd);
158 return false;
159 }
160
161 if (memcpy_s(macAddr, ETH_ALEN, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != EOK) {
162 LOGE("get mac addr memcpy_s error");
163 close(fd);
164 return false;
165 }
166 close(fd);
167 return true;
168 }
169 } // namespace WiFi
170 } // namespace OHOS
171