• 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 
16 #include "trans_bind_request_manager.h"
17 
18 #include <securec.h>
19 #include <stdlib.h>
20 
21 #include "message_handler.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_common.h"
24 #include "softbus_def.h"
25 #include "softbus_utils.h"
26 #include "trans_log.h"
27 
28 #define DDOS_DETECTION_PERIOD_MS (60 * 1000)    // 60s
29 #define BIND_PROTECT_PERIOD_MS (60 * 10 * 1000) // 600s
30 #define BIND_FAILED_COUNT_MAX 10
31 
32 typedef enum {
33     LOOP_DELETE_TIMESTAMP,
34     LOOP_RESET_BIND_DENIED_FLAG
35 } BindRequestLoopMsg;
36 
37 typedef struct {
38     ListNode node;
39     uint64_t timestamp;
40 } BindFailInfo;
41 
42 typedef struct {
43     char mySocketName[SESSION_NAME_SIZE_MAX];
44     char peerSocketName[SESSION_NAME_SIZE_MAX];
45     char peerNetworkId[NETWORK_ID_BUF_LEN];
46 } BindRequestParam;
47 
48 typedef struct {
49     ListNode node;
50     BindRequestParam bindRequestParam;
51     int32_t count;
52     bool bindDeniedFlag;
53     ListNode timestampList;
54 } BindRequestManager;
55 
56 static SoftBusList *g_bindRequestList = NULL;
57 const char *g_transLoopName = "transBindRequestLoop";
58 static SoftBusHandler g_transLoopHandler = { 0 };
59 
60 // need to get g_bindRequestList->lock before calling this function
GetBindRequestManagerByPeer(BindRequestParam * bindRequestParam)61 static BindRequestManager *GetBindRequestManagerByPeer(BindRequestParam *bindRequestParam)
62 {
63     BindRequestManager *item = NULL;
64     BindRequestManager *next = NULL;
65     LIST_FOR_EACH_ENTRY_SAFE(item, next, &g_bindRequestList->list, BindRequestManager, node) {
66         if (strcmp(item->bindRequestParam.mySocketName, bindRequestParam->mySocketName) == 0 &&
67             strcmp(item->bindRequestParam.peerSocketName, bindRequestParam->peerSocketName) == 0 &&
68             strcmp(item->bindRequestParam.peerNetworkId, bindRequestParam->peerNetworkId) == 0) {
69             return item;
70         }
71     }
72     TRANS_LOGI(TRANS_SVC, "session not found");
73     return NULL;
74 }
75 
GenerateParam(const char * mySocketName,const char * peerSocketName,const char * peerNetworkId,BindRequestParam * bindReqParam)76 static int32_t GenerateParam(
77     const char *mySocketName, const char *peerSocketName, const char *peerNetworkId, BindRequestParam *bindReqParam)
78 {
79     int32_t ret = strcpy_s(bindReqParam->mySocketName, sizeof(bindReqParam->mySocketName), mySocketName);
80     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == EOK, SOFTBUS_STRCPY_ERR, TRANS_SVC, "memcpy mySocketName failed");
81 
82     ret = strcpy_s(bindReqParam->peerSocketName, sizeof(bindReqParam->peerSocketName), peerSocketName);
83     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == EOK, SOFTBUS_STRCPY_ERR, TRANS_SVC, "memcpy peerSocketName failed");
84 
85     ret = strcpy_s(bindReqParam->peerNetworkId, sizeof(bindReqParam->peerNetworkId), peerNetworkId);
86     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == EOK, SOFTBUS_STRCPY_ERR, TRANS_SVC, "memcpy peerNetworkId failed");
87     return SOFTBUS_OK;
88 }
89 
CreateBindRequestManager(const char * mySocketName,const char * peerSocketName,const char * peerNetworkId)90 static BindRequestManager *CreateBindRequestManager(
91     const char *mySocketName, const char *peerSocketName, const char *peerNetworkId)
92 {
93     BindRequestManager *bindRequest = (BindRequestManager *)SoftBusCalloc(sizeof(BindRequestManager));
94     TRANS_CHECK_AND_RETURN_RET_LOGE(bindRequest != NULL, NULL, TRANS_SVC, "malloc failed");
95     bindRequest->bindDeniedFlag = false;
96     bindRequest->count = 0;
97     int32_t ret = GenerateParam(mySocketName, peerSocketName, peerNetworkId, &bindRequest->bindRequestParam);
98     if (ret != SOFTBUS_OK) {
99         TRANS_LOGE(TRANS_SVC, "genarate param failed");
100         SoftBusFree(bindRequest);
101         return NULL;
102     }
103     ListInit(&bindRequest->node);
104     ListInit(&bindRequest->timestampList);
105     ListAdd(&g_bindRequestList->list, &bindRequest->node);
106     return bindRequest;
107 }
108 
FreeBindRequestMessage(SoftBusMessage * msg)109 static void FreeBindRequestMessage(SoftBusMessage *msg)
110 {
111     if (msg == NULL) {
112         return;
113     }
114     if (msg->obj != NULL) {
115         SoftBusFree(msg->obj);
116         msg->obj = NULL;
117     }
118     SoftBusFree(msg);
119 }
120 
TransBindRequestMsgToLooper(int32_t msgType,uint64_t param1,uint64_t param2,BindRequestParam * data,uint64_t delayMillis)121 static void TransBindRequestMsgToLooper(
122     int32_t msgType, uint64_t param1, uint64_t param2, BindRequestParam *data, uint64_t delayMillis)
123 {
124     SoftBusMessage *msg = (SoftBusMessage *)SoftBusCalloc(sizeof(SoftBusMessage));
125     TRANS_CHECK_AND_RETURN_LOGE(msg != NULL, TRANS_MSG, "msg create failed");
126     msg->what = msgType;
127     msg->arg1 = param1;
128     msg->arg2 = param2;
129     msg->handler = &g_transLoopHandler;
130 
131     BindRequestParam *param = (BindRequestParam *)SoftBusCalloc(sizeof(BindRequestParam));
132     if (param == NULL) {
133         TRANS_LOGE(TRANS_SVC, "malloc failed");
134         SoftBusFree(msg);
135         return;
136     }
137     (void)GenerateParam(data->mySocketName, data->peerSocketName, data->peerNetworkId, param);
138     msg->obj = (void *)param;
139     msg->FreeMessage = FreeBindRequestMessage;
140 
141     if (delayMillis == 0) {
142         g_transLoopHandler.looper->PostMessage(g_transLoopHandler.looper, msg);
143     } else {
144         g_transLoopHandler.looper->PostMessageDelay(g_transLoopHandler.looper, msg, delayMillis);
145     }
146 }
147 
SendMsgToLooper(BindRequestParam * bindRequestParam,uint64_t timestamp,int32_t count)148 static void SendMsgToLooper(BindRequestParam *bindRequestParam, uint64_t timestamp, int32_t count)
149 {
150     TransBindRequestMsgToLooper(
151         LOOP_DELETE_TIMESTAMP, timestamp, 0, bindRequestParam, DDOS_DETECTION_PERIOD_MS);
152     if (count >= BIND_FAILED_COUNT_MAX) {
153         TransBindRequestMsgToLooper(
154             LOOP_RESET_BIND_DENIED_FLAG, 0, 0, bindRequestParam, BIND_PROTECT_PERIOD_MS);
155     }
156 }
157 
TransAddTimestampToList(const char * mySocketName,const char * peerSocketName,const char * peerNetworkId,uint64_t timestamp)158 int32_t TransAddTimestampToList(
159     const char *mySocketName, const char *peerSocketName, const char *peerNetworkId, uint64_t timestamp)
160 {
161     if (mySocketName == NULL || peerSocketName == NULL || peerNetworkId == NULL || g_bindRequestList == NULL) {
162         return SOFTBUS_INVALID_PARAM;
163     }
164     BindRequestParam bindRequestParam = { {0} };
165     int32_t ret = GenerateParam(mySocketName, peerSocketName, peerNetworkId, &bindRequestParam);
166     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_STRCPY_ERR, TRANS_SVC, "genarate param failed");
167     ret = SoftBusMutexLock(&g_bindRequestList->lock);
168     TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, TRANS_SVC, "lock failed");
169 
170     BindRequestManager *bindRequest = GetBindRequestManagerByPeer(&bindRequestParam);
171     if (bindRequest == NULL) {
172         bindRequest = CreateBindRequestManager(mySocketName, peerSocketName, peerNetworkId);
173         if (bindRequest == NULL) {
174             TRANS_LOGE(TRANS_SVC, "create request manager failed");
175             (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
176             return SOFTBUS_MALLOC_ERR;
177         }
178     }
179     BindFailInfo *bindFailInfo = (BindFailInfo *)SoftBusCalloc(sizeof(BindFailInfo));
180     if (bindFailInfo == NULL) {
181         TRANS_LOGE(TRANS_SVC, "malloc failed");
182         (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
183         return SOFTBUS_MALLOC_ERR;
184     }
185 
186     bindFailInfo->timestamp = timestamp;
187     ListInit(&bindFailInfo->node);
188     ListAdd(&bindRequest->timestampList, &bindFailInfo->node);
189     bindRequest->count++;
190     int32_t count = bindRequest->count;
191     if (count >= BIND_FAILED_COUNT_MAX) {
192         bindRequest->bindDeniedFlag = true;
193     }
194     TRANS_LOGI(TRANS_SVC, "add timestamp to list success, count=%{public}d, timestamp=%{public}" PRId64,
195         count, timestamp);
196     (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
197     SendMsgToLooper(&bindRequestParam, timestamp, count);
198     return SOFTBUS_OK;
199 }
200 
TransDelTimestampFormList(BindRequestParam * bindRequestParam,uint64_t timestamp)201 static void TransDelTimestampFormList(BindRequestParam *bindRequestParam, uint64_t timestamp)
202 {
203     TRANS_CHECK_AND_RETURN_LOGE(g_bindRequestList != NULL, TRANS_SVC, "bind request list no init");
204     int32_t ret = SoftBusMutexLock(&g_bindRequestList->lock);
205     TRANS_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, TRANS_SVC, "lock bind request list failed");
206 
207     BindRequestManager *bindRequest = GetBindRequestManagerByPeer(bindRequestParam);
208     if (bindRequest != NULL) {
209         BindFailInfo *failItem = NULL;
210         BindFailInfo *failNext = NULL;
211         LIST_FOR_EACH_ENTRY_SAFE(failItem, failNext, &bindRequest->timestampList, BindFailInfo, node) {
212             if (failItem->timestamp == timestamp) {
213                 ListDelete(&failItem->node);
214                 SoftBusFree(failItem);
215                 bindRequest->count--;
216                 TRANS_LOGI(TRANS_SVC, "del timestamp form list success, count=%{public}d, timestamp=%{public}" PRId64,
217                     bindRequest->count, timestamp);
218                 break;
219             }
220         }
221         if (bindRequest->count == 0 && !bindRequest->bindDeniedFlag) {
222             ListDelete(&bindRequest->node);
223             SoftBusFree(bindRequest);
224         }
225     }
226     (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
227 }
228 
GetDeniedFlagByPeer(const char * mySocketName,const char * peerSocketName,const char * peerNetworkId)229 bool GetDeniedFlagByPeer(const char *mySocketName, const char *peerSocketName, const char *peerNetworkId)
230 {
231     if (mySocketName == NULL || peerSocketName == NULL || peerNetworkId == NULL || g_bindRequestList == NULL) {
232         return false;
233     }
234 
235     bool flag = false;
236     BindRequestParam bindRequestParam = { {0} };
237     int32_t ret = GenerateParam(mySocketName, peerSocketName, peerNetworkId, &bindRequestParam);
238     if (ret != SOFTBUS_OK) {
239         TRANS_LOGE(TRANS_SVC, "genarate param failed");
240         return flag;
241     }
242     ret = SoftBusMutexLock(&g_bindRequestList->lock);
243     if (ret != SOFTBUS_OK) {
244         TRANS_LOGE(TRANS_SVC, "lock bind request list failed");
245         return flag;
246     }
247 
248     BindRequestManager *bindRequest = GetBindRequestManagerByPeer(&bindRequestParam);
249     if (bindRequest != NULL) {
250         flag = bindRequest->bindDeniedFlag;
251     }
252     (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
253     return flag;
254 }
255 
TransResetBindDeniedFlag(BindRequestParam * bindRequestParam)256 static void TransResetBindDeniedFlag(BindRequestParam *bindRequestParam)
257 {
258     TRANS_CHECK_AND_RETURN_LOGE(g_bindRequestList != NULL, TRANS_SVC, "bind request list no init");
259     int32_t ret = SoftBusMutexLock(&g_bindRequestList->lock);
260     TRANS_CHECK_AND_RETURN_LOGE(ret == SOFTBUS_OK, TRANS_SVC, "lock bind request list failed");
261 
262     BindRequestManager *bindRequest = GetBindRequestManagerByPeer(bindRequestParam);
263     if (bindRequest != NULL) {
264         bindRequest->bindDeniedFlag = false;
265         ListDelete(&bindRequest->node);
266         SoftBusFree(bindRequest);
267         TRANS_LOGI(TRANS_SVC, "close bind request protect.");
268     }
269     (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
270 }
271 
TransBindRequestLoopMsgHandler(SoftBusMessage * msg)272 static void TransBindRequestLoopMsgHandler(SoftBusMessage *msg)
273 {
274     TRANS_LOGD(TRANS_SVC, "trans loop process msgType=%{public}d", msg->what);
275     BindRequestParam *bindRequestParam = (BindRequestParam *)msg->obj;
276     switch (msg->what) {
277         case LOOP_DELETE_TIMESTAMP: {
278             uint64_t timestamp = msg->arg1;
279             TransDelTimestampFormList(bindRequestParam, timestamp);
280             break;
281         }
282         case LOOP_RESET_BIND_DENIED_FLAG: {
283             TransResetBindDeniedFlag(bindRequestParam);
284             break;
285         }
286         default: {
287             TRANS_LOGE(TRANS_SVC, "msg type=%{public}d not support", msg->what);
288             break;
289         }
290     }
291 }
292 
TransBindRequestManagerInit(void)293 int32_t TransBindRequestManagerInit(void)
294 {
295     if (g_bindRequestList != NULL) {
296         TRANS_LOGI(TRANS_INIT, "trans bind request manager has init.");
297         return SOFTBUS_OK;
298     }
299     g_bindRequestList = CreateSoftBusList();
300     if (g_bindRequestList == NULL) {
301         TRANS_LOGE(TRANS_INIT, "create bind request manager failed.");
302         return SOFTBUS_MALLOC_ERR;
303     }
304 
305     g_transLoopHandler.name = (char *)g_transLoopName;
306     g_transLoopHandler.looper = GetLooper(LOOP_TYPE_DEFAULT);
307     if (g_transLoopHandler.looper == NULL) {
308         TRANS_LOGE(TRANS_INIT, "create bind request looper failed.");
309         return SOFTBUS_TRANS_INIT_FAILED;
310     }
311     g_transLoopHandler.HandleMessage = TransBindRequestLoopMsgHandler;
312     return SOFTBUS_OK;
313 }
314 
TransBindRequestManagerDeinit(void)315 void TransBindRequestManagerDeinit(void)
316 {
317     if (g_bindRequestList == NULL) {
318         return;
319     }
320 
321     if (SoftBusMutexLock(&g_bindRequestList->lock) != SOFTBUS_OK) {
322         TRANS_LOGE(TRANS_SVC, "lock failed");
323         return;
324     }
325     BindRequestManager *bindReqItem = NULL;
326     BindRequestManager *bindReqNext = NULL;
327     BindFailInfo *bindFailItem = NULL;
328     BindFailInfo *bindFailNext = NULL;
329     LIST_FOR_EACH_ENTRY_SAFE(bindReqItem, bindReqNext, &g_bindRequestList->list, BindRequestManager, node) {
330         LIST_FOR_EACH_ENTRY_SAFE(bindFailItem, bindFailNext, &bindReqItem->timestampList, BindFailInfo, node) {
331             ListDelete(&bindFailItem->node);
332             SoftBusFree(bindFailItem);
333         }
334         ListDelete(&bindReqItem->node);
335         SoftBusFree(bindReqItem);
336     }
337     (void)SoftBusMutexUnlock(&g_bindRequestList->lock);
338     DestroySoftBusList(g_bindRequestList);
339     g_bindRequestList = NULL;
340     g_transLoopHandler.HandleMessage = NULL;
341     g_transLoopHandler.looper = NULL;
342 }