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_socket.h" 16518678f8Sopenharmony_ci 17518678f8Sopenharmony_ci#include <stdio.h> 18518678f8Sopenharmony_ci#include <unistd.h> 19518678f8Sopenharmony_ci#include <string.h> 20518678f8Sopenharmony_ci#include <errno.h> 21518678f8Sopenharmony_ci#include <sys/types.h> 22518678f8Sopenharmony_ci#include <sys/socket.h> 23518678f8Sopenharmony_ci#include <netpacket/packet.h> 24518678f8Sopenharmony_ci#include <net/ethernet.h> 25518678f8Sopenharmony_ci#include <net/if.h> 26518678f8Sopenharmony_ci#include <arpa/inet.h> 27518678f8Sopenharmony_ci 28518678f8Sopenharmony_ci#include "dhcp_options.h" 29518678f8Sopenharmony_ci#include "securec.h" 30518678f8Sopenharmony_ci#include "dhcp_logger.h" 31518678f8Sopenharmony_ci 32518678f8Sopenharmony_ciDEFINE_DHCPLOG_DHCP_LABEL("DhcpSocket"); 33518678f8Sopenharmony_ci 34518678f8Sopenharmony_cistatic uint16_t GetCheckSum(uint16_t *pData, int nBytes) 35518678f8Sopenharmony_ci{ 36518678f8Sopenharmony_ci uint32_t uTotalSum = 0; 37518678f8Sopenharmony_ci 38518678f8Sopenharmony_ci /* Calculates the network checksum by 2 bytes. */ 39518678f8Sopenharmony_ci while (nBytes >= DHCP_UINT16_BYTES) { 40518678f8Sopenharmony_ci uTotalSum += *pData++; 41518678f8Sopenharmony_ci nBytes -= DHCP_UINT16_BYTES; 42518678f8Sopenharmony_ci } 43518678f8Sopenharmony_ci /* Calculate the network checksum based on the remaining bytes. */ 44518678f8Sopenharmony_ci if (nBytes > 0) { 45518678f8Sopenharmony_ci uint16_t u16Sum; 46518678f8Sopenharmony_ci *(uint8_t *)(&u16Sum) = *(uint8_t *)pData; 47518678f8Sopenharmony_ci uTotalSum += u16Sum; 48518678f8Sopenharmony_ci } 49518678f8Sopenharmony_ci /* Checksum conversion from 32-bit to 16-bit. */ 50518678f8Sopenharmony_ci while (uTotalSum >> DHCP_UINT16_BITS) { 51518678f8Sopenharmony_ci uTotalSum = (uTotalSum & 0xffff) + (uTotalSum >> DHCP_UINT16_BITS); 52518678f8Sopenharmony_ci } 53518678f8Sopenharmony_ci 54518678f8Sopenharmony_ci return (uint16_t)(~uTotalSum); 55518678f8Sopenharmony_ci} 56518678f8Sopenharmony_ci 57518678f8Sopenharmony_ci/* Raw socket can receive data frames or data packets from the local network interface. */ 58518678f8Sopenharmony_ciint CreateRawSocket(int *rawFd) 59518678f8Sopenharmony_ci{ 60518678f8Sopenharmony_ci int sockFd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); 61518678f8Sopenharmony_ci if (sockFd == -1) { 62518678f8Sopenharmony_ci DHCP_LOGE("CreateRawSocket() failed, socket error:%{public}d.", errno); 63518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 64518678f8Sopenharmony_ci } 65518678f8Sopenharmony_ci *rawFd = sockFd; 66518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 67518678f8Sopenharmony_ci} 68518678f8Sopenharmony_ci 69518678f8Sopenharmony_ci/* Kernel socket can receive data frames or data packets from the local network interface, ip and port. */ 70518678f8Sopenharmony_ciint CreateKernelSocket(int *sockFd) 71518678f8Sopenharmony_ci{ 72518678f8Sopenharmony_ci if (sockFd == NULL) { 73518678f8Sopenharmony_ci DHCP_LOGE("CreateKernelSocket() failed, sockFd is NULL!"); 74518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 75518678f8Sopenharmony_ci } 76518678f8Sopenharmony_ci int nFd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 77518678f8Sopenharmony_ci if (nFd == -1) { 78518678f8Sopenharmony_ci DHCP_LOGE("CreateKernelSocket() failed, socket error:%{public}d.", errno); 79518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 80518678f8Sopenharmony_ci } 81518678f8Sopenharmony_ci *sockFd = nFd; 82518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 83518678f8Sopenharmony_ci} 84518678f8Sopenharmony_ci 85518678f8Sopenharmony_ciint BindRawSocket(const int rawFd, const int ifaceIndex, const uint8_t *ifaceAddr) 86518678f8Sopenharmony_ci{ 87518678f8Sopenharmony_ci if (rawFd < 0) { 88518678f8Sopenharmony_ci DHCP_LOGE("BindRawSocket() failed, rawFd:%{public}d error!", rawFd); 89518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 90518678f8Sopenharmony_ci } 91518678f8Sopenharmony_ci 92518678f8Sopenharmony_ci struct sockaddr_ll rawAddr; 93518678f8Sopenharmony_ci if (memset_s(&rawAddr, sizeof(rawAddr), 0, sizeof(rawAddr)) != EOK) { 94518678f8Sopenharmony_ci DHCP_LOGE("BindRawSocket() failed, memset_s rawAddr error!"); 95518678f8Sopenharmony_ci close(rawFd); 96518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 97518678f8Sopenharmony_ci } 98518678f8Sopenharmony_ci rawAddr.sll_ifindex = ifaceIndex; 99518678f8Sopenharmony_ci rawAddr.sll_protocol = htons(ETH_P_IP); 100518678f8Sopenharmony_ci rawAddr.sll_family = AF_PACKET; 101518678f8Sopenharmony_ci if (ifaceAddr != NULL) { 102518678f8Sopenharmony_ci rawAddr.sll_halen = MAC_ADDR_LEN; 103518678f8Sopenharmony_ci if (memcpy_s(rawAddr.sll_addr, sizeof(rawAddr.sll_addr), ifaceAddr, MAC_ADDR_LEN) != EOK) { 104518678f8Sopenharmony_ci DHCP_LOGE("BindRawSocket() failed, memcpy_s rawAddr.sll_addr error!"); 105518678f8Sopenharmony_ci close(rawFd); 106518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 107518678f8Sopenharmony_ci } 108518678f8Sopenharmony_ci } 109518678f8Sopenharmony_ci int nRet = bind(rawFd, (struct sockaddr *)&rawAddr, sizeof(rawAddr)); 110518678f8Sopenharmony_ci if (nRet == -1) { 111518678f8Sopenharmony_ci DHCP_LOGE("BindRawSocket() index:%{public}d failed, bind error:%{public}d.", ifaceIndex, errno); 112518678f8Sopenharmony_ci close(rawFd); 113518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 114518678f8Sopenharmony_ci } 115518678f8Sopenharmony_ci 116518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 117518678f8Sopenharmony_ci} 118518678f8Sopenharmony_ci 119518678f8Sopenharmony_ciint BindKernelSocket(const int sockFd, const char *ifaceName, const uint32_t sockIp, const int sockPort, bool bCast) 120518678f8Sopenharmony_ci{ 121518678f8Sopenharmony_ci if (sockFd < 0) { 122518678f8Sopenharmony_ci DHCP_LOGE("BindKernelSocket() failed, sockFd:%{public}d error!", sockFd); 123518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 124518678f8Sopenharmony_ci } 125518678f8Sopenharmony_ci 126518678f8Sopenharmony_ci /* Bind the specified interface. */ 127518678f8Sopenharmony_ci if (ifaceName != NULL) { 128518678f8Sopenharmony_ci struct ifreq ifaceReq; 129518678f8Sopenharmony_ci if (strncpy_s(ifaceReq.ifr_name, sizeof(ifaceReq.ifr_name), ifaceName, strlen(ifaceName)) != EOK) { 130518678f8Sopenharmony_ci close(sockFd); 131518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 132518678f8Sopenharmony_ci } 133518678f8Sopenharmony_ci if (setsockopt(sockFd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifaceReq, sizeof(ifaceReq)) == -1) { 134518678f8Sopenharmony_ci DHCP_LOGE("BindKernelSocket() %{public}s SO_BINDTODEVICE error:%{public}d.", ifaceName, errno); 135518678f8Sopenharmony_ci close(sockFd); 136518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 137518678f8Sopenharmony_ci } 138518678f8Sopenharmony_ci } 139518678f8Sopenharmony_ci 140518678f8Sopenharmony_ci /* Set the broadcast feature of the data sent by the socket. */ 141518678f8Sopenharmony_ci if (bCast) { 142518678f8Sopenharmony_ci int broadcast = 1; 143518678f8Sopenharmony_ci if (setsockopt(sockFd, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(int)) == -1) { 144518678f8Sopenharmony_ci DHCP_LOGE("BindKernelSocket() sockFd:%{public}d SO_BROADCAST error:%{public}d.", sockFd, errno); 145518678f8Sopenharmony_ci close(sockFd); 146518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 147518678f8Sopenharmony_ci } 148518678f8Sopenharmony_ci } 149518678f8Sopenharmony_ci 150518678f8Sopenharmony_ci /* Allow multiple sockets to use the same port number. */ 151518678f8Sopenharmony_ci int bReuseaddr = 1; 152518678f8Sopenharmony_ci if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, (const char *)&bReuseaddr, sizeof(bReuseaddr)) == -1) { 153518678f8Sopenharmony_ci DHCP_LOGE("BindKernelSocket() sockFd:%{public}d SO_REUSEADDR error:%{public}d.", sockFd, errno); 154518678f8Sopenharmony_ci close(sockFd); 155518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 156518678f8Sopenharmony_ci } 157518678f8Sopenharmony_ci 158518678f8Sopenharmony_ci struct sockaddr_in kernelAddr; 159518678f8Sopenharmony_ci if (memset_s(&kernelAddr, sizeof(kernelAddr), 0, sizeof(kernelAddr)) != EOK) { 160518678f8Sopenharmony_ci close(sockFd); 161518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 162518678f8Sopenharmony_ci } 163518678f8Sopenharmony_ci kernelAddr.sin_addr.s_addr = sockIp; 164518678f8Sopenharmony_ci kernelAddr.sin_port = htons(sockPort); 165518678f8Sopenharmony_ci kernelAddr.sin_family = AF_INET; 166518678f8Sopenharmony_ci int nRet = bind(sockFd, (struct sockaddr *)&kernelAddr, sizeof(kernelAddr)); 167518678f8Sopenharmony_ci if (nRet == -1) { 168518678f8Sopenharmony_ci DHCP_LOGE("BindKernelSocket() sockFd:%{public}d failed, bind error:%{public}d.", sockFd, errno); 169518678f8Sopenharmony_ci close(sockFd); 170518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 171518678f8Sopenharmony_ci } 172518678f8Sopenharmony_ci 173518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 174518678f8Sopenharmony_ci} 175518678f8Sopenharmony_ci 176518678f8Sopenharmony_ciint SendToDhcpPacket( 177518678f8Sopenharmony_ci const struct DhcpPacket *sendPacket, uint32_t srcIp, uint32_t destIp, int destIndex, const uint8_t *destHwaddr) 178518678f8Sopenharmony_ci{ 179518678f8Sopenharmony_ci DHCP_LOGI("SendToDhcpPacket enter, destIndex:%{public}d, destHwaddr:%{public}d", destIndex, *destHwaddr); 180518678f8Sopenharmony_ci int nFd = -1; 181518678f8Sopenharmony_ci if (CreateRawSocket(&nFd) != SOCKET_OPT_SUCCESS) { 182518678f8Sopenharmony_ci DHCP_LOGE("SendToDhcpPacket CreateRawSocket fail."); 183518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 184518678f8Sopenharmony_ci } 185518678f8Sopenharmony_ci 186518678f8Sopenharmony_ci struct sockaddr_ll rawAddr; 187518678f8Sopenharmony_ci if ((memset_s(&rawAddr, sizeof(rawAddr), 0, sizeof(rawAddr)) != EOK) || 188518678f8Sopenharmony_ci (memcpy_s(rawAddr.sll_addr, sizeof(rawAddr.sll_addr), destHwaddr, MAC_ADDR_LEN) != EOK)) { 189518678f8Sopenharmony_ci close(nFd); 190518678f8Sopenharmony_ci DHCP_LOGE("SendToDhcpPacket memcpy_s fail."); 191518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 192518678f8Sopenharmony_ci } 193518678f8Sopenharmony_ci rawAddr.sll_ifindex = destIndex; 194518678f8Sopenharmony_ci rawAddr.sll_protocol = htons(ETH_P_IP); 195518678f8Sopenharmony_ci rawAddr.sll_family = AF_PACKET; 196518678f8Sopenharmony_ci rawAddr.sll_halen = MAC_ADDR_LEN; 197518678f8Sopenharmony_ci if (bind(nFd, (struct sockaddr *)&rawAddr, sizeof(rawAddr)) == -1) { 198518678f8Sopenharmony_ci close(nFd); 199518678f8Sopenharmony_ci DHCP_LOGE("SendToDhcpPacket bind fail."); 200518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 201518678f8Sopenharmony_ci } 202518678f8Sopenharmony_ci 203518678f8Sopenharmony_ci /* Filling the structure information. */ 204518678f8Sopenharmony_ci struct UdpDhcpPacket udpPackets; 205518678f8Sopenharmony_ci if (memset_s(&udpPackets, sizeof(udpPackets), 0, sizeof(udpPackets)) != EOK) { 206518678f8Sopenharmony_ci close(nFd); 207518678f8Sopenharmony_ci DHCP_LOGE("SendToDhcpPacket memset_s udpPackets fail."); 208518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 209518678f8Sopenharmony_ci } 210518678f8Sopenharmony_ci /* get append options length , include endpoint length(2) */ 211518678f8Sopenharmony_ci int optionLen = GetEndOptionIndex(sendPacket->options) + DHCP_APPEND_LEN; 212518678f8Sopenharmony_ci int sendLen = sizeof(udpPackets) - sizeof(udpPackets.data.options) + optionLen; 213518678f8Sopenharmony_ci int dhcpPackLen = sizeof(struct DhcpPacket) - sizeof(udpPackets.data.options) + optionLen; 214518678f8Sopenharmony_ci udpPackets.udp.source = htons(BOOTP_CLIENT); 215518678f8Sopenharmony_ci udpPackets.udp.dest = htons(BOOTP_SERVER); 216518678f8Sopenharmony_ci udpPackets.udp.len = htons(sizeof(udpPackets.udp) + dhcpPackLen); 217518678f8Sopenharmony_ci udpPackets.ip.tot_len = udpPackets.udp.len; 218518678f8Sopenharmony_ci udpPackets.ip.protocol = IPPROTO_UDP; 219518678f8Sopenharmony_ci udpPackets.ip.saddr = srcIp; 220518678f8Sopenharmony_ci udpPackets.ip.daddr = destIp; 221518678f8Sopenharmony_ci if (memcpy_s(&(udpPackets.data), sizeof(struct DhcpPacket), sendPacket, sizeof(struct DhcpPacket)) != EOK) { 222518678f8Sopenharmony_ci close(nFd); 223518678f8Sopenharmony_ci DHCP_LOGE("SendToDhcpPacket memcpy_s sendPacket fail."); 224518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 225518678f8Sopenharmony_ci } 226518678f8Sopenharmony_ci udpPackets.udp.check = GetCheckSum((uint16_t *)&udpPackets, sizeof(struct UdpDhcpPacket)); 227518678f8Sopenharmony_ci udpPackets.ip.ihl = sizeof(udpPackets.ip) >> DHCP_UINT16_BYTES; 228518678f8Sopenharmony_ci udpPackets.ip.version = IPVERSION; 229518678f8Sopenharmony_ci udpPackets.ip.tot_len = htons(sendLen); 230518678f8Sopenharmony_ci udpPackets.ip.ttl = IPDEFTTL; 231518678f8Sopenharmony_ci udpPackets.ip.check = GetCheckSum((uint16_t *)&(udpPackets.ip), sizeof(udpPackets.ip)); 232518678f8Sopenharmony_ci 233518678f8Sopenharmony_ci ssize_t nBytes = sendto(nFd, &udpPackets, sendLen, 0, (struct sockaddr *)&rawAddr, sizeof(rawAddr)); 234518678f8Sopenharmony_ci if (nBytes <= 0) { 235518678f8Sopenharmony_ci DHCP_LOGE("SendToDhcpPacket optionLen:%{public}d sendLen:%{public}d, " 236518678f8Sopenharmony_ci "dhcpPackLen:%{public}d fd:%{public}d failed, sendto error:%{public}d.", 237518678f8Sopenharmony_ci optionLen, sendLen, dhcpPackLen, nFd, errno); 238518678f8Sopenharmony_ci } else { 239518678f8Sopenharmony_ci DHCP_LOGI("SendToDhcpPacket optionLen:%{public}d sendLen:%{public}d, " 240518678f8Sopenharmony_ci "dhcpPackLen:%{public}d fd:%{public}d, index:%{public}d, bytes:%{public}d.", 241518678f8Sopenharmony_ci optionLen, sendLen, dhcpPackLen, nFd, destIndex, static_cast<int>(nBytes)); 242518678f8Sopenharmony_ci } 243518678f8Sopenharmony_ci close(nFd); 244518678f8Sopenharmony_ci return (nBytes <= 0) ? SOCKET_OPT_FAILED : SOCKET_OPT_SUCCESS; 245518678f8Sopenharmony_ci} 246518678f8Sopenharmony_ci 247518678f8Sopenharmony_ciint SendDhcpPacket(struct DhcpPacket *sendPacket, uint32_t srcIp, uint32_t destIp) 248518678f8Sopenharmony_ci{ 249518678f8Sopenharmony_ci int nFd = -1; 250518678f8Sopenharmony_ci if ((CreateKernelSocket(&nFd) != SOCKET_OPT_SUCCESS) || 251518678f8Sopenharmony_ci (BindKernelSocket(nFd, NULL, srcIp, BOOTP_CLIENT, false) != SOCKET_OPT_SUCCESS)) { 252518678f8Sopenharmony_ci DHCP_LOGE("SendDhcpPacket fd:%{public}d failed!", nFd); 253518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 254518678f8Sopenharmony_ci } 255518678f8Sopenharmony_ci 256518678f8Sopenharmony_ci struct sockaddr_in kernelAddr; 257518678f8Sopenharmony_ci if (memset_s(&kernelAddr, sizeof(kernelAddr), 0, sizeof(kernelAddr)) != EOK) { 258518678f8Sopenharmony_ci close(nFd); 259518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 260518678f8Sopenharmony_ci } 261518678f8Sopenharmony_ci kernelAddr.sin_addr.s_addr = destIp; 262518678f8Sopenharmony_ci kernelAddr.sin_port = htons(BOOTP_SERVER); 263518678f8Sopenharmony_ci kernelAddr.sin_family = AF_INET; 264518678f8Sopenharmony_ci int nRet = connect(nFd, (struct sockaddr *)&kernelAddr, sizeof(kernelAddr)); 265518678f8Sopenharmony_ci if (nRet == -1) { 266518678f8Sopenharmony_ci DHCP_LOGE("SendDhcpPacket nFd:%{public}d failed, connect error:%{public}d.", nFd, errno); 267518678f8Sopenharmony_ci close(nFd); 268518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 269518678f8Sopenharmony_ci } 270518678f8Sopenharmony_ci 271518678f8Sopenharmony_ci ssize_t nBytes = write(nFd, sendPacket, sizeof(struct DhcpPacket)); 272518678f8Sopenharmony_ci if (nBytes <= 0) { 273518678f8Sopenharmony_ci DHCP_LOGE("SendDhcpPacket fd:%{public}d failed, write error:%{public}d.", nFd, errno); 274518678f8Sopenharmony_ci } else { 275518678f8Sopenharmony_ci DHCP_LOGI("SendDhcpPacket fd:%{public}d, bytes:%{public}d.", nFd, static_cast<int>(nBytes)); 276518678f8Sopenharmony_ci } 277518678f8Sopenharmony_ci close(nFd); 278518678f8Sopenharmony_ci return (nBytes <= 0) ? SOCKET_OPT_FAILED : SOCKET_OPT_SUCCESS; 279518678f8Sopenharmony_ci} 280518678f8Sopenharmony_ci 281518678f8Sopenharmony_ciint CheckReadBytes(const int count, const int totLen) 282518678f8Sopenharmony_ci{ 283518678f8Sopenharmony_ci if (count < 0) { 284518678f8Sopenharmony_ci DHCP_LOGE("CheckReadBytes() couldn't read on raw listening socket, count:%{public}d, error:%{public}d!", 285518678f8Sopenharmony_ci count, errno); 286518678f8Sopenharmony_ci return SOCKET_OPT_ERROR; 287518678f8Sopenharmony_ci } 288518678f8Sopenharmony_ci 289518678f8Sopenharmony_ci int nCommonSize = sizeof(struct iphdr) + sizeof(struct udphdr); 290518678f8Sopenharmony_ci if (count < nCommonSize) { 291518678f8Sopenharmony_ci DHCP_LOGE("CheckReadBytes() read size:%{public}d less than common size:%{public}d!", count, nCommonSize); 292518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 293518678f8Sopenharmony_ci } 294518678f8Sopenharmony_ci 295518678f8Sopenharmony_ci if (count < totLen) { 296518678f8Sopenharmony_ci DHCP_LOGE("CheckReadBytes() count:%{public}d less than totLen:%{public}d, packet is Truncated!", count, totLen); 297518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 298518678f8Sopenharmony_ci } 299518678f8Sopenharmony_ci 300518678f8Sopenharmony_ci DHCP_LOGI("CheckReadBytes() count:%{public}d, tot:%{public}d, common:%{public}d.", count, totLen, nCommonSize); 301518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 302518678f8Sopenharmony_ci} 303518678f8Sopenharmony_ci 304518678f8Sopenharmony_ciint CheckUdpPacket(struct UdpDhcpPacket *pPacket, const int totLen) 305518678f8Sopenharmony_ci{ 306518678f8Sopenharmony_ci if (pPacket == NULL) { 307518678f8Sopenharmony_ci DHCP_LOGE("CheckUdpPacket() failed, pPacket == NULL!"); 308518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 309518678f8Sopenharmony_ci } 310518678f8Sopenharmony_ci 311518678f8Sopenharmony_ci if (totLen > (int)sizeof(struct UdpDhcpPacket)) { 312518678f8Sopenharmony_ci DHCP_LOGE("CheckUdpPacket() totLen:%{public}d more than %{public}d!", totLen, 313518678f8Sopenharmony_ci (int)sizeof(struct UdpDhcpPacket)); 314518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 315518678f8Sopenharmony_ci } 316518678f8Sopenharmony_ci 317518678f8Sopenharmony_ci if ((pPacket->ip.protocol != IPPROTO_UDP) || (pPacket->ip.version != IPVERSION)) { 318518678f8Sopenharmony_ci DHCP_LOGE("CheckUdpPacket() failed, pPacket->ip.protocol:%{public}d or version:%{public}u error!", 319518678f8Sopenharmony_ci pPacket->ip.protocol, pPacket->ip.version); 320518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 321518678f8Sopenharmony_ci } 322518678f8Sopenharmony_ci 323518678f8Sopenharmony_ci uint32_t uIhl = (uint32_t)(sizeof(pPacket->ip) >> DHCP_UINT16_BYTES); 324518678f8Sopenharmony_ci if (pPacket->ip.ihl != uIhl) { 325518678f8Sopenharmony_ci DHCP_LOGE("CheckUdpPacket() failed, pPacket->ip.ihl:%{public}u error, uIhl:%{public}u!", pPacket->ip.ihl, uIhl); 326518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 327518678f8Sopenharmony_ci } 328518678f8Sopenharmony_ci 329518678f8Sopenharmony_ci if (pPacket->udp.dest != htons(BOOTP_CLIENT)) { 330518678f8Sopenharmony_ci DHCP_LOGE("CheckUdpPacket() failed, pPacket->udp.dest:%{public}d error, htons:%{public}d!", 331518678f8Sopenharmony_ci pPacket->udp.dest, htons(BOOTP_CLIENT)); 332518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 333518678f8Sopenharmony_ci } 334518678f8Sopenharmony_ci 335518678f8Sopenharmony_ci uint16_t uLen = (uint16_t)(totLen - (int)sizeof(pPacket->ip)); 336518678f8Sopenharmony_ci if (ntohs(pPacket->udp.len) != uLen) { 337518678f8Sopenharmony_ci DHCP_LOGE("CheckUdpPacket() failed, pPacket->udp.len:%{public}d error, uLen:%{public}d!", 338518678f8Sopenharmony_ci pPacket->udp.len, uLen); 339518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 340518678f8Sopenharmony_ci } 341518678f8Sopenharmony_ci DHCP_LOGI("CheckUdpPacket() success, totLen:%{public}d.", totLen); 342518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 343518678f8Sopenharmony_ci} 344518678f8Sopenharmony_ci 345518678f8Sopenharmony_ciint CheckPacketIpSum(struct UdpDhcpPacket *pPacket, const int bytes) 346518678f8Sopenharmony_ci{ 347518678f8Sopenharmony_ci if (pPacket == NULL) { 348518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 349518678f8Sopenharmony_ci } 350518678f8Sopenharmony_ci 351518678f8Sopenharmony_ci if (CheckUdpPacket(pPacket, bytes) != SOCKET_OPT_SUCCESS) { 352518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 353518678f8Sopenharmony_ci } 354518678f8Sopenharmony_ci 355518678f8Sopenharmony_ci /* Check packet ip sum. */ 356518678f8Sopenharmony_ci uint16_t uCheck = pPacket->ip.check; 357518678f8Sopenharmony_ci pPacket->ip.check = 0; 358518678f8Sopenharmony_ci uint16_t uCheckSum = GetCheckSum((uint16_t *)&(pPacket->ip), sizeof(pPacket->ip)); 359518678f8Sopenharmony_ci if (uCheck != uCheckSum) { 360518678f8Sopenharmony_ci DHCP_LOGE("CheckPacketIpSum() failed, ip.check:%{public}d, uCheckSum:%{public}d!", uCheck, uCheckSum); 361518678f8Sopenharmony_ci return SOCKET_OPT_ERROR; 362518678f8Sopenharmony_ci } 363518678f8Sopenharmony_ci DHCP_LOGI("CheckPacketIpSum() success, bytes:%{public}d.", bytes); 364518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 365518678f8Sopenharmony_ci} 366518678f8Sopenharmony_ci 367518678f8Sopenharmony_ciint CheckPacketUdpSum(struct UdpDhcpPacket *pPacket, const int bytes) 368518678f8Sopenharmony_ci{ 369518678f8Sopenharmony_ci if (pPacket == NULL) { 370518678f8Sopenharmony_ci DHCP_LOGE("CheckPacketUdpSum() failed, pPacket == NULL!"); 371518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 372518678f8Sopenharmony_ci } 373518678f8Sopenharmony_ci 374518678f8Sopenharmony_ci /* Check packet udp sum. */ 375518678f8Sopenharmony_ci uint16_t uCheck = pPacket->udp.check; 376518678f8Sopenharmony_ci pPacket->udp.check = 0; 377518678f8Sopenharmony_ci u_int32_t source = pPacket->ip.saddr; 378518678f8Sopenharmony_ci u_int32_t dest = pPacket->ip.daddr; 379518678f8Sopenharmony_ci if (memset_s(&pPacket->ip, sizeof(pPacket->ip), 0, sizeof(pPacket->ip)) != EOK) { 380518678f8Sopenharmony_ci DHCP_LOGE("CheckPacketUdpSum() failed, memset_s ERROR!"); 381518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 382518678f8Sopenharmony_ci } 383518678f8Sopenharmony_ci pPacket->ip.protocol = IPPROTO_UDP; 384518678f8Sopenharmony_ci pPacket->ip.saddr = source; 385518678f8Sopenharmony_ci pPacket->ip.daddr = dest; 386518678f8Sopenharmony_ci pPacket->ip.tot_len = pPacket->udp.len; 387518678f8Sopenharmony_ci uint16_t uCheckSum = GetCheckSum((uint16_t *)pPacket, bytes); 388518678f8Sopenharmony_ci if (uCheck && (uCheck != uCheckSum)) { 389518678f8Sopenharmony_ci DHCP_LOGE("CheckPacketUdpSum() failed, udp.check:%{public}d, uCheckSum:%{public}d!", uCheck, uCheckSum); 390518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 391518678f8Sopenharmony_ci } 392518678f8Sopenharmony_ci DHCP_LOGI("CheckPacketUdpSum() success, bytes:%{public}d.", bytes); 393518678f8Sopenharmony_ci return SOCKET_OPT_SUCCESS; 394518678f8Sopenharmony_ci} 395518678f8Sopenharmony_ci 396518678f8Sopenharmony_ciint GetDhcpRawPacket(struct DhcpPacket *getPacket, int rawFd) 397518678f8Sopenharmony_ci{ 398518678f8Sopenharmony_ci if (getPacket == NULL) { 399518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 400518678f8Sopenharmony_ci } 401518678f8Sopenharmony_ci 402518678f8Sopenharmony_ci /* Get and check udp dhcp packet bytes. */ 403518678f8Sopenharmony_ci struct UdpDhcpPacket udpPackets; 404518678f8Sopenharmony_ci if (memset_s(&udpPackets, sizeof(struct UdpDhcpPacket), 0, sizeof(struct UdpDhcpPacket)) != EOK) { 405518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 406518678f8Sopenharmony_ci } 407518678f8Sopenharmony_ci int nBytes = read(rawFd, &udpPackets, sizeof(struct UdpDhcpPacket)); 408518678f8Sopenharmony_ci int nRet = CheckReadBytes(nBytes, (int)ntohs(udpPackets.ip.tot_len)); 409518678f8Sopenharmony_ci if (nRet != SOCKET_OPT_SUCCESS) { 410518678f8Sopenharmony_ci usleep(SLEEP_TIME_200_MS); 411518678f8Sopenharmony_ci return nRet; 412518678f8Sopenharmony_ci } 413518678f8Sopenharmony_ci 414518678f8Sopenharmony_ci /* Check udp dhcp packet sum. */ 415518678f8Sopenharmony_ci nBytes = (int)ntohs(udpPackets.ip.tot_len); 416518678f8Sopenharmony_ci nRet = CheckPacketIpSum(&udpPackets, nBytes); 417518678f8Sopenharmony_ci if (nRet != SOCKET_OPT_SUCCESS) { 418518678f8Sopenharmony_ci return nRet; 419518678f8Sopenharmony_ci } 420518678f8Sopenharmony_ci nRet = CheckPacketUdpSum(&udpPackets, nBytes); 421518678f8Sopenharmony_ci if (nRet != SOCKET_OPT_SUCCESS) { 422518678f8Sopenharmony_ci return nRet; 423518678f8Sopenharmony_ci } 424518678f8Sopenharmony_ci 425518678f8Sopenharmony_ci int nDhcpPacket = nBytes - (int)(sizeof(udpPackets.ip) + sizeof(udpPackets.udp)); 426518678f8Sopenharmony_ci if (memcpy_s(getPacket, sizeof(struct DhcpPacket), &(udpPackets.data), nDhcpPacket) != EOK) { 427518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpRawPacket() memcpy_s packet.data failed!"); 428518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 429518678f8Sopenharmony_ci } 430518678f8Sopenharmony_ci if (ntohl(getPacket->cookie) != MAGIC_COOKIE) { 431518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpRawPacket() cook:%{public}x error, COOK:%{public}x!", ntohl(getPacket->cookie), MAGIC_COOKIE); 432518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 433518678f8Sopenharmony_ci } 434518678f8Sopenharmony_ci return nDhcpPacket; 435518678f8Sopenharmony_ci} 436518678f8Sopenharmony_ci 437518678f8Sopenharmony_ciint GetDhcpKernelPacket(struct DhcpPacket *getPacket, int sockFd) 438518678f8Sopenharmony_ci{ 439518678f8Sopenharmony_ci if (getPacket == NULL) { 440518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 441518678f8Sopenharmony_ci } 442518678f8Sopenharmony_ci 443518678f8Sopenharmony_ci int nBytes = -1; 444518678f8Sopenharmony_ci if ((nBytes = read(sockFd, getPacket, sizeof(struct DhcpPacket))) == -1) { 445518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpKernelPacket() couldn't read on kernel listening socket, error:%{public}d!", errno); 446518678f8Sopenharmony_ci return SOCKET_OPT_ERROR; 447518678f8Sopenharmony_ci } 448518678f8Sopenharmony_ci 449518678f8Sopenharmony_ci if (ntohl(getPacket->cookie) != MAGIC_COOKIE) { 450518678f8Sopenharmony_ci DHCP_LOGE("GetDhcpKernelPacket() cook:%{public}x error, COOK:%{public}x!", ntohl(getPacket->cookie), 451518678f8Sopenharmony_ci MAGIC_COOKIE); 452518678f8Sopenharmony_ci return SOCKET_OPT_FAILED; 453518678f8Sopenharmony_ci } 454518678f8Sopenharmony_ci return nBytes; 455518678f8Sopenharmony_ci} 456