• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 "dhcp_option.h"
17 #include <stdint.h>
18 #include <cstdlib>
19 #include "dhcp_s_define.h"
20 #include "dhcp_logger.h"
21 #include "securec.h"
22 
23 DEFINE_DHCPLOG_DHCP_LABEL("DhcpServerOption");
24 
CreateOptionNode(PDhcpOption opt)25 PDhcpOptionNode CreateOptionNode(PDhcpOption opt)
26 {
27     if (!opt) {
28         DHCP_LOGE("input parameter is null.");
29         return nullptr;
30     }
31     DhcpOptionNode *pNode = (DhcpOptionNode *)calloc(1, sizeof(DhcpOptionNode));
32     if (pNode == nullptr) {
33         DHCP_LOGE("failed to create dhcp option node!");
34         return nullptr;
35     }
36     pNode->option.code = opt->code;
37     pNode->option.length = opt->length;
38     if (opt == nullptr || opt->length == 0) {
39         free(pNode);
40         return nullptr;
41     }
42     if (memcpy_s(pNode->option.data, sizeof(pNode->option.data), opt->data, opt->length) != EOK) {
43         DHCP_LOGE("create option node failed when memcpy opt data!");
44         free(pNode);
45         pNode = nullptr;
46         return nullptr;
47     }
48     pNode->previous = pNode->next = 0;
49     return pNode;
50 }
51 
HasInitialized(PDhcpOptionList pOptions)52 int HasInitialized(PDhcpOptionList pOptions)
53 {
54     if (!pOptions) {
55         DHCP_LOGE("option list pointer is null.");
56         return 0;
57     }
58     if (pOptions->first != nullptr) {
59         return 1;
60     }
61     return 0;
62 }
63 
InitOptionList(PDhcpOptionList pOptions)64 int InitOptionList(PDhcpOptionList pOptions)
65 {
66     DHCP_LOGI("start %{public}s %{public}d ", __func__, __LINE__);
67     if (!pOptions) {
68         return RET_ERROR;
69     }
70     if (pOptions->first != nullptr && pOptions->first == pOptions->last) {
71         DHCP_LOGE(" start %{public}s %{public}d   over  return success", __func__, __LINE__);
72         return RET_SUCCESS;
73     }
74 
75     DhcpOptionNode *pNode = (DhcpOptionNode *)calloc(1, sizeof(DhcpOptionNode));
76     if (!pNode) {
77         DHCP_LOGE("failed to create dhcp option node!");
78         return 1;
79     }
80 
81     pOptions->size = 0;
82     pOptions->first = pOptions->last = pNode;
83     pOptions->first->previous = nullptr;
84     pOptions->last->next = nullptr;
85     DHCP_LOGI("start %{public}s  %{public}d success ", __func__, __LINE__);
86     return RET_SUCCESS;
87 }
88 
PushBackOption(PDhcpOptionList pOptions,PDhcpOption pOption)89 int PushBackOption(PDhcpOptionList pOptions, PDhcpOption pOption)
90 {
91     if (!pOptions) {
92         DHCP_LOGE("option list pointer is null.");
93         return RET_ERROR;
94     }
95     if (!pOption) {
96         DHCP_LOGE("option pointer is null.");
97         return RET_ERROR;
98     }
99     if (pOptions->first == nullptr) {
100         DHCP_LOGE("option list not initialized");
101         return RET_SUCCESS;
102     }
103     DhcpOptionNode *pNode = CreateOptionNode(pOption);
104     if (!pNode) {
105         DHCP_LOGE("failed to create option node.");
106         return 1;
107     }
108     pNode->previous = pOptions->last;
109     pOptions->last->next = pNode;
110     pOptions->last = pNode;
111     pOptions->size++;
112 
113     return RET_SUCCESS;
114 }
115 
PushFrontOption(PDhcpOptionList pOptions,PDhcpOption pOption)116 int PushFrontOption(PDhcpOptionList pOptions, PDhcpOption pOption)
117 {
118     if (!pOptions) {
119         DHCP_LOGE("option list pointer is null.");
120         return RET_ERROR;
121     }
122     if (!pOption) {
123         DHCP_LOGE("option pointer is null.");
124         return RET_ERROR;
125     }
126     PDhcpOptionNode pNode = CreateOptionNode(pOption);
127     if (!pNode) {
128         return RET_FAILED;
129     }
130 
131     if (pOptions->first == pOptions->last) {
132         pNode->previous = pOptions->first;
133         pOptions->first->next = pNode;
134         pOptions->last = pNode;
135     } else {
136         pNode->next = pOptions->first->next;
137         pNode->next->previous = pNode;
138         pNode->previous = pOptions->first;
139         pOptions->first->next = pNode;
140     }
141     pOptions->size++;
142 
143     return RET_SUCCESS;
144 }
145 
RemoveOption(PDhcpOptionList pOptions,uint8_t code)146 int RemoveOption(PDhcpOptionList pOptions, uint8_t code)
147 {
148     if (pOptions == nullptr) {
149         return RET_ERROR;
150     }
151     if (pOptions->size == 0) {
152         return RET_FAILED;
153     }
154     DhcpOptionNode *pNode = GetOptionNode(pOptions, code);
155     if (pNode == nullptr) {
156         return RET_FAILED;
157     }
158     if (pNode == pOptions->last) {
159         pOptions->last = pNode->previous;
160         pOptions->last->next = nullptr;
161     } else {
162         pNode->next->previous = pNode->previous;
163         pNode->previous->next = pNode->next;
164     }
165     pOptions->size--;
166     free(pNode);
167     pNode = nullptr;
168     return RET_SUCCESS;
169 }
170 
GetOptionNode(PDhcpOptionList pOptions,uint8_t code)171 PDhcpOptionNode GetOptionNode(PDhcpOptionList pOptions, uint8_t code)
172 {
173     if (pOptions->first == nullptr) {
174         return nullptr;
175     }
176     PDhcpOptionNode pNode = pOptions->first->next;
177     while (pNode != nullptr && pNode->option.code != code) {
178         pNode = pNode->next;
179     }
180     return pNode;
181 }
182 
GetOption(PDhcpOptionList pOptions,uint8_t code)183 PDhcpOption GetOption(PDhcpOptionList pOptions, uint8_t code)
184 {
185     PDhcpOptionNode pNode = GetOptionNode(pOptions, code);
186     if (pNode) {
187         return &pNode->option;
188     }
189     return nullptr;
190 }
191 
ClearOptions(PDhcpOptionList pOptions)192 void ClearOptions(PDhcpOptionList pOptions)
193 {
194     if (pOptions == nullptr || pOptions->size == 0) {
195         return;
196     }
197     DhcpOptionNode *pNode = pOptions->first->next;
198     while (pNode != nullptr) {
199         if (pNode == pOptions->last) {
200             pOptions->last = pOptions->first;
201             pOptions->last->next = nullptr;
202         } else {
203             pNode->next->previous = pNode->previous;
204             pNode->previous->next = pNode->next;
205         }
206         free(pNode);
207         pNode = pOptions->first->next;
208     }
209     pNode = pOptions->first;
210     pOptions->size = 0;
211     pOptions->first = pOptions->last = pNode;
212     pOptions->first->previous = nullptr;
213     pOptions->last->next = nullptr;
214 }
215 
FreeOptionList(PDhcpOptionList pOptions)216 void FreeOptionList(PDhcpOptionList pOptions)
217 {
218     if (pOptions == nullptr) {
219         return;
220     }
221     if (pOptions->first == nullptr) {
222         return;
223     }
224     DhcpOptionNode *pNode = pOptions->first->next;
225     while (pNode != nullptr) {
226         if (pNode == pOptions->last) {
227             pOptions->last = pOptions->first;
228             pOptions->last->next = nullptr;
229         } else {
230             pNode->next->previous = pNode->previous;
231             pNode->previous->next = pNode->next;
232         }
233         free(pNode);
234         pNode = pOptions->first->next;
235     }
236     pOptions->size = 0;
237     free(pOptions->first);
238     pOptions->first = pOptions->last = nullptr;
239     return;
240 }
241 
FillOption(PDhcpOption pOption,const char * data,size_t len)242 int FillOption(PDhcpOption pOption, const char *data, size_t len)
243 {
244     if (!pOption) {
245         return RET_ERROR;
246     }
247     if (!data) {
248         return RET_FAILED;
249     }
250     size_t flen = len;
251     if (flen > (DHCP_OPTION_SIZE - 1)) {
252         flen = DHCP_OPTION_SIZE - 1;
253     }
254     if (memcpy_s(pOption->data, sizeof(pOption->data) - 1, data, flen) != EOK) {
255         return RET_ERROR;
256     }
257     pOption->length = static_cast<uint8_t>(flen);
258     return RET_SUCCESS;
259 }
260 
FillU32Option(PDhcpOption pOption,uint32_t u32)261 int FillU32Option(PDhcpOption pOption, uint32_t u32)
262 {
263     if (!pOption) {
264         return RET_ERROR;
265     }
266     if (memcpy_s(pOption->data, sizeof(pOption->data), &u32, sizeof(uint32_t)) != EOK) {
267         return RET_ERROR;
268     }
269     pOption->length = sizeof(uint32_t);
270     return RET_SUCCESS;
271 }
272 
FillOptionData(PDhcpOption pOption,const uint8_t * data,size_t len)273 int FillOptionData(PDhcpOption pOption, const uint8_t *data, size_t len)
274 {
275     size_t flen = len;
276     if (!pOption) {
277         return RET_ERROR;
278     }
279     if (!data) {
280         return RET_FAILED;
281     }
282     if (flen > (DHCP_OPTION_SIZE)) {
283         flen = DHCP_OPTION_SIZE;
284     }
285     if (memcpy_s(pOption->data, sizeof(pOption->data), data, flen) != EOK) {
286         return RET_ERROR;
287     }
288     pOption->length = flen;
289     return RET_SUCCESS;
290 }
291 
AppendAddressOption(PDhcpOption pOption,uint32_t address)292 int AppendAddressOption(PDhcpOption pOption, uint32_t address)
293 {
294     if (!pOption) {
295         return RET_ERROR;
296     }
297     uint8_t addrLen = pOption->length;
298     uint8_t *pData = pOption->data;
299     int spaceSize = sizeof(pOption->data) - addrLen;
300     if (spaceSize < DHCP_ADDRESS_LENGTH) {
301         DHCP_LOGE("failed to append address, not enough space for option data.");
302         return RET_ERROR;
303     }
304     if ((int)addrLen > 0) {
305         pData += addrLen;
306     }
307     if (memcpy_s(pData, spaceSize, &address, DHCP_ADDRESS_LENGTH) != EOK) {
308         return RET_ERROR;
309     }
310     pOption->length += DHCP_ADDRESS_LENGTH;
311     return RET_SUCCESS;
312 }
313