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