1518678f8Sopenharmony_ci/* 2518678f8Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3518678f8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4518678f8Sopenharmony_ci * you may not use this file except in compliance with the License. 5518678f8Sopenharmony_ci * You may obtain a copy of the License at 6518678f8Sopenharmony_ci * 7518678f8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8518678f8Sopenharmony_ci * 9518678f8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10518678f8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11518678f8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12518678f8Sopenharmony_ci * See the License for the specific language governing permissions and 13518678f8Sopenharmony_ci * limitations under the License. 14518678f8Sopenharmony_ci */ 15518678f8Sopenharmony_ci#include "dhcp_options.h" 16518678f8Sopenharmony_ci 17518678f8Sopenharmony_ci#include <stdio.h> 18518678f8Sopenharmony_ci#include <stdlib.h> 19518678f8Sopenharmony_ci#include <string.h> 20518678f8Sopenharmony_ci 21518678f8Sopenharmony_ci#include "securec.h" 22518678f8Sopenharmony_ci#include "dhcp_logger.h" 23518678f8Sopenharmony_ci 24518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpOptions"); 25518678f8Sopenharmony_ci 26518678f8Sopenharmony_ci/* Check packet option OPTION_OVERLOAD_OPTION. */ 27518678f8Sopenharmony_cistatic bool CheckOptSoverloaded(const struct DhcpPacket *packet, int code, int maxLen, int *over, int *index) 28518678f8Sopenharmony_ci{ 29518678f8Sopenharmony_ci if (packet == nullptr) { 30518678f8Sopenharmony_ci DHCP_LOGE("CheckOptSoverloaded failed, packet == nullptr!"); 31518678f8Sopenharmony_ci return false; 32518678f8Sopenharmony_ci } 33518678f8Sopenharmony_ci 34518678f8Sopenharmony_ci const uint8_t *pOption = packet->options; 35518678f8Sopenharmony_ci if (*index + DHCP_OPT_LEN_INDEX + pOption[*index + DHCP_OPT_LEN_INDEX] >= maxLen) { 36518678f8Sopenharmony_ci DHCP_LOGW("CheckOptSoverloaded code:%{public}d,*index:%{public}d more than max bytes:%{public}d!", 37518678f8Sopenharmony_ci code, *index, maxLen); 38518678f8Sopenharmony_ci return false; 39518678f8Sopenharmony_ci } 40518678f8Sopenharmony_ci *over = pOption[*index + DHCP_OPT_DATA_INDEX + DHCP_OPT_CODE_INDEX]; 41518678f8Sopenharmony_ci *index += pOption[DHCP_OPT_LEN_INDEX] + DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES; 42518678f8Sopenharmony_ci return true; 43518678f8Sopenharmony_ci} 44518678f8Sopenharmony_ci 45518678f8Sopenharmony_ci/* Check packet options based on the code and index. */ 46518678f8Sopenharmony_cistatic int CheckOptionsData(const struct DhcpPacket *packet, int code, int index, int maxLen) 47518678f8Sopenharmony_ci{ 48518678f8Sopenharmony_ci if (packet == nullptr) { 49518678f8Sopenharmony_ci DHCP_LOGE("CheckOptionsData failed, packet == nullptr!"); 50518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 51518678f8Sopenharmony_ci } 52518678f8Sopenharmony_ci 53518678f8Sopenharmony_ci if (index >= maxLen - DHCP_OPT_DATA_INDEX) { 54518678f8Sopenharmony_ci DHCP_LOGW("CheckOptionsData code:%{public}d,index:%{public}d more than max bytes:%{public}d!", 55518678f8Sopenharmony_ci code, index, maxLen); 56518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 57518678f8Sopenharmony_ci } 58518678f8Sopenharmony_ci 59518678f8Sopenharmony_ci const uint8_t *pOption = packet->options; 60518678f8Sopenharmony_ci if (pOption[index + DHCP_OPT_CODE_INDEX] != code) { 61518678f8Sopenharmony_ci return DHCP_OPT_NONE; 62518678f8Sopenharmony_ci } 63518678f8Sopenharmony_ci 64518678f8Sopenharmony_ci if (index + DHCP_OPT_LEN_INDEX + pOption[index + DHCP_OPT_LEN_INDEX] >= maxLen) { 65518678f8Sopenharmony_ci DHCP_LOGW("CheckOptionsData failed, options data too long, code:%{public}d,index:%{public}d!", code, index); 66518678f8Sopenharmony_ci return DHCP_OPT_FAILED; 67518678f8Sopenharmony_ci } 68518678f8Sopenharmony_ci 69518678f8Sopenharmony_ci return DHCP_OPT_SUCCESS; 70518678f8Sopenharmony_ci} 71518678f8Sopenharmony_ci 72518678f8Sopenharmony_ci/* Obtains the data type based on the code. */ 73518678f8Sopenharmony_cistatic uint8_t GetDhcpOptionCodeType(const uint8_t code) 74518678f8Sopenharmony_ci{ 75518678f8Sopenharmony_ci if ((code <= PAD_OPTION) || (code >= END_OPTION)) { 76518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionCodeType error, code:%{public}d is error!", code); 77518678f8Sopenharmony_ci return DHCP_OPTION_DATA_INVALID; 78518678f8Sopenharmony_ci } 79518678f8Sopenharmony_ci 80518678f8Sopenharmony_ci uint8_t nDataType = DHCP_OPTION_DATA_INVALID; 81518678f8Sopenharmony_ci switch (code) { 82518678f8Sopenharmony_ci case DHCP_MESSAGE_TYPE_OPTION: 83518678f8Sopenharmony_ci case FORCERENEW_NONCE_OPTION: 84518678f8Sopenharmony_ci nDataType = DHCP_OPTION_DATA_U8; 85518678f8Sopenharmony_ci break; 86518678f8Sopenharmony_ci case INTERFACE_MTU_OPTION: 87518678f8Sopenharmony_ci case MAXIMUM_DHCP_MESSAGE_SIZE_OPTION: 88518678f8Sopenharmony_ci nDataType = DHCP_OPTION_DATA_U16; 89518678f8Sopenharmony_ci break; 90518678f8Sopenharmony_ci case IP_ADDRESS_LEASE_TIME_OPTION: 91518678f8Sopenharmony_ci nDataType = DHCP_OPTION_DATA_U32; 92518678f8Sopenharmony_ci break; 93518678f8Sopenharmony_ci case SUBNET_MASK_OPTION: 94518678f8Sopenharmony_ci case BROADCAST_ADDRESS_OPTION: 95518678f8Sopenharmony_ci case REQUESTED_IP_ADDRESS_OPTION: 96518678f8Sopenharmony_ci case SERVER_IDENTIFIER_OPTION: 97518678f8Sopenharmony_ci nDataType = DHCP_OPTION_DATA_IP; 98518678f8Sopenharmony_ci break; 99518678f8Sopenharmony_ci case ROUTER_OPTION: 100518678f8Sopenharmony_ci case DOMAIN_NAME_SERVER_OPTION: 101518678f8Sopenharmony_ci case NETWORK_TIME_PROTOCOL_SERVERS_OPTION: 102518678f8Sopenharmony_ci nDataType = DHCP_OPTION_DATA_IP_LIST; 103518678f8Sopenharmony_ci break; 104518678f8Sopenharmony_ci case HOST_NAME_OPTION: 105518678f8Sopenharmony_ci case DOMAIN_NAME_OPTION: 106518678f8Sopenharmony_ci case MESSAGE_OPTION: 107518678f8Sopenharmony_ci nDataType = DHCP_OPTION_DATA_IP_STRING; 108518678f8Sopenharmony_ci break; 109518678f8Sopenharmony_ci default: 110518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionCodeType failed, code:%{public}d is invalid!", code); 111518678f8Sopenharmony_ci break; 112518678f8Sopenharmony_ci } 113518678f8Sopenharmony_ci 114518678f8Sopenharmony_ci return nDataType; 115518678f8Sopenharmony_ci} 116518678f8Sopenharmony_ci 117518678f8Sopenharmony_ci/* Obtains the data length based on the code. */ 118518678f8Sopenharmony_ciuint8_t GetDhcpOptionDataLen(const uint8_t code) 119518678f8Sopenharmony_ci{ 120518678f8Sopenharmony_ci uint8_t nDataType = GetDhcpOptionCodeType(code); 121518678f8Sopenharmony_ci if (nDataType == DHCP_OPTION_DATA_INVALID) { 122518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionDataLen code:%{public}d error, GetDhcpOptionCodeType invalid!", code); 123518678f8Sopenharmony_ci return 0; 124518678f8Sopenharmony_ci } 125518678f8Sopenharmony_ci 126518678f8Sopenharmony_ci uint8_t nDataLen = 0; 127518678f8Sopenharmony_ci switch (nDataType) { 128518678f8Sopenharmony_ci case DHCP_OPTION_DATA_U8: 129518678f8Sopenharmony_ci nDataLen = DHCP_UINT8_BYTES; 130518678f8Sopenharmony_ci break; 131518678f8Sopenharmony_ci case DHCP_OPTION_DATA_U16: 132518678f8Sopenharmony_ci nDataLen = DHCP_UINT16_BYTES; 133518678f8Sopenharmony_ci break; 134518678f8Sopenharmony_ci case DHCP_OPTION_DATA_U32: 135518678f8Sopenharmony_ci nDataLen = DHCP_UINT32_BYTES; 136518678f8Sopenharmony_ci break; 137518678f8Sopenharmony_ci case DHCP_OPTION_DATA_IP: 138518678f8Sopenharmony_ci nDataLen = DHCP_UINT32_BYTES; 139518678f8Sopenharmony_ci break; 140518678f8Sopenharmony_ci case DHCP_OPTION_DATA_IP_PAIR: 141518678f8Sopenharmony_ci nDataLen = DHCP_UINT32_DOUBLE_BYTES; 142518678f8Sopenharmony_ci break; 143518678f8Sopenharmony_ci default: 144518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionDataLen code:%{public}d failed, nDataType:%{public}d is invalid!", 145518678f8Sopenharmony_ci code, nDataType); 146518678f8Sopenharmony_ci break; 147518678f8Sopenharmony_ci } 148518678f8Sopenharmony_ci 149518678f8Sopenharmony_ci return nDataLen; 150518678f8Sopenharmony_ci} 151518678f8Sopenharmony_ci 152518678f8Sopenharmony_ci/* Obtains the data pointer and length from the packet based on the code. */ 153518678f8Sopenharmony_ciconst uint8_t *GetDhcpOption(const struct DhcpPacket *packet, int code, size_t *length) 154518678f8Sopenharmony_ci{ 155518678f8Sopenharmony_ci *length = 0; 156518678f8Sopenharmony_ci if (packet == nullptr) { 157518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOption failed, packet == nullptr!"); 158518678f8Sopenharmony_ci return nullptr; 159518678f8Sopenharmony_ci } 160518678f8Sopenharmony_ci 161518678f8Sopenharmony_ci const uint8_t *pOption = packet->options; 162518678f8Sopenharmony_ci int nIndex = 0, maxLen = DHCP_OPT_SIZE, nOver = 0, nFinished = 0, nFlag = OPTION_FIELD; 163518678f8Sopenharmony_ci while (nFinished == 0) { 164518678f8Sopenharmony_ci int nRet = CheckOptionsData(packet, code, nIndex, maxLen); 165518678f8Sopenharmony_ci if (nRet == DHCP_OPT_SUCCESS) { 166518678f8Sopenharmony_ci *length = pOption[nIndex + DHCP_OPT_LEN_INDEX]; 167518678f8Sopenharmony_ci return pOption + nIndex + DHCP_OPT_DATA_INDEX; 168518678f8Sopenharmony_ci } else if (nRet == DHCP_OPT_FAILED) { 169518678f8Sopenharmony_ci return nullptr; 170518678f8Sopenharmony_ci } 171518678f8Sopenharmony_ci 172518678f8Sopenharmony_ci switch (pOption[nIndex + DHCP_OPT_CODE_INDEX]) { 173518678f8Sopenharmony_ci case PAD_OPTION: 174518678f8Sopenharmony_ci nIndex++; 175518678f8Sopenharmony_ci break; 176518678f8Sopenharmony_ci case OPTION_OVERLOAD_OPTION: 177518678f8Sopenharmony_ci if (!CheckOptSoverloaded(packet, code, maxLen, &nOver, &nIndex)) { 178518678f8Sopenharmony_ci return nullptr; 179518678f8Sopenharmony_ci } 180518678f8Sopenharmony_ci break; 181518678f8Sopenharmony_ci case END_OPTION: 182518678f8Sopenharmony_ci if ((nFlag == OPTION_FIELD) && (nOver & FILE_FIELD)) { 183518678f8Sopenharmony_ci pOption = packet->file; 184518678f8Sopenharmony_ci nIndex = 0; 185518678f8Sopenharmony_ci maxLen = DHCP_BOOT_FILE_LENGTH; 186518678f8Sopenharmony_ci nFlag = FILE_FIELD; 187518678f8Sopenharmony_ci } else if ((nFlag == FILE_FIELD) && (nOver & SNAME_FIELD)) { 188518678f8Sopenharmony_ci pOption = packet->sname; 189518678f8Sopenharmony_ci nIndex = 0; 190518678f8Sopenharmony_ci maxLen = DHCP_HOST_NAME_LENGTH; 191518678f8Sopenharmony_ci nFlag = SNAME_FIELD; 192518678f8Sopenharmony_ci } else { 193518678f8Sopenharmony_ci nFinished = 1; 194518678f8Sopenharmony_ci } 195518678f8Sopenharmony_ci break; 196518678f8Sopenharmony_ci default: 197518678f8Sopenharmony_ci nIndex += DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + pOption[nIndex + DHCP_OPT_LEN_INDEX]; 198518678f8Sopenharmony_ci break; 199518678f8Sopenharmony_ci } 200518678f8Sopenharmony_ci } 201518678f8Sopenharmony_ci DHCP_LOGW("GetDhcpOption options no find code:%{public}d, nIndex:%{public}d!", code, nIndex); 202518678f8Sopenharmony_ci return nullptr; 203518678f8Sopenharmony_ci} 204518678f8Sopenharmony_ci 205518678f8Sopenharmony_ci/* Obtains the uint8 data from the packet based on the code. */ 206518678f8Sopenharmony_cibool GetDhcpOptionUint8(const struct DhcpPacket *packet, int code, uint8_t *data) 207518678f8Sopenharmony_ci{ 208518678f8Sopenharmony_ci size_t len = 0; 209518678f8Sopenharmony_ci const uint8_t *p = GetDhcpOption(packet, code, &len); 210518678f8Sopenharmony_ci if (p == nullptr) { 211518678f8Sopenharmony_ci DHCP_LOGW("GetDhcpOptionUint8 GetDhcpOption nullptr, code:%{public}d!", code); 212518678f8Sopenharmony_ci return false; 213518678f8Sopenharmony_ci } 214518678f8Sopenharmony_ci if (len < static_cast<size_t>(sizeof(uint8_t))) { 215518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionUint8 failed, len:%{public}zu less data:%{public}zu, code:%{public}d!", 216518678f8Sopenharmony_ci len, sizeof(uint8_t), code); 217518678f8Sopenharmony_ci return false; 218518678f8Sopenharmony_ci } 219518678f8Sopenharmony_ci if (memcpy_s(data, sizeof(uint8_t), p, sizeof(uint8_t)) != EOK) { 220518678f8Sopenharmony_ci return false; 221518678f8Sopenharmony_ci } 222518678f8Sopenharmony_ci return true; 223518678f8Sopenharmony_ci} 224518678f8Sopenharmony_ci 225518678f8Sopenharmony_ci/* Obtains the uint32 data from the packet based on the code. */ 226518678f8Sopenharmony_cibool GetDhcpOptionUint32(const struct DhcpPacket *packet, int code, uint32_t *data) 227518678f8Sopenharmony_ci{ 228518678f8Sopenharmony_ci size_t len = 0; 229518678f8Sopenharmony_ci const uint8_t *p = GetDhcpOption(packet, code, &len); 230518678f8Sopenharmony_ci if (p == nullptr) { 231518678f8Sopenharmony_ci DHCP_LOGW("GetDhcpOptionUint32 GetDhcpOption nullptr, code:%{public}d!", code); 232518678f8Sopenharmony_ci return false; 233518678f8Sopenharmony_ci } 234518678f8Sopenharmony_ci uint32_t uData = 0; 235518678f8Sopenharmony_ci if (len < static_cast<size_t>(sizeof(uData))) { 236518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionUint32 failed, len:%{public}zu less uData:%{public}zu, code:%{public}d!", 237518678f8Sopenharmony_ci len, sizeof(uData), code); 238518678f8Sopenharmony_ci return false; 239518678f8Sopenharmony_ci } 240518678f8Sopenharmony_ci if (memcpy_s(&uData, sizeof(uData), p, sizeof(uData)) != EOK) { 241518678f8Sopenharmony_ci return false; 242518678f8Sopenharmony_ci } 243518678f8Sopenharmony_ci if (uData > 0) { 244518678f8Sopenharmony_ci *data = ntohl(uData); 245518678f8Sopenharmony_ci } 246518678f8Sopenharmony_ci return true; 247518678f8Sopenharmony_ci} 248518678f8Sopenharmony_ci 249518678f8Sopenharmony_ci/* Obtains the uint32n data from the packet based on the code. */ 250518678f8Sopenharmony_cibool GetDhcpOptionUint32n(const struct DhcpPacket *packet, int code, uint32_t *data1, uint32_t *data2) 251518678f8Sopenharmony_ci{ 252518678f8Sopenharmony_ci size_t len = 0; 253518678f8Sopenharmony_ci const uint8_t *p = GetDhcpOption(packet, code, &len); 254518678f8Sopenharmony_ci if (p == nullptr) { 255518678f8Sopenharmony_ci DHCP_LOGW("GetDhcpOptionUint32n GetDhcpOption nullptr, code:%{public}d!", code); 256518678f8Sopenharmony_ci return false; 257518678f8Sopenharmony_ci } 258518678f8Sopenharmony_ci uint32_t uData = 0; 259518678f8Sopenharmony_ci if ((len < static_cast<size_t>(sizeof(uData))) || (len % static_cast<size_t>(sizeof(uData)) != 0)) { 260518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionUint32n failed, len:%{public}zu is not %{public}zu * n, code:%{public}d!", 261518678f8Sopenharmony_ci len, sizeof(uData), code); 262518678f8Sopenharmony_ci return false; 263518678f8Sopenharmony_ci } 264518678f8Sopenharmony_ci if (memcpy_s(&uData, sizeof(uData), p, sizeof(uData)) != EOK) { 265518678f8Sopenharmony_ci return false; 266518678f8Sopenharmony_ci } 267518678f8Sopenharmony_ci if (uData > 0) { 268518678f8Sopenharmony_ci *data1 = ntohl(uData); 269518678f8Sopenharmony_ci } 270518678f8Sopenharmony_ci if (len > static_cast<size_t>(sizeof(uData))) { 271518678f8Sopenharmony_ci p += sizeof(uData); 272518678f8Sopenharmony_ci uData = 0; 273518678f8Sopenharmony_ci if (memcpy_s(&uData, sizeof(uData), p, sizeof(uData)) != EOK) { 274518678f8Sopenharmony_ci return false; 275518678f8Sopenharmony_ci } 276518678f8Sopenharmony_ci if (uData > 0) { 277518678f8Sopenharmony_ci *data2 = ntohl(uData); 278518678f8Sopenharmony_ci } 279518678f8Sopenharmony_ci } 280518678f8Sopenharmony_ci return true; 281518678f8Sopenharmony_ci} 282518678f8Sopenharmony_ci 283518678f8Sopenharmony_ci/* Obtains the string data from the packet based on the code. */ 284518678f8Sopenharmony_cichar *GetDhcpOptionString(const struct DhcpPacket *packet, int code) 285518678f8Sopenharmony_ci{ 286518678f8Sopenharmony_ci size_t len; 287518678f8Sopenharmony_ci const uint8_t *p = GetDhcpOption(packet, code, &len); 288518678f8Sopenharmony_ci if ((p == nullptr) || (*p == '\0')) { 289518678f8Sopenharmony_ci DHCP_LOGW("GetDhcpOptionString GetDhcpOption nullptr, code:%{public}d!", code); 290518678f8Sopenharmony_ci return nullptr; 291518678f8Sopenharmony_ci } 292518678f8Sopenharmony_ci if (len < static_cast<size_t>(sizeof(uint8_t))) { 293518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpOptionString failed, len:%{public}zu less data:%{public}zu, code:%{public}d!", 294518678f8Sopenharmony_ci len, sizeof(uint8_t), code); 295518678f8Sopenharmony_ci return nullptr; 296518678f8Sopenharmony_ci } 297518678f8Sopenharmony_ci 298518678f8Sopenharmony_ci char *s = (char *)malloc(sizeof(char) * (len + 1)); 299518678f8Sopenharmony_ci if (s) { 300518678f8Sopenharmony_ci if (memcpy_s(s, len + 1, p, len) != EOK) { 301518678f8Sopenharmony_ci free(s); 302518678f8Sopenharmony_ci s = nullptr; 303518678f8Sopenharmony_ci return nullptr; 304518678f8Sopenharmony_ci } 305518678f8Sopenharmony_ci s[len] = '\0'; 306518678f8Sopenharmony_ci } 307518678f8Sopenharmony_ci return s; 308518678f8Sopenharmony_ci} 309518678f8Sopenharmony_ci 310518678f8Sopenharmony_ci/* Obtain the end index from options. */ 311518678f8Sopenharmony_ciint GetEndOptionIndex(const uint8_t *pOpts) 312518678f8Sopenharmony_ci{ 313518678f8Sopenharmony_ci int nIndex = 0; 314518678f8Sopenharmony_ci while (pOpts[nIndex] != END_OPTION) { 315518678f8Sopenharmony_ci if (pOpts[nIndex] != PAD_OPTION) { 316518678f8Sopenharmony_ci nIndex += pOpts[nIndex + DHCP_OPT_LEN_INDEX] + DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES; 317518678f8Sopenharmony_ci continue; 318518678f8Sopenharmony_ci } 319518678f8Sopenharmony_ci nIndex++; 320518678f8Sopenharmony_ci } 321518678f8Sopenharmony_ci return nIndex; 322518678f8Sopenharmony_ci} 323518678f8Sopenharmony_ci 324518678f8Sopenharmony_ci/* Adds a single option string to options. */ 325518678f8Sopenharmony_ciint AddOptStrToOpts(uint8_t *pOpts, uint8_t *pOpt, int nOptLen) 326518678f8Sopenharmony_ci{ 327518678f8Sopenharmony_ci int optStrLen = DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + pOpt[DHCP_OPT_LEN_INDEX]; 328518678f8Sopenharmony_ci if (nOptLen != optStrLen) { 329518678f8Sopenharmony_ci DHCP_LOGE("AddOptStrToOpts() code:%{public}u nOptLen:%{public}d no equal optStrLen:%{public}d!", 330518678f8Sopenharmony_ci pOpt[DHCP_OPT_CODE_INDEX], nOptLen, optStrLen); 331518678f8Sopenharmony_ci return 0; 332518678f8Sopenharmony_ci } 333518678f8Sopenharmony_ci 334518678f8Sopenharmony_ci int nEndIndex = GetEndOptionIndex(pOpts); 335518678f8Sopenharmony_ci if ((nEndIndex + nOptLen + 1) >= DHCP_OPT_SIZE) { 336518678f8Sopenharmony_ci DHCP_LOGE("AddOptStrToOpts() code:%{public}u did not fit into the packet!", pOpt[DHCP_OPT_CODE_INDEX]); 337518678f8Sopenharmony_ci return 0; 338518678f8Sopenharmony_ci } 339518678f8Sopenharmony_ci 340518678f8Sopenharmony_ci DHCP_LOGD("AddOptStrToOpts() adding option code %{public}u.", pOpt[DHCP_OPT_CODE_INDEX]); 341518678f8Sopenharmony_ci if (memcpy_s(pOpts + nEndIndex, nOptLen + 1, pOpt, nOptLen) != EOK) { 342518678f8Sopenharmony_ci return 0; 343518678f8Sopenharmony_ci } 344518678f8Sopenharmony_ci pOpts[nEndIndex + nOptLen] = END_OPTION; 345518678f8Sopenharmony_ci return nOptLen; 346518678f8Sopenharmony_ci} 347518678f8Sopenharmony_ci 348518678f8Sopenharmony_ci/* Adds a single option value to options. */ 349518678f8Sopenharmony_ciint AddOptValueToOpts(uint8_t *pOpts, uint8_t code, uint32_t value) 350518678f8Sopenharmony_ci{ 351518678f8Sopenharmony_ci uint8_t uLen = GetDhcpOptionDataLen(code); 352518678f8Sopenharmony_ci if (uLen == 0) { 353518678f8Sopenharmony_ci DHCP_LOGE("AddOptValueToOpts() code:%{public}d failed, GetDhcpOptionDataLen uLen:0!", code); 354518678f8Sopenharmony_ci return 0; 355518678f8Sopenharmony_ci } 356518678f8Sopenharmony_ci 357518678f8Sopenharmony_ci uint32_t uValue = 0; 358518678f8Sopenharmony_ci uint8_t *pUint8 = (uint8_t *)&uValue; 359518678f8Sopenharmony_ci uint16_t *pUint16 = (uint16_t *)&uValue; 360518678f8Sopenharmony_ci uint32_t *pUint32 = &uValue; 361518678f8Sopenharmony_ci switch (uLen) { 362518678f8Sopenharmony_ci case DHCP_UINT8_BYTES: 363518678f8Sopenharmony_ci *pUint8 = value; 364518678f8Sopenharmony_ci break; 365518678f8Sopenharmony_ci case DHCP_UINT16_BYTES: 366518678f8Sopenharmony_ci *pUint16 = htons(static_cast<uint16_t>(value)); 367518678f8Sopenharmony_ci break; 368518678f8Sopenharmony_ci case DHCP_UINT32_BYTES: 369518678f8Sopenharmony_ci *pUint32 = value; 370518678f8Sopenharmony_ci break; 371518678f8Sopenharmony_ci default: 372518678f8Sopenharmony_ci DHCP_LOGE("AddOptValueToOpts() uLen:%{public}d error, break!", uLen); 373518678f8Sopenharmony_ci break; 374518678f8Sopenharmony_ci } 375518678f8Sopenharmony_ci 376518678f8Sopenharmony_ci uint8_t uOption[DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + DHCP_UINT32_BYTES]; 377518678f8Sopenharmony_ci uOption[DHCP_OPT_CODE_INDEX] = code; 378518678f8Sopenharmony_ci uOption[DHCP_OPT_LEN_INDEX] = uLen; 379518678f8Sopenharmony_ci if (memcpy_s(uOption + DHCP_OPT_DATA_INDEX, sizeof(uint32_t), &uValue, uLen) != EOK) { 380518678f8Sopenharmony_ci return 0; 381518678f8Sopenharmony_ci } 382518678f8Sopenharmony_ci 383518678f8Sopenharmony_ci int nLen = DHCP_OPT_CODE_BYTES + DHCP_OPT_LEN_BYTES + uOption[DHCP_OPT_LEN_INDEX]; 384518678f8Sopenharmony_ci return AddOptStrToOpts(pOpts, uOption, nLen); 385518678f8Sopenharmony_ci} 386