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 "bluetooth_address.h"
17 #include <cerrno>
18 #include <cstdio>
19 #include <cstring>
20 #include <fcntl.h>
21 #include <hdf_log.h>
22 #include <unistd.h>
23 #include <dlfcn.h>
24 #include "securec.h"
25
26 #ifdef LOG_DOMAIN
27 #undef LOG_DOMAIN
28 #endif
29 #define LOG_DOMAIN 0xD000105
30
31 namespace OHOS {
32 namespace HDI {
33 namespace Bluetooth {
34 namespace Hci {
35 namespace {
36 constexpr int ADDRESS_STR_LEN = 17;
37 constexpr int ADDRESS_SIZE = 6;
38 } // namespace
39
BluetoothAddress()40 BluetoothAddress::BluetoothAddress()
41 {
42 address_.resize(ADDRESS_SIZE);
43 }
44
45 constexpr int START_POS = 6;
46 constexpr int END_POS = 13;
47 constexpr int ADDR_BYTE = 18;
GetEncryptAddr(std::string addr)48 std::string GetEncryptAddr(std::string addr)
49 {
50 if (addr.empty() || addr.length() != ADDRESS_STR_LEN) {
51 HDF_LOGE("addr is invalid.");
52 return std::string("");
53 }
54 std::string tmp = "**:**:**:**:**:**";
55 std::string out = addr;
56 for (int i = START_POS; i <= END_POS; i++) {
57 out[i] = tmp[i];
58 }
59 return out;
60 }
61
ParseAddressToString(std::vector<uint8_t> & address,std::string & outString)62 void BluetoothAddress::ParseAddressToString(std::vector<uint8_t> &address, std::string &outString)
63 {
64 char temp[ADDR_BYTE] = {0};
65 int ret = sprintf_s(temp, sizeof(temp), "%02X:%02X:%02X:%02X:%02X:%02X",
66 address[0], address[1], address[2], address[3], address[4], address[5]);
67 if (ret == -1) {
68 HDF_LOGE("ConvertAddr sprintf_s return error, ret -1");
69 }
70 outString = temp;
71 }
72
ParseAddressFromString(const std::string & string) const73 int BluetoothAddress::ParseAddressFromString(const std::string &string) const
74 {
75 size_t offset = 0;
76 int bytesIndex = 0;
77 int readCount = 0;
78 for (bytesIndex = 0; bytesIndex < ADDRESS_SIZE && offset < string.size(); bytesIndex++) {
79 readCount = 0;
80 if (sscanf_s(&string[offset], "%02hhx:%n", &address_[bytesIndex], &readCount) > 0) {
81 if (readCount == 0 && bytesIndex != ADDRESS_SIZE - 1) {
82 return bytesIndex;
83 }
84 offset += readCount;
85 } else {
86 break;
87 }
88 }
89
90 return bytesIndex;
91 }
92
GetConstantAddress(char * address,int len)93 bool BluetoothAddress::GetConstantAddress(char *address, int len)
94 {
95 if (address == nullptr || len < ADDRESS_STR_LEN + 1) {
96 HDF_LOGE("GetConstantAddress buf error");
97 return false;
98 }
99
100 void *libMac = dlopen(BT_MAC_LIB, RTLD_LAZY);
101 if (libMac == nullptr) {
102 HDF_LOGI("GetConstantAddress no mac lib ready for dlopen");
103 return false;
104 }
105
106 using GetMacFun = int (*)(unsigned int, char*, int);
107 GetMacFun getMac = reinterpret_cast<GetMacFun>(dlsym(libMac, GET_BT_MAC_SYMBOL_NAME));
108 if (getMac == nullptr) {
109 HDF_LOGE("GetConstantAddress dlsym error");
110 dlclose(libMac);
111 return false;
112 }
113
114 int ret = getMac(MAC_TYPE_BLUETOOTH, address, len);
115 HDF_LOGI("GetConstantAddress ret: %{public}d", ret);
116 dlclose(libMac);
117 return (ret == 0);
118 }
119
CheckAddress(char * address)120 bool BluetoothAddress::CheckAddress(char *address)
121 {
122 for (int index = 0; index < ADDRESS_STR_LEN; ++index) {
123 if (address[index] != 0) {
124 return true;
125 }
126 }
127 HDF_LOGI("Check bt address fail, address invailid!");
128 return false;
129 }
130
131 #ifdef BT_MAC_UPDATE
132 // system boot less 2min, need ReadbtAddress from NV
NeedReloadAddress()133 bool BluetoothAddress::NeedReloadAddress()
134 {
135 const int64_t maxNeedReloadTime = 120000; // 120s
136 constexpr int64_t msPerSecond = 1000;
137 constexpr int64_t nsPerMs = 1000000;
138 struct timespec times = {0};
139 if (clock_gettime(CLOCK_MONOTONIC, ×) < 0) {
140 HDF_LOGE("Failed clock_gettime:%{public}s, needReloadAddress:false", strerror(errno));
141 return false;
142 }
143 int64_t relativeTime = ((times.tv_sec * msPerSecond) + (times.tv_nsec / nsPerMs));
144 HDF_LOGI("relativeTime:%{public}lu", relativeTime);
145 return relativeTime < maxNeedReloadTime;
146 }
147 #endif
148
GetDeviceAddress(const std::string & path)149 std::shared_ptr<BluetoothAddress> BluetoothAddress::GetDeviceAddress(const std::string &path)
150 {
151 #ifdef BT_MAC_UPDATE
152 if (NeedReloadAddress()) {
153 return GenerateDeviceAddressFile();
154 }
155 #endif
156 int addrFd = open(path.c_str(), O_RDONLY);
157 if (addrFd < 0) {
158 HDF_LOGI("GetDeviceAddress open %{public}s.", path.c_str());
159 auto ptr = GenerateDeviceAddressFile();
160 if (ptr == nullptr) {
161 HDF_LOGE("GenerateDeviceAddressFile fail!");
162 return nullptr;
163 }
164 return ptr;
165 }
166
167 char addressStr[ADDRESS_STR_LEN + 1] = {0};
168 if (read(addrFd, addressStr, ADDRESS_STR_LEN) != ADDRESS_STR_LEN || !CheckAddress(addressStr)) {
169 HDF_LOGE("read %{public}s failed.", path.c_str());
170 close(addrFd);
171 auto ptr = GenerateDeviceAddressFile();
172 if (ptr == nullptr) {
173 HDF_LOGE("RegenerateDeviceAddressFile fail!");
174 return nullptr;
175 }
176 return ptr;
177 }
178 close(addrFd);
179
180 auto ptr = std::make_shared<BluetoothAddress>();
181 if (ptr->ParseAddressFromString(addressStr) != ADDRESS_SIZE) {
182 return nullptr;
183 }
184
185 return ptr;
186 }
187
GenerateDeviceAddress(const std::string & prefix)188 std::shared_ptr<BluetoothAddress> BluetoothAddress::GenerateDeviceAddress(const std::string &prefix)
189 {
190 const int bufsize = 256;
191 char buf[bufsize] = {0};
192 auto ptr = std::make_shared<BluetoothAddress>();
193 char addressStr[ADDRESS_STR_LEN + 1] = {"00:11:22:33:44:55"};
194 ptr->ParseAddressFromString(addressStr);
195 int prefixCount = ptr->ParseAddressFromString(prefix);
196 if (prefixCount < ADDRESS_SIZE) {
197 int fd = open("/dev/urandom", O_RDONLY);
198 if (fd < 0) {
199 strerror_r(errno, buf, sizeof(buf));
200 HDF_LOGE("open /dev/urandom failed err:%{public}s.", buf);
201 return ptr;
202 }
203 if (read(fd, &ptr->address_[prefixCount], ADDRESS_SIZE - prefixCount) != ADDRESS_SIZE - prefixCount) {
204 strerror_r(errno, buf, sizeof(buf));
205 HDF_LOGE("read /dev/urandom failed err:%{public}s.", buf);
206 }
207 close(fd);
208 }
209 return ptr;
210 }
211
ParseAddressToPtr(char * address,int len)212 std::shared_ptr<BluetoothAddress> BluetoothAddress::ParseAddressToPtr(char *address, int len)
213 {
214 if (address == nullptr || len < ADDRESS_STR_LEN + 1) {
215 HDF_LOGE("ParseAddressToPtr buf error");
216 return nullptr;
217 }
218 auto ptr = std::make_shared<BluetoothAddress>();
219 if (ptr->ParseAddressFromString(address) != ADDRESS_SIZE) {
220 return nullptr;
221 }
222 return ptr;
223 }
224
GenerateDeviceAddressFile(const std::string & path)225 std::shared_ptr<BluetoothAddress> BluetoothAddress::GenerateDeviceAddressFile(const std::string &path)
226 {
227 if (path.compare(BT_DEVICE_ADDRESS_PATH)) {
228 HDF_LOGE("Address file path error.");
229 return nullptr;
230 }
231 const int bufsize = 256;
232 char buf[bufsize] = {0};
233 char addressStr[ADDRESS_STR_LEN + 1] = {"00:11:22:33:44:55"};
234 bool readNVSucc = GetConstantAddress(addressStr, ADDRESS_STR_LEN + 1);
235 int newFd = open(path.c_str(), O_RDWR | O_CREAT, 00600);
236 HDF_LOGI("GetDeviceAddress open newFd %{public}d.", newFd);
237 if (newFd < 0) {
238 return ParseAddressToPtr(addressStr, ADDRESS_STR_LEN + 1);
239 }
240 bool needUpdateTxt = true;
241 char readAddressStr[ADDRESS_STR_LEN + 1] = {"00:11:22:33:44:55"};
242 bool readTxtSucc = read(newFd, readAddressStr, ADDRESS_STR_LEN) == ADDRESS_STR_LEN;
243
244 if (!readNVSucc) {
245 // read NV fail, if btmac.txt exsit mac, not update, needUpdateTxt = false
246 if (!readTxtSucc) {
247 auto tmpPtr = GenerateDeviceAddress();
248 std::string strAddress;
249 ParseAddressToString(tmpPtr->address_, strAddress);
250 HDF_LOGI("device mac addr: %{public}s", GetEncryptAddr(strAddress).c_str());
251 int ret = strcpy_s(addressStr, ADDRESS_STR_LEN + 1, strAddress.c_str());
252 if (ret != 0) {
253 HDF_LOGI("ParseAddressToString strcpy_s err!");
254 }
255 } else {
256 HDF_LOGI("newFd %{public}d not update", newFd);
257 needUpdateTxt = false;
258 }
259 }
260
261 // mac in txt is the same as that in NV, not update txt
262 if (readNVSucc && readTxtSucc && strcmp(addressStr, readAddressStr) == 0) {
263 HDF_LOGI("no need update mac");
264 needUpdateTxt = false;
265 }
266
267 if (needUpdateTxt) {
268 int fdRet = write(newFd, addressStr, ADDRESS_STR_LEN);
269 if (fdRet < 0) {
270 strerror_r(errno, buf, sizeof(buf));
271 HDF_LOGI("GetDeviceAddress addr write failed, err:%{public}s.", buf);
272 }
273 }
274 close(newFd);
275 return needUpdateTxt ? ParseAddressToPtr(addressStr, ADDRESS_STR_LEN + 1) :
276 ParseAddressToPtr(readAddressStr, ADDRESS_STR_LEN + 1);
277 }
278
ReadAddress(std::vector<uint8_t> & address) const279 void BluetoothAddress::ReadAddress(std::vector<uint8_t> &address) const
280 {
281 address = address_;
282 }
283
ReadAddress(std::string & address) const284 void BluetoothAddress::ReadAddress(std::string &address) const
285 {
286 address.resize(ADDRESS_STR_LEN + 1);
287
288 int offset = 0;
289 for (int ii = 0; ii < ADDRESS_SIZE; ii++) {
290 int ret = snprintf_s(
291 &address[offset], (ADDRESS_STR_LEN + 1) - offset, ADDRESS_STR_LEN - offset, "%02x:", address_[ii]);
292 if (ret < 0) {
293 break;
294 }
295 offset += ret;
296 }
297 }
298 } // namespace Hci
299 } // namespace Bluetooth
300 } // namespace HDI
301 } // namespace OHOS
302