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 40static pthread_mutex_t g_buffMutex = PTHREAD_MUTEX_INITIALIZER; 41 42static 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 83static 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 117static 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 134static 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 150static 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 165static 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 190static 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 198static 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 231static 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 259static 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 271static void PrintAllDevices(int fd) 272{ 273 ForEachDeviceDump(DumpOneDevice, fd); 274} 275 276static 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 296void DslmDumper(int fd) 297{ 298 PrintBanner(fd); 299 PrintDefaultStatus(fd); 300 PrintAllDevices(fd); 301}