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 "syscap_tool.h"
17
18 #include <arpa/inet.h>
19 #include <securec.h>
20
21 #include "hilog/log_c.h"
22
23 const int32_t OK = 0;
24 const int32_t ERROR = -1;
25 const int32_t API_VERSION_TYPE = 1;
26 const int32_t APP_SYSCAP_TYPE = 2;
27 const int32_t SYSCAP_PREFIX_NAME_LEN = 18;
28 const char SYSCAP_PREFIX_NAME[] = "SystemCapability.";
29
30 typedef struct RequiredProductCompatibilityIDHead {
31 uint16_t apiVersion : 15;
32 uint16_t apiVersionType : 1;
33 } RPCIDHead;
34
RPCIDStreamDecodeToBuffer(char * contextBuffer,uint32_t bufferLen,char ** syscapSetBuf,uint32_t * syscapSetLength)35 int32_t RPCIDStreamDecodeToBuffer(
36 char *contextBuffer, uint32_t bufferLen, char **syscapSetBuf, uint32_t *syscapSetLength)
37 {
38 char *contextBufferTail = NULL;
39 char *syscapBuf = NULL;
40 uint32_t syscapBufLen;
41 uint16_t sysCaptype;
42 uint16_t sysCapLength;
43 RPCIDHead *headPtr = NULL;
44 char *sysCapArrayPtr = NULL;
45 if (syscapSetBuf == NULL) {
46 HILOG_ERROR(LOG_CORE, "syscapSetBuf is NULL\n");
47 return ERROR;
48 }
49 *syscapSetBuf = NULL;
50 if (syscapSetLength == NULL) {
51 HILOG_ERROR(LOG_CORE, "syscapSetLength is NULL\n");
52 return ERROR;
53 }
54 *syscapSetLength = 0;
55 if (contextBuffer == NULL) {
56 HILOG_ERROR(LOG_CORE, "input buffer is NULL\n");
57 return ERROR;
58 }
59
60 contextBufferTail = contextBuffer + bufferLen;
61 sysCapArrayPtr = contextBuffer + sizeof(RPCIDHead) + APP_SYSCAP_TYPE * sizeof(uint16_t);
62 if (contextBufferTail <= sysCapArrayPtr) {
63 HILOG_ERROR(LOG_CORE, "format error:sysCapArray head over to buffer\n");
64 return ERROR;
65 }
66
67 headPtr = (RPCIDHead *)contextBuffer;
68 if (headPtr->apiVersionType != API_VERSION_TYPE) {
69 HILOG_ERROR(LOG_CORE, "format error:apiVersionType is invaild\n");
70 return ERROR;
71 }
72
73 sysCaptype = ntohs(*(uint16_t *)(sysCapArrayPtr - APP_SYSCAP_TYPE * sizeof(uint16_t)));
74 if (sysCaptype != APP_SYSCAP_TYPE) {
75 HILOG_ERROR(LOG_CORE, "format error:sysCaptype is invaild\n");
76 return ERROR;
77 }
78
79 sysCapLength = ntohs(*(uint16_t *)(sysCapArrayPtr - sizeof(uint16_t)));
80 if (sysCapLength < 0) {
81 HILOG_ERROR(LOG_CORE, "format error:sysCapLength is invalid\n");
82 return ERROR;
83 }
84 if (contextBufferTail < sysCapArrayPtr + sysCapLength) {
85 HILOG_ERROR(LOG_CORE, "format error:sysCapArray tail over to buffer\n");
86 return ERROR;
87 }
88
89 if ((sysCapLength % SINGLE_FEAT_LENGTH) != 0) {
90 HILOG_ERROR(LOG_CORE, "format error:sysCapLength is invalid\n");
91 return ERROR;
92 }
93
94 syscapBufLen = sysCapLength / SINGLE_FEAT_LENGTH * SINGLE_SYSCAP_LENGTH;
95 syscapBuf = (char *)malloc(syscapBufLen);
96 if (syscapBuf == NULL) {
97 HILOG_ERROR(LOG_CORE, "malloc syscapBuf failed, size = %u, errno = %{public}d\n", syscapBufLen, errno);
98 return ERROR;
99 }
100
101 (void)memset_s(syscapBuf, syscapBufLen, 0, syscapBufLen);
102 char *bufferPtr = syscapBuf;
103 for (int32_t i = 0; i < ((int32_t)sysCapLength / SINGLE_FEAT_LENGTH); i++) {
104 if (*(sysCapArrayPtr + (i + 1) * SINGLE_FEAT_LENGTH - 1) != '\0') {
105 HILOG_ERROR(LOG_CORE, "prase failed, format is invaild, in line %{public}d\n", __LINE__);
106 (void)free(syscapBuf);
107 return ERROR;
108 }
109
110 errno_t ret = memcpy_s(bufferPtr, SINGLE_SYSCAP_LENGTH, SYSCAP_PREFIX_NAME, SYSCAP_PREFIX_NAME_LEN);
111 if (ret != EOK) {
112 HILOG_ERROR(LOG_CORE, "context of \"os\" array is invaild\n");
113 (void)free(syscapBuf);
114 return ERROR;
115 }
116
117 ret = strncat_s(bufferPtr, SINGLE_SYSCAP_LENGTH, sysCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
118 if (ret != EOK) {
119 HILOG_ERROR(LOG_CORE, "strncat_s failed, (%{public}s, %{public}d, %{public}s, %{public}d)\n",
120 bufferPtr, SINGLE_SYSCAP_LENGTH, sysCapArrayPtr + i * SINGLE_FEAT_LENGTH, SINGLE_FEAT_LENGTH);
121 (void)free(syscapBuf);
122 return ERROR;
123 }
124
125 bufferPtr += SINGLE_SYSCAP_LENGTH;
126 }
127
128 *syscapSetBuf = syscapBuf;
129 *syscapSetLength = syscapBufLen;
130 return OK;
131 }