1 /*
2  * Copyright (C) 2021-2023 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 "nstackx_dfinder_mgt_msg_log.h"
17 #include "nstackx_device.h"
18 #include "nstackx_dfinder_hidump.h"
19 #include "nstackx_dfinder_log.h"
20 #include "nstackx_util.h"
21 #include "json_payload.h"
22 
23 #ifdef DFINDER_MGT_MSG_LOG
24 
25 #define TAG "nStackXDFinder"
26 
27 #define MAKE_STR(x) #x
28 
29 static int g_mgtMsgLog = 0;
30 
DFinderSetMgtMsgLog(int enable)31 void DFinderSetMgtMsgLog(int enable)
32 {
33     g_mgtMsgLog = enable;
34     if (g_mgtMsgLog == 0) {
35         DFINDER_LOGD(TAG, "disable management message log");
36         return;
37     }
38     DFINDER_LOGD(TAG, "enable management message log");
39 }
40 
GetCoapReqTypeStr(uint8_t reqType)41 static char *GetCoapReqTypeStr(uint8_t reqType)
42 {
43     switch (reqType) {
44         case COAP_MESSAGE_CON:
45             return MAKE_STR(COAP_MESSAGE_CON);
46         case COAP_MESSAGE_NON:
47             return MAKE_STR(COAP_MESSAGE_NON);
48         case COAP_MESSAGE_ACK:
49             return MAKE_STR(COAP_MESSAGE_ACK);
50         case COAP_MESSAGE_RST:
51             return MAKE_STR(COAP_MESSAGE_RST);
52         default:
53             return NULL;
54     }
55 }
56 
GetBusinessTypeStr(uint8_t businessType)57 static char *GetBusinessTypeStr(uint8_t businessType)
58 {
59     switch (businessType) {
60         case NSTACKX_BUSINESS_TYPE_NULL:
61             return MAKE_STR(NSTACKX_BUSINESS_TYPE_NULL);
62         case NSTACKX_BUSINESS_TYPE_HICOM:
63             return MAKE_STR(NSTACKX_BUSINESS_TYPE_HICOM);
64         case NSTACKX_BUSINESS_TYPE_SOFTBUS:
65             return MAKE_STR(NSTACKX_BUSINESS_TYPE_SOFTBUS);
66         case NSTACKX_BUSINESS_TYPE_NEARBY:
67             return MAKE_STR(NSTACKX_BUSINESS_TYPE_NEARBY);
68         default:
69             return NULL;
70     }
71 }
72 
GetModeTypeStr(uint8_t discMode)73 static char *GetModeTypeStr(uint8_t discMode)
74 {
75     switch (discMode) {
76         case DEFAULT_MODE:
77             return MAKE_STR(DEFAULT_MODE);
78         case DISCOVER_MODE:
79             return MAKE_STR(DISCOVER_MODE);
80         case PUBLISH_MODE_UPLINE:
81             return MAKE_STR(PUBLISH_MODE_UPLINE);
82         case PUBLISH_MODE_OFFLINE:
83             return MAKE_STR(PUBLISH_MODE_OFFLINE);
84         case PUBLISH_MODE_PROACTIVE:
85             return MAKE_STR(PUBLISH_MODE_PROACTIVE);
86         default:
87             return NULL;
88     }
89 }
90 
RemoveCoapReqJsonData(cJSON * data)91 static void RemoveCoapReqJsonData(cJSON *data)
92 {
93     // remove: service data, extend service data, business data, coapUri, device hash
94     cJSON_DeleteItemFromObjectCaseSensitive(data, JSON_SERVICE_DATA);
95     cJSON_DeleteItemFromObjectCaseSensitive(data, JSON_EXTEND_SERVICE_DATA);
96     cJSON_DeleteItemFromObjectCaseSensitive(data, JSON_BUSINESS_DATA);
97     cJSON_DeleteItemFromObjectCaseSensitive(data, JSON_COAP_URI);
98     cJSON_DeleteItemFromObjectCaseSensitive(data, JSON_DEVICE_HASH);
99 }
100 
GetAnonymizedIp(char * dstIp,size_t dstLen,char * srcIp)101 static int32_t GetAnonymizedIp(char *dstIp, size_t dstLen, char *srcIp)
102 {
103     struct sockaddr_in addr;
104     (void)memset_s(&addr, sizeof(struct sockaddr_in), 0, sizeof(struct sockaddr_in));
105     addr.sin_family = AF_INET;
106     addr.sin_addr.s_addr = inet_addr(srcIp);
107     return IpAddrAnonymousFormat(dstIp, dstLen, (struct sockaddr *)&addr, sizeof(addr));
108 }
109 
CheckAnonymizeJsonData(cJSON * data,const char * const jsonKey)110 static cJSON *CheckAnonymizeJsonData(cJSON *data, const char * const jsonKey)
111 {
112     cJSON *item = cJSON_GetObjectItemCaseSensitive(data, jsonKey);
113     if (item == NULL) {
114         DFINDER_LOGE(TAG, "can not get json data with passed key");
115         return NULL;
116     }
117     if (!cJSON_IsString(item) || !strlen(item->valuestring)) {
118         DFINDER_LOGE(TAG, "invalid json data with passed key");
119         return NULL;
120     }
121     return item;
122 }
123 
GetAnonymizedDeviceId(char * srcStr,char * dstStr,size_t dstLen)124 static int32_t GetAnonymizedDeviceId(char *srcStr, char *dstStr, size_t dstLen)
125 {
126     size_t lenFlag = strlen(srcStr) / DFINDER_MGT_UUID_LEN;
127     size_t len = (lenFlag > 0) ? DFINDER_MGT_UUID_LEN : strlen(srcStr);
128     int ret = 0;
129     uint32_t wroteLen = 0;
130     DUMP_MSG_ADD_CHECK(ret, dstStr, wroteLen, dstLen, "%.*s******", len, srcStr);
131     return NSTACKX_EOK;
132 }
133 
AnonymizeDeviceIdJsonData(cJSON * data)134 static int32_t AnonymizeDeviceIdJsonData(cJSON  *data)
135 {
136     cJSON *item = CheckAnonymizeJsonData(data, JSON_DEVICE_ID);
137     if (item == NULL) {
138         return NSTACKX_EFAILED;
139     }
140     char anonyDevId[NSTACKX_MAX_DEVICE_ID_LEN] = {0};
141     if (GetAnonymizedDeviceId(item->valuestring, anonyDevId, sizeof(anonyDevId)) != NSTACKX_EOK) {
142         DFINDER_LOGE(TAG, "get anonymize device id failed");
143         return NSTACKX_EFAILED;
144     }
145     if (!cJSON_ReplaceItemInObjectCaseSensitive(data, JSON_DEVICE_ID, cJSON_CreateString(anonyDevId))) {
146         DFINDER_LOGE(TAG, "replace device id in json failed");
147         return NSTACKX_EFAILED;
148     }
149     return NSTACKX_EOK;
150 }
151 
AnonymizeIpJsonData(cJSON * data)152 static int32_t AnonymizeIpJsonData(cJSON *data)
153 {
154     cJSON *item = CheckAnonymizeJsonData(data, JSON_DEVICE_WLAN_IP);
155     if (item == NULL) {
156         return NSTACKX_EFAILED;
157     }
158     char ipStr[NSTACKX_MAX_IP_STRING_LEN] = {0};
159     int ret = GetAnonymizedIp(ipStr, sizeof(ipStr), item->valuestring);
160     if (ret < 0) {
161         DFINDER_LOGE(TAG, "get anonymized ip failed");
162         return NSTACKX_EFAILED;
163     }
164     if (!cJSON_ReplaceItemInObjectCaseSensitive(data, JSON_DEVICE_WLAN_IP, cJSON_CreateString(ipStr))) {
165         DFINDER_LOGE(TAG, "replace device wlan ip in json failed");
166         return NSTACKX_EFAILED;
167     }
168     return NSTACKX_EOK;
169 }
170 
CheckJsonTypeFiled(cJSON * data,const char * const typeFiled)171 static cJSON *CheckJsonTypeFiled(cJSON *data, const char * const typeFiled)
172 {
173     cJSON *item = cJSON_GetObjectItemCaseSensitive(data, typeFiled);
174     if (item == NULL) {
175         DFINDER_LOGE(TAG, "can not get json data with passed filed");
176         return NULL;
177     }
178     if (!cJSON_IsNumber(item) || (item->valuedouble) < 0) {
179         DFINDER_LOGE(TAG, "invalid json data with passed filed");
180         return NULL;
181     }
182     return item;
183 }
184 
UpdateJsonTypeFiled(cJSON * data,const char * const typeFiled,const char * newTypeStr)185 static int32_t UpdateJsonTypeFiled(cJSON *data, const char * const typeFiled, const char *newTypeStr)
186 {
187     cJSON_DeleteItemFromObjectCaseSensitive(data, typeFiled);
188     cJSON *item = cJSON_CreateString(newTypeStr);
189     if (item == NULL || !cJSON_AddItemToObject(data, typeFiled, item)) {
190         cJSON_Delete(item);
191         DFINDER_LOGE(TAG, "cjson create new type item failed");
192         return NSTACKX_EFAILED;
193     }
194     return NSTACKX_EOK;
195 }
196 
BusinessTypeToJsonStr(cJSON * data)197 static int32_t BusinessTypeToJsonStr(cJSON *data)
198 {
199     cJSON *item = CheckJsonTypeFiled(data, JSON_BUSINESS_TYPE);
200     if (item == NULL) {
201         return NSTACKX_EFAILED;
202     }
203     char *businessTypeStr = GetBusinessTypeStr((uint8_t)item->valuedouble);
204     if (businessTypeStr == NULL) {
205         DFINDER_LOGE(TAG, "get business type str failed");
206         return NSTACKX_EFAILED;
207     }
208     return UpdateJsonTypeFiled(data, JSON_BUSINESS_TYPE, businessTypeStr);
209 }
210 
ModeTypeToJsonStr(cJSON * data)211 static int32_t ModeTypeToJsonStr(cJSON *data)
212 {
213     cJSON *item = CheckJsonTypeFiled(data, JSON_REQUEST_MODE);
214     if (item == NULL) {
215         return NSTACKX_EFAILED;
216     }
217     char *modeTypeStr = GetModeTypeStr((uint8_t)item->valuedouble);
218     if (modeTypeStr == NULL) {
219         DFINDER_LOGE(TAG, "get mode type str failed");
220         return NSTACKX_EFAILED;
221     }
222     return UpdateJsonTypeFiled(data, JSON_REQUEST_MODE, modeTypeStr);
223 }
224 
ParseCoapRequestData(const char * reqData,size_t dataLen)225 static char *ParseCoapRequestData(const char *reqData, size_t dataLen)
226 {
227     if (reqData == NULL || dataLen == 0) {
228         DFINDER_LOGE(TAG, "illegal coap request data");
229         return NULL;
230     }
231     char *dupReqData = (char *)malloc(dataLen);
232     if (dupReqData == NULL) {
233         DFINDER_LOGE(TAG, "malloc for duplicate request data failed");
234         return NULL;
235     }
236     (void)memcpy_s(dupReqData, dataLen, reqData, dataLen);
237     char *formatString = NULL;
238     cJSON *data = cJSON_Parse(dupReqData);
239     if (data == NULL) {
240         DFINDER_LOGE(TAG, "cjson parse coap request data failed");
241         goto L_END_JSON;
242     }
243     RemoveCoapReqJsonData(data);
244     if (BusinessTypeToJsonStr(data) != NSTACKX_EOK) {
245         goto L_END_JSON;
246     }
247     if (ModeTypeToJsonStr(data) != NSTACKX_EOK) {
248         goto L_END_JSON;
249     }
250     if (AnonymizeDeviceIdJsonData(data) != NSTACKX_EOK) {
251         goto L_END_JSON;
252     }
253     if (AnonymizeIpJsonData(data) != NSTACKX_EOK) {
254         goto L_END_JSON;
255     }
256     formatString = cJSON_PrintUnformatted(data);
257     if (formatString == NULL) {
258         DFINDER_LOGE(TAG, "cjson print unformatted data failed");
259         goto L_END_JSON;
260     }
261 L_END_JSON:
262     cJSON_Delete(data);
263     free(dupReqData);
264     return formatString;
265 }
266 
DFinderMgtReqLog(CoapRequest * coapRequest)267 void DFinderMgtReqLog(CoapRequest *coapRequest)
268 {
269     if (!g_mgtMsgLog) {
270         return;
271     }
272     char *coapReqData = ParseCoapRequestData(coapRequest->data, coapRequest->dataLength);
273     if (coapReqData == NULL) {
274         DFINDER_LOGE(TAG, "parse coap request data failed");
275         return;
276     }
277     DFINDER_LOGI(TAG, "coap msg type: %s, coap req data: %s", GetCoapReqTypeStr(coapRequest->type), coapReqData);
278     cJSON_free(coapReqData);
279 }
280 
UnpackLogToStr(DeviceInfo * dev,char * msg,uint32_t size)281 static int32_t UnpackLogToStr(DeviceInfo *dev, char *msg, uint32_t size)
282 {
283     char ip[NSTACKX_MAX_IP_STRING_LEN] = {0};
284     if (inet_ntop(AF_INET, &(dev->netChannelInfo.wifiApInfo.ip), ip, sizeof(ip)) == NULL) {
285         DFINDER_LOGE(TAG, "convert ip struct failed");
286         return NSTACKX_EFAILED;
287     }
288     char ipStr[NSTACKX_MAX_IP_STRING_LEN] = {0};
289     if (GetAnonymizedIp(ipStr, sizeof(ipStr), ip) < 0) {
290         DFINDER_LOGE(TAG, "get anonymized ip failed");
291         return NSTACKX_EFAILED;
292     }
293     char anonyDevId[NSTACKX_MAX_DEVICE_ID_LEN] = {0};
294     if (GetAnonymizedDeviceId(dev->deviceId, anonyDevId, sizeof(anonyDevId)) != NSTACKX_EOK) {
295         DFINDER_LOGE(TAG, "get anonymize device id failed");
296         return NSTACKX_EFAILED;
297     }
298 
299     uint32_t wroteLen = 0;
300     int ret = 0;
301     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size, "deviceId: %s ", anonyDevId);
302     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size, "devicename: %s, ", dev->deviceName);
303     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size, "type: %u, ", dev->deviceType);
304     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size, "hicomversion: %s, ", dev->version);
305     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size, "mode: %s, ", GetModeTypeStr(dev->mode));
306     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size,
307         "bType: %s, ", GetBusinessTypeStr(dev->businessType));
308     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size, "wlanIp: %s, ", ipStr);
309     DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size,
310         "bcast: %hhu, ", dev->businessData.isBroadcast);
311     for (uint32_t i = 0; i < dev->capabilityBitmapNum; ++i) {
312         DUMP_MSG_ADD_CHECK(ret, msg, wroteLen, size,
313             "cap[%u]:%u, ", i, dev->capabilityBitmap[i]);
314     }
315     DFINDER_LOGI(TAG, "%s", msg);
316     return NSTACKX_EOK;
317 }
318 
DFinderMgtUnpackLog(DeviceInfo * dev)319 void DFinderMgtUnpackLog(DeviceInfo *dev)
320 {
321     if (!g_mgtMsgLog) {
322         return;
323     }
324 
325     if (dev == NULL) {
326         DFINDER_LOGE(TAG, "invalid deviceInfo");
327         return;
328     }
329 
330     char *msg = (char *)malloc(DFINDER_MGT_UNPACK_LOG_LEN);
331     if (msg == NULL) {
332         DFINDER_LOGE(TAG, "malloc failed");
333         return;
334     }
335     (void)memset_s(msg, DFINDER_MGT_UNPACK_LOG_LEN, 0, DFINDER_MGT_UNPACK_LOG_LEN);
336     if (UnpackLogToStr(dev, msg, DFINDER_MGT_UNPACK_LOG_LEN) != NSTACKX_EOK) {
337         DFINDER_LOGE(TAG, "unpack log to string failed");
338     }
339     free(msg);
340 }
341 #endif /* END OF DFINDER_MGT_MSG_LOG */
342