1 /*
2 * Copyright (C) 2021 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 "btm_snoop_filter.h"
16
17 #include <log.h>
18 #include <securec.h>
19
20 #include "gap/gap_def.h"
21 #include "hci/hci.h"
22 #include "hci/hci_error.h"
23 #include "platform/include/allocator.h"
24 #include "platform/include/list.h"
25 #include "platform/include/mutex.h"
26
27 #include "btm.h"
28
29 #define L2CAP_DYNAMIC_PSM_NUM_BASE 0x1000
30
31 #define HCI_H4_HEADER_LEN 1
32
33 static bool g_filter = false;
34 static Mutex *g_filterMutex = NULL;
35 static List *g_filterInfoList = NULL;
36
FreeListNodeData(void * data)37 static void FreeListNodeData(void *data)
38 {
39 MEM_MALLOC.free(data);
40 }
41
BtmGetFilterInfoList(void)42 List *BtmGetFilterInfoList(void)
43 {
44 return g_filterInfoList;
45 }
46
BtmInitSnoopFilter(void)47 void BtmInitSnoopFilter(void)
48 {
49 g_filter = false;
50 g_filterMutex = MutexCreate();
51 }
52
BtmCloseSnoopFilter(void)53 void BtmCloseSnoopFilter(void)
54 {
55 g_filter = false;
56 if (g_filterMutex != NULL) {
57 MutexDelete(g_filterMutex);
58 g_filterMutex = NULL;
59 }
60 }
61
BtmEnableSnoopFilter(void)62 void BtmEnableSnoopFilter(void)
63 {
64 MutexLock(g_filterMutex);
65 if (g_filter) {
66 MutexUnlock(g_filterMutex);
67 return;
68 }
69
70 g_filter = true;
71
72 if (g_filterInfoList == NULL) {
73 g_filterInfoList = ListCreate(FreeListNodeData);
74 }
75
76 BtmEnableSnoopFilterAcl();
77 MutexUnlock(g_filterMutex);
78 }
79
BtmDisableSnoopFilter(void)80 void BtmDisableSnoopFilter(void)
81 {
82 MutexLock(g_filterMutex);
83 if (g_filter) {
84 MutexUnlock(g_filterMutex);
85 return;
86 }
87
88 g_filter = false;
89
90 BtmDisableSnoopFilterAcl();
91
92 if (g_filterInfoList != NULL) {
93 ListDelete(g_filterInfoList);
94 g_filterInfoList = NULL;
95 }
96 MutexUnlock(g_filterMutex);
97 }
98
FilterData(uint8_t * data,uint8_t length)99 void FilterData(uint8_t *data, uint8_t length)
100 {
101 (void)memset_s(data, length, 0, length);
102 }
103
BtmFilterAddress(uint8_t * addr,uint8_t length)104 void BtmFilterAddress(uint8_t *addr, uint8_t length)
105 {
106 FilterData(addr, (length > BT_ADDRESS_SIZE) ? BT_ADDRESS_SIZE : length);
107 }
108
IsL2capDynamicPsm(uint16_t psm)109 static bool IsL2capDynamicPsm(uint16_t psm)
110 {
111 if (psm > L2CAP_DYNAMIC_PSM_NUM_BASE) {
112 return true;
113 }
114 return false;
115 }
116
BtmFindFilterInfoByInfoUsePsm(void * nodeData,void * info)117 bool BtmFindFilterInfoByInfoUsePsm(void *nodeData, void *info)
118 {
119 BtmSnoopFilterInfo *srcInfo = nodeData;
120 BtmSnoopFilterInfo *cmpInfo = info;
121
122 if (!IsL2capDynamicPsm(cmpInfo->l2capPsm)) {
123 if (srcInfo->l2capPsm == cmpInfo->l2capPsm) {
124 return true;
125 }
126 } else {
127 cmpInfo->rfcommScn = srcInfo->rfcommScn;
128 cmpInfo->module = srcInfo->module;
129 if (!memcmp(srcInfo, cmpInfo, sizeof(BtmSnoopFilterInfo))) {
130 return true;
131 }
132 }
133
134 return false;
135 }
136
BtmFindFilterInfoByInfoUseScn(void * nodeData,void * info)137 bool BtmFindFilterInfoByInfoUseScn(void *nodeData, void *info)
138 {
139 BtmSnoopFilterInfo *srcInfo = nodeData;
140 BtmSnoopFilterInfo *cmpInfo = info;
141
142 cmpInfo->l2capPsm = srcInfo->l2capPsm;
143 cmpInfo->module = srcInfo->module;
144 if (!memcmp(srcInfo, cmpInfo, sizeof(BtmSnoopFilterInfo))) {
145 return true;
146 } else {
147 return false;
148 }
149 }
150
BtmChangeIncludeLength(uint16_t * includedLength,uint16_t len)151 void BtmChangeIncludeLength(uint16_t *includedLength, uint16_t len)
152 {
153 *includedLength = len + HCI_H4_HEADER_LEN;
154 }
155
BtmCreateFilterBuffer(const uint16_t * includedLength,const uint8_t * data)156 uint8_t *BtmCreateFilterBuffer(const uint16_t *includedLength, const uint8_t *data)
157 {
158 uint16_t bufferLen = *includedLength - HCI_H4_HEADER_LEN;
159 uint8_t *buffer = MEM_MALLOC.alloc(bufferLen);
160 if (buffer != NULL) {
161 if (data != NULL) {
162 (void)memcpy_s(buffer, bufferLen, data, bufferLen);
163 }
164 }
165
166 return buffer;
167 }
168
AllocFilterInfo(uint8_t module,uint8_t rfcommScn,uint16_t l2capPsm,bool isLocal,const BtAddr * remoteAddr)169 static BtmSnoopFilterInfo *AllocFilterInfo(
170 uint8_t module, uint8_t rfcommScn, uint16_t l2capPsm, bool isLocal, const BtAddr *remoteAddr)
171 {
172 BtmSnoopFilterInfo *info = MEM_MALLOC.alloc(sizeof(BtmSnoopFilterInfo));
173 if (info != NULL) {
174 info->module = module;
175 info->rfcommScn = rfcommScn;
176 info->l2capPsm = l2capPsm;
177 info->isLocal = isLocal;
178 if (remoteAddr != NULL) {
179 info->remoteAddr = *remoteAddr;
180 } else {
181 BtAddr addr = {0};
182 info->remoteAddr = addr;
183 }
184 }
185
186 return info;
187 }
188
BtmHciFilter(uint8_t type,const uint8_t ** data,uint16_t originalLength,uint16_t * includedLength)189 void BtmHciFilter(uint8_t type, const uint8_t **data, uint16_t originalLength, uint16_t *includedLength)
190 {
191 MutexLock(g_filterMutex);
192 if (!g_filter) {
193 MutexUnlock(g_filterMutex);
194 return;
195 }
196
197 switch (type) {
198 case TRANSMISSON_TYPE_H2C_CMD:
199 BtmFilterHciCmd(data, originalLength, includedLength);
200 break;
201 case TRANSMISSON_TYPE_C2H_EVENT:
202 HciEvtFilter(data, originalLength, includedLength);
203 break;
204 case TRANSMISSON_TYPE_H2C_DATA:
205 case TRANSMISSON_TYPE_C2H_DATA:
206 BtmFilterAclData(type, data, originalLength, includedLength);
207 break;
208 default:
209 break;
210 }
211 MutexUnlock(g_filterMutex);
212 }
213
BTM_AddLocalL2capPsmForLogging(uint8_t module,uint16_t psm)214 void BTM_AddLocalL2capPsmForLogging(uint8_t module, uint16_t psm)
215 {
216 MutexLock(g_filterMutex);
217 if (!g_filter) {
218 MutexUnlock(g_filterMutex);
219 return;
220 }
221 LOG_INFO("%{public}s: module:%{public}d, local psm:0x%04x", __FUNCTION__, module, psm);
222 BtmSnoopFilterInfo *info = AllocFilterInfo(module, 0, psm, true, NULL);
223 if (info != NULL) {
224 ListAddLast(g_filterInfoList, info);
225 }
226 MutexUnlock(g_filterMutex);
227 }
228
BTM_AddRemoteL2capPsmForLogging(uint8_t module,uint16_t psm,const BtAddr * remoteAddr)229 void BTM_AddRemoteL2capPsmForLogging(uint8_t module, uint16_t psm, const BtAddr *remoteAddr)
230 {
231 MutexLock(g_filterMutex);
232 if (!g_filter) {
233 MutexUnlock(g_filterMutex);
234 return;
235 }
236 LOG_INFO("%{public}s: module:%{public}d, " BT_ADDR_FMT " local psm:0x%04x",
237 __FUNCTION__,
238 module,
239 BT_ADDR_FMT_OUTPUT(remoteAddr->addr),
240 psm);
241 BtmSnoopFilterInfo *info = AllocFilterInfo(module, 0, psm, false, remoteAddr);
242 if (info != NULL) {
243 ListAddLast(g_filterInfoList, info);
244 }
245 MutexUnlock(g_filterMutex);
246 }
247
BTM_RemoveLocalL2capPsmForLogging(uint8_t module,uint16_t psm)248 void BTM_RemoveLocalL2capPsmForLogging(uint8_t module, uint16_t psm)
249 {
250 MutexLock(g_filterMutex);
251 if (!g_filter) {
252 MutexUnlock(g_filterMutex);
253 return;
254 }
255 BtmSnoopFilterInfo cmpInfo = {
256 .isLocal = true,
257 .l2capPsm = psm,
258 .remoteAddr = {},
259 };
260 LOG_INFO("%{public}s: module:%{public}d, local psm:0x%04x", __FUNCTION__, module, psm);
261 BtmSnoopFilterInfo *info = ListForEachData(g_filterInfoList, BtmFindFilterInfoByInfoUsePsm, &cmpInfo);
262 if (info != NULL && info->module == module) {
263 ListRemoveNode(g_filterInfoList, info);
264 }
265 MutexUnlock(g_filterMutex);
266 }
267
BTM_RemoveRemoteL2capPsmForLogging(uint8_t module,uint16_t psm,const BtAddr * remoteAddr)268 void BTM_RemoveRemoteL2capPsmForLogging(uint8_t module, uint16_t psm, const BtAddr *remoteAddr)
269 {
270 MutexLock(g_filterMutex);
271 if (!g_filter) {
272 MutexUnlock(g_filterMutex);
273 return;
274 }
275 BtmSnoopFilterInfo cmpInfo = {
276 .isLocal = false,
277 .l2capPsm = psm,
278 .remoteAddr = *remoteAddr,
279 };
280 LOG_INFO("%{public}s: module:%{public}d, " BT_ADDR_FMT " local psm:0x%04x",
281 __FUNCTION__,
282 module,
283 BT_ADDR_FMT_OUTPUT(remoteAddr->addr),
284 psm);
285 BtmSnoopFilterInfo *info = ListForEachData(g_filterInfoList, BtmFindFilterInfoByInfoUsePsm, &cmpInfo);
286 if (info != NULL && info->module == module) {
287 ListRemoveNode(g_filterInfoList, info);
288 }
289 MutexUnlock(g_filterMutex);
290 }
291
BTM_AddLocalRfcommScnForLogging(uint8_t module,uint8_t scn)292 void BTM_AddLocalRfcommScnForLogging(uint8_t module, uint8_t scn)
293 {
294 MutexLock(g_filterMutex);
295 if (!g_filter) {
296 MutexUnlock(g_filterMutex);
297 return;
298 }
299 LOG_INFO("%{public}s: module:%{public}d, local scn:%02d", __FUNCTION__, module, scn);
300 BtmSnoopFilterInfo *info = AllocFilterInfo(module, scn, 0, true, NULL);
301 if (info != NULL) {
302 ListAddLast(g_filterInfoList, info);
303 }
304 MutexUnlock(g_filterMutex);
305 }
306
BTM_AddRemoteRfcommScnForLogging(uint8_t module,uint8_t scn,const BtAddr * remoteAddr)307 void BTM_AddRemoteRfcommScnForLogging(uint8_t module, uint8_t scn, const BtAddr *remoteAddr)
308 {
309 MutexLock(g_filterMutex);
310 if (!g_filter) {
311 MutexUnlock(g_filterMutex);
312 return;
313 }
314 LOG_INFO("%{public}s: module:%{public}d, " BT_ADDR_FMT " local scn:%02d",
315 __FUNCTION__,
316 module,
317 BT_ADDR_FMT_OUTPUT(remoteAddr->addr),
318 scn);
319 BtmSnoopFilterInfo *info = AllocFilterInfo(module, scn, 0, false, remoteAddr);
320 if (info != NULL) {
321 ListAddLast(g_filterInfoList, info);
322 }
323 MutexUnlock(g_filterMutex);
324 }
325
BTM_RemoveLocalRfcommScnChannelForLogging(uint8_t module,uint8_t scn)326 void BTM_RemoveLocalRfcommScnChannelForLogging(uint8_t module, uint8_t scn)
327 {
328 MutexLock(g_filterMutex);
329 if (!g_filter) {
330 MutexUnlock(g_filterMutex);
331 return;
332 }
333 BtmSnoopFilterInfo cmpInfo = {
334 .isLocal = true,
335 .rfcommScn = scn,
336 .module = module,
337 .remoteAddr = {},
338 };
339 LOG_INFO("%{public}s: module:%{public}d, local scn:%02d", __FUNCTION__, module, scn);
340 BtmSnoopFilterInfo *info = ListForEachData(g_filterInfoList, BtmFindFilterInfoByInfoUseScn, &cmpInfo);
341 if (info != NULL && info->module == module) {
342 ListRemoveNode(g_filterInfoList, info);
343 }
344 MutexUnlock(g_filterMutex);
345 }
346
BTM_RemoveRemoteRfcommScnChannelForLogging(uint8_t module,uint8_t scn,const BtAddr * remoteAddr)347 void BTM_RemoveRemoteRfcommScnChannelForLogging(uint8_t module, uint8_t scn, const BtAddr *remoteAddr)
348 {
349 MutexLock(g_filterMutex);
350 if (!g_filter) {
351 MutexUnlock(g_filterMutex);
352 return;
353 }
354 BtmSnoopFilterInfo cmpInfo = {
355 .isLocal = true,
356 .rfcommScn = scn,
357 .module = module,
358 .remoteAddr = {},
359 };
360 LOG_INFO("%{public}s: module:%{public}d, " BT_ADDR_FMT " local scn:%02d",
361 __FUNCTION__,
362 module,
363 BT_ADDR_FMT_OUTPUT(remoteAddr->addr),
364 scn);
365 BtmSnoopFilterInfo *info = ListForEachData(g_filterInfoList, BtmFindFilterInfoByInfoUseScn, &cmpInfo);
366 if (info != NULL && info->module == module) {
367 ListRemoveNode(g_filterInfoList, info);
368 }
369 MutexUnlock(g_filterMutex);
370 }