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