1 /*
2 * Copyright (c) 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 "dslm_hidumper.h"
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <sys/time.h>
21
22 #include "securec.h"
23
24 #include "utils_datetime.h"
25 #include "utils_log.h"
26
27 #include "dslm_credential.h"
28 #include "dslm_device_list.h"
29 #include "dslm_fsm_process.h"
30 #include "dslm_messenger_wrapper.h"
31 #include "dslm_notify_node.h"
32
33 #define SPLIT_LINE "------------------------------------------------------"
34 #define END_LINE "\n"
35
36 #define TIME_STRING_LEN 256
37 #define COST_STRING_LEN 64
38 #define NOTIFY_NODE_MAX_CNT 1024
39
40 static pthread_mutex_t g_buffMutex = PTHREAD_MUTEX_INITIALIZER;
41
GetTimeStringFromTimeStamp(uint64_t timeStamp)42 static const char *GetTimeStringFromTimeStamp(uint64_t timeStamp)
43 {
44 static char timeBuff[TIME_STRING_LEN] = {0};
45 DateTime dateTime = {0};
46 bool success = false;
47 int lockRet = pthread_mutex_lock(&g_buffMutex);
48 if (lockRet != 0) {
49 SECURITY_LOG_ERROR("pthread_mutex_lock error");
50 return "";
51 }
52 do {
53 (void)memset_s(timeBuff, TIME_STRING_LEN, 0, TIME_STRING_LEN);
54 if (timeStamp == 0) {
55 break;
56 }
57 if (!GetDateTimeByMillisecondSinceBoot(timeStamp, &dateTime)) {
58 SECURITY_LOG_ERROR("GetTimeStringFromTimeStamp GetDateTimeByMillisecondSinceBoot error");
59 break;
60 }
61 int ret =
62 snprintf_s(timeBuff, TIME_STRING_LEN, TIME_STRING_LEN - 1, "%04hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu",
63 dateTime.year, dateTime.mon, dateTime.day, dateTime.hour, dateTime.min, dateTime.sec, dateTime.msec);
64 if (ret < 0) {
65 break;
66 }
67 success = true;
68 } while (0);
69
70 if (!success) {
71 if (snprintf_s(timeBuff, TIME_STRING_LEN, TIME_STRING_LEN - 1, "-") < 0) {
72 SECURITY_LOG_ERROR("GetTimeStringFromTimeStamp snprintf_s error");
73 }
74 }
75
76 lockRet = pthread_mutex_unlock(&g_buffMutex);
77 if (lockRet != 0) {
78 SECURITY_LOG_ERROR("pthread_mutex_unlock error");
79 }
80 return timeBuff;
81 }
82
GetCostTime(const uint64_t beginTime, const uint64_t endTime)83 static const char *GetCostTime(const uint64_t beginTime, const uint64_t endTime)
84 {
85 static char costBuff[COST_STRING_LEN] = {0};
86
87 if (beginTime == 0 || endTime == 0) {
88 return "";
89 }
90
91 if (endTime < beginTime) {
92 return "";
93 }
94 uint32_t cost = (uint32_t)(endTime - beginTime);
95
96 int ret = pthread_mutex_lock(&g_buffMutex);
97 if (ret != 0) {
98 SECURITY_LOG_ERROR("pthread_mutex_lock error");
99 return "";
100 }
101
102 if (snprintf_s(costBuff, COST_STRING_LEN, COST_STRING_LEN - 1, "(cost %ums)", cost) < 0) {
103 ret = pthread_mutex_unlock(&g_buffMutex);
104 if (ret != 0) {
105 SECURITY_LOG_ERROR("pthread_mutex_unlock error");
106 }
107 return "";
108 };
109
110 ret = pthread_mutex_unlock(&g_buffMutex);
111 if (ret != 0) {
112 SECURITY_LOG_ERROR("pthread_mutex_unlock error");
113 }
114 return costBuff;
115 }
116
GetMachineState(const DslmDeviceInfo *info)117 static const char *GetMachineState(const DslmDeviceInfo *info)
118 {
119 uint32_t state = GetCurrentMachineState(info);
120 switch (state) {
121 case STATE_INIT:
122 return "STATE_INIT";
123 case STATE_WAITING_CRED_RSP:
124 return "STATE_WAITING_CRED_RSP";
125 case STATE_SUCCESS:
126 return "STATE_SUCCESS";
127 case STATE_FAILED:
128 return "STATE_FAILED";
129 default:
130 return "STATE_UNKOWN";
131 }
132 }
133
GetCreadType(const DslmDeviceInfo *info)134 static const char *GetCreadType(const DslmDeviceInfo *info)
135 {
136 switch (info->credInfo.credType) {
137 case CRED_TYPE_MINI:
138 return "mini";
139 case CRED_TYPE_SMALL:
140 return "small";
141 case CRED_TYPE_STANDARD:
142 return "standard";
143 case CRED_TYPE_LARGE:
144 return "large";
145 default:
146 return "default";
147 }
148 }
149
GetPendingNotifyNodeCnt(const DslmDeviceInfo *info)150 static int32_t GetPendingNotifyNodeCnt(const DslmDeviceInfo *info)
151 {
152 int result = 0;
153 LockDslmStateMachine((DslmDeviceInfo *)info);
154 ListNode *node = NULL;
155 FOREACH_LIST_NODE (node, &info->notifyList) {
156 result++;
157 if (result >= NOTIFY_NODE_MAX_CNT) {
158 break;
159 }
160 }
161 UnLockDslmStateMachine((DslmDeviceInfo *)info);
162 return result;
163 }
164
GetDefaultStatus(int32_t *requestResult, int32_t *verifyResult, uint32_t *credLevel)165 static void GetDefaultStatus(int32_t *requestResult, int32_t *verifyResult, uint32_t *credLevel)
166 {
167 if (requestResult == NULL || verifyResult == NULL || credLevel == NULL) {
168 return;
169 }
170
171 int32_t level = 0;
172 const DeviceIdentify *device = GetSelfDevice(&level);
173 RequestObject object;
174
175 object.arraySize = (uint32_t)GetSupportedCredTypes(object.credArray, MAX_CRED_ARRAY_SIZE);
176 object.challenge = 0x0;
177 object.version = GetCurrentVersion();
178
179 DslmCredBuff *cred = NULL;
180 *requestResult = DefaultRequestDslmCred(device, &object, &cred);
181
182 DslmCredInfo info;
183 (void)memset_s(&info, sizeof(DslmCredInfo), 0, sizeof(DslmCredInfo));
184
185 *verifyResult = DefaultVerifyDslmCred(device, object.challenge, cred, &info);
186 *credLevel = info.credLevel;
187 DestroyDslmCred(cred);
188 }
189
PrintBanner(int fd)190 static void PrintBanner(int fd)
191 {
192 dprintf(fd, " ___ ___ _ __ __ ___ _ _ __ __ ___ ___ ___ " END_LINE);
193 dprintf(fd, "| \\/ __| | | \\/ | | \\| | | | \\/ | _ \\ __| _ \\" END_LINE);
194 dprintf(fd, "| |) \\__ \\ |__| |\\/| | | |) | |_| | |\\/| | _/ __| /" END_LINE);
195 dprintf(fd, "|___/|___/____|_| |_| |___/ \\___/|_| |_|_| |___|_|_\\" END_LINE);
196 }
197
DumpDeviceDetails(const DslmDeviceInfo *info, int32_t fd)198 static void DumpDeviceDetails(const DslmDeviceInfo *info, int32_t fd)
199 {
200 dprintf(fd, "DEVICE_ID : %x" END_LINE, info->machine.machineId);
201 dprintf(fd, END_LINE);
202
203 dprintf(fd, "DEVICE_ONLINE_STATUS : %s" END_LINE, (info->onlineStatus != 0) ? "online" : "offline");
204 dprintf(fd, "DEVICE_ONLINE_TIME : %s" END_LINE, GetTimeStringFromTimeStamp(info->lastOnlineTime));
205 dprintf(fd, "DEVICE_OFFLINE_TIME : %s" END_LINE, GetTimeStringFromTimeStamp(info->lastOfflineTime));
206 dprintf(fd, "DEVICE_REQUEST_TIME : %s" END_LINE, GetTimeStringFromTimeStamp(info->lastRequestTime));
207 dprintf(fd, "DEVICE_RESPONSE_TIME : %s%s" END_LINE, GetTimeStringFromTimeStamp(info->lastResponseTime),
208 GetCostTime(info->lastRequestTime, info->lastResponseTime));
209 dprintf(fd, "DEVICE_VERIFY_TIME : %s%s" END_LINE, GetTimeStringFromTimeStamp(info->lastVerifyTime),
210 GetCostTime(info->lastResponseTime, info->lastVerifyTime));
211 dprintf(fd, END_LINE);
212
213 dprintf(fd, "DEVICE_PENDING_CNT : %d" END_LINE, GetPendingNotifyNodeCnt(info));
214 dprintf(fd, "DEVICE_MACHINE_STATUS : %s" END_LINE, GetMachineState(info));
215 dprintf(fd, "DEVICE_VERIFIED_LEVEL : %u" END_LINE, info->credInfo.credLevel);
216 dprintf(fd, "DEVICE_VERIFIED_RESULT : %s" END_LINE, (info->result == 0) ? "success" : "failed");
217 dprintf(fd, END_LINE);
218
219 dprintf(fd, "CRED_TYPE : %s" END_LINE, GetCreadType(info));
220 dprintf(fd, "CRED_RELEASE_TYPE : %s" END_LINE, info->credInfo.releaseType);
221 dprintf(fd, "CRED_SIGN_TIME : %s" END_LINE, info->credInfo.signTime);
222 dprintf(fd, "CRED_MANUFACTURE : %s" END_LINE, info->credInfo.manufacture);
223 dprintf(fd, "CRED_BAND : %s" END_LINE, info->credInfo.brand);
224 dprintf(fd, "CRED_MODEL : %s" END_LINE, info->credInfo.model);
225 dprintf(fd, "CRED_SOFTWARE_VERSION : %s" END_LINE, info->credInfo.softwareVersion);
226 dprintf(fd, "CRED_SECURITY_LEVEL : %s" END_LINE, info->credInfo.securityLevel);
227 dprintf(fd, "CRED_VERSION : %s" END_LINE, info->credInfo.version);
228 dprintf(fd, END_LINE);
229 }
230
DumpHistoryCalls(const DslmDeviceInfo *info, int32_t fd)231 static void DumpHistoryCalls(const DslmDeviceInfo *info, int32_t fd)
232 {
233 dprintf(fd, "SDK_CALL_HISTORY: " END_LINE);
234 ListNode *node = NULL;
235 int32_t index = 0;
236 FOREACH_LIST_NODE (node, &info->historyList) {
237 index++;
238 DslmNotifyListNode *notifyNode = LIST_ENTRY(node, DslmNotifyListNode, linkNode);
239
240 char timeStart[TIME_STRING_LEN] = {0};
241 if (strcpy_s(timeStart, TIME_STRING_LEN, GetTimeStringFromTimeStamp(notifyNode->start)) != EOK) {
242 continue;
243 }
244 char timeStop[TIME_STRING_LEN] = {0};
245 if (strcpy_s(timeStop, TIME_STRING_LEN, GetTimeStringFromTimeStamp(notifyNode->stop)) != EOK) {
246 continue;
247 }
248
249 uint32_t cost = (notifyNode->stop > notifyNode->start) ? (notifyNode->stop - notifyNode->start) : 0;
250 dprintf(fd, "#%-4d pid:%-6u seq:%-4u req:%-26s res:%-26s ret:%-4u cost:%ums" END_LINE, index, notifyNode->owner,
251 notifyNode->cookie, timeStart, timeStop, notifyNode->result, cost);
252
253 if (index >= NOTIFY_NODE_MAX_CNT) {
254 break;
255 }
256 }
257 }
258
DumpOneDevice(const DslmDeviceInfo *info, int32_t fd)259 static void DumpOneDevice(const DslmDeviceInfo *info, int32_t fd)
260 {
261 if (info == NULL) {
262 return;
263 }
264
265 dprintf(fd, SPLIT_LINE END_LINE);
266 DumpDeviceDetails(info, fd);
267 DumpHistoryCalls(info, fd);
268 dprintf(fd, SPLIT_LINE END_LINE);
269 }
270
PrintAllDevices(int fd)271 static void PrintAllDevices(int fd)
272 {
273 ForEachDeviceDump(DumpOneDevice, fd);
274 }
275
PrintDefaultStatus(int fd)276 static void PrintDefaultStatus(int fd)
277 {
278 int32_t requestResult = 0;
279 int32_t verifyResult = 0;
280 uint32_t credLevel = 0;
281
282 GetDefaultStatus(&requestResult, &verifyResult, &credLevel);
283
284 const time_t YEAR_TIME_2023 = 1699977600;
285 struct timeval timeVal = {0};
286 gettimeofday(&timeVal, NULL);
287 char *notice = timeVal.tv_sec <= YEAR_TIME_2023 ? "(please check the system time)" : "";
288
289 dprintf(fd, SPLIT_LINE END_LINE);
290 dprintf(fd, "REQUEST_TEST : %s" END_LINE, requestResult == SUCCESS ? "success" : "failed");
291 dprintf(fd, "VERIFY_TEST : %s%s" END_LINE, verifyResult == SUCCESS ? "success" : "failed", notice);
292 dprintf(fd, "SELF_CRED_LEVEL : %u" END_LINE, credLevel);
293 dprintf(fd, SPLIT_LINE END_LINE);
294 }
295
DslmDumper(int fd)296 void DslmDumper(int fd)
297 {
298 PrintBanner(fd);
299 PrintDefaultStatus(fd);
300 PrintAllDevices(fd);
301 }