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 }