1 /*
2  * Copyright (c) 2020 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 "dmslite_tlv_common.h"
17 
18 #include "dmslite_inner_common.h"
19 #include "dmslite_utils.h"
20 
21 #include <stdbool.h>
22 #include <string.h>
23 
24 #include "securec.h"
25 
26 #include "dmslite_log.h"
27 
GetNodeByType(uint8_t nodeType,const TlvNode * tlvHead)28 TlvNode* GetNodeByType(uint8_t nodeType, const TlvNode *tlvHead)
29 {
30     TlvNode* tlvNode = (TlvNode *)tlvHead;
31     while (tlvNode != NULL) {
32         if (tlvNode->type == nodeType) {
33             return tlvNode;
34         }
35         tlvNode = tlvNode->next;
36     }
37     return NULL;
38 }
39 
ConvertIntDataBig2Little(const uint8_t * dataIn,uint8_t typeSize)40 static uint64_t ConvertIntDataBig2Little(const uint8_t *dataIn, uint8_t typeSize)
41 {
42     uint64_t dataOut = 0;
43     switch (typeSize) {
44         case INT_16:
45             Convert16DataBig2Little(dataIn, (uint16_t*)&dataOut);
46             break;
47         case INT_32:
48             Convert32DataBig2Little(dataIn, (uint32_t*)&dataOut);
49             break;
50         case INT_64:
51             Convert64DataBig2Little(dataIn, (uint64_t*)&dataOut);
52             break;
53         default:
54             break;
55     }
56     return dataOut;
57 }
58 
ConvertIntByDefault(const uint8_t * dataIn,uint8_t typeSize)59 static uint64_t ConvertIntByDefault(const uint8_t *dataIn, uint8_t typeSize)
60 {
61     switch (typeSize) {
62         case INT_8:
63             return *((int8_t*)dataIn);
64         case INT_16:
65             return *((int16_t*)dataIn);
66         case INT_32:
67             return *((int32_t*)dataIn);
68         case INT_64:
69             return *((int64_t*)dataIn);
70         default:
71             return 0;
72     }
73 }
74 
UnMarshallInt(const TlvNode * tlvHead,uint8_t nodeType,uint8_t fieldSize)75 static uint64_t UnMarshallInt(const TlvNode *tlvHead, uint8_t nodeType, uint8_t fieldSize)
76 {
77     if (tlvHead == NULL) {
78         return 0;
79     }
80     TlvNode* tlvNode = GetNodeByType(nodeType, tlvHead);
81     if (tlvNode == NULL || tlvNode->value == NULL) {
82         HILOGE("[Bad node type %hhu]", nodeType);
83         return 0;
84     }
85     if (fieldSize != tlvNode->length) {
86         HILOGE("[Mismatched fieldSize=%hhu while nodeLength=%hu]", fieldSize, tlvNode->length);
87         return 0;
88     }
89     return IsBigEndian() ? ConvertIntByDefault(tlvNode->value, fieldSize)
90         : ConvertIntDataBig2Little(tlvNode->value, fieldSize);
91 }
92 
UnMarshallUint8(const TlvNode * tlvHead,uint8_t nodeType)93 uint8_t UnMarshallUint8(const TlvNode *tlvHead, uint8_t nodeType)
94 {
95     return UnMarshallInt(tlvHead, nodeType, sizeof(uint8_t));
96 }
97 
UnMarshallUint16(const TlvNode * tlvHead,uint8_t nodeType)98 uint16_t UnMarshallUint16(const TlvNode *tlvHead, uint8_t nodeType)
99 {
100     return UnMarshallInt(tlvHead, nodeType, sizeof(uint16_t));
101 }
102 
UnMarshallUint32(const TlvNode * tlvHead,uint8_t nodeType)103 uint32_t UnMarshallUint32(const TlvNode *tlvHead, uint8_t nodeType)
104 {
105     return UnMarshallInt(tlvHead, nodeType, sizeof(uint32_t));
106 }
107 
UnMarshallUint64(const TlvNode * tlvHead,uint8_t nodeType)108 uint64_t UnMarshallUint64(const TlvNode *tlvHead, uint8_t nodeType)
109 {
110     return UnMarshallInt(tlvHead, nodeType, sizeof(uint64_t));
111 }
112 
UnMarshallInt8(const TlvNode * tlvHead,uint8_t nodeType)113 int8_t UnMarshallInt8(const TlvNode *tlvHead, uint8_t nodeType)
114 {
115     return UnMarshallInt(tlvHead, nodeType, sizeof(int8_t));
116 }
117 
UnMarshallInt16(const TlvNode * tlvHead,uint8_t nodeType)118 int16_t UnMarshallInt16(const TlvNode *tlvHead, uint8_t nodeType)
119 {
120     return UnMarshallInt(tlvHead, nodeType, sizeof(int16_t));
121 }
122 
UnMarshallInt32(const TlvNode * tlvHead,uint8_t nodeType)123 int32_t UnMarshallInt32(const TlvNode *tlvHead, uint8_t nodeType)
124 {
125     return UnMarshallInt(tlvHead, nodeType, sizeof(int32_t));
126 }
127 
UnMarshallInt64(const TlvNode * tlvHead,uint8_t nodeType)128 int64_t UnMarshallInt64(const TlvNode *tlvHead, uint8_t nodeType)
129 {
130     return UnMarshallInt(tlvHead, nodeType, sizeof(int64_t));
131 }
132 
UnMarshallString(const TlvNode * tlvHead,uint8_t nodeType)133 const char* UnMarshallString(const TlvNode *tlvHead, uint8_t nodeType)
134 {
135     HILOGI("[Get string value for node %hhu]", nodeType);
136     if (tlvHead == NULL) {
137         return "";
138     }
139     TlvNode* tlvNode = GetNodeByType(nodeType, tlvHead);
140     if (tlvNode == NULL || tlvNode->value == NULL) {
141         HILOGE("[Bad node type %hhu]", nodeType);
142         return "";
143     }
144     const char* value = (const char*)tlvNode->value;
145     if (value[tlvNode->length - 1] != '\0') {
146         HILOGE("[Non-zero ending string, length:%hu, ending:%d]", tlvNode->length, value[tlvNode->length - 1]);
147         return "";
148     } else {
149         return value;
150     }
151 }