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