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