1 /*
2  * Copyright (C) 2021 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 #include "dhcp_socket.h"
16 
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <errno.h>
21 #include <linux/filter.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netpacket/packet.h>
25 #include <net/ethernet.h>
26 #include <net/if.h>
27 #include <arpa/inet.h>
28 
29 #include "dhcp_options.h"
30 #include "securec.h"
31 #include "dhcp_logger.h"
32 
33 DEFINE_DHCPLOG_DHCP_LABEL("DhcpSocket");
34 
35 namespace {
36 constexpr uint32_t ETHER_HEADER_LEN = 0;
37 constexpr uint32_t IPV4_PROTOCOL = ETHER_HEADER_LEN + offsetof(iphdr, protocol);
38 constexpr uint32_t IPV4_FLAGS_OFFSET = ETHER_HEADER_LEN + offsetof(iphdr, frag_off);
39 constexpr uint32_t UDP_DST_PORT_INDIRECT_OFFSET = ETHER_HEADER_LEN + offsetof(udphdr, dest);
40 constexpr uint16_t DHCP_CLIENT_PORT = 68;
41 sock_filter g_filterCode[] = {
42     // Check the protocol is UDP.
43     BPF_STMT(BPF_LD  | BPF_B    | BPF_ABS, IPV4_PROTOCOL),
44     BPF_JUMP(BPF_JMP | BPF_JEQ  | BPF_K,   IPPROTO_UDP, 0, 6),
45 
46     // Check this is not a fragment.
47     BPF_STMT(BPF_LD  | BPF_H    | BPF_ABS, IPV4_FLAGS_OFFSET),
48     BPF_JUMP(BPF_JMP | BPF_JSET | BPF_K,   IP_OFFMASK, 4, 0),
49 
50     // Get the IP header length.
51     BPF_STMT(BPF_LDX | BPF_B    | BPF_MSH, ETHER_HEADER_LEN),
52 
53     // Check the destination port.
54     BPF_STMT(BPF_LD  | BPF_H    | BPF_IND, UDP_DST_PORT_INDIRECT_OFFSET),
55     BPF_JUMP(BPF_JMP | BPF_JEQ  | BPF_K,   DHCP_CLIENT_PORT, 0, 1),
56 
57     // Accept or reject.
58     BPF_STMT(BPF_RET | BPF_K,              0xffff),
59     BPF_STMT(BPF_RET | BPF_K,              0)
60 };
61 const sock_fprog g_filter = {
62     sizeof(g_filterCode) / sizeof(sock_filter),
63     g_filterCode,
64 };
65 }
66 
GetCheckSum(uint16_t * pData,int nBytes)67 static uint16_t GetCheckSum(uint16_t *pData, int nBytes)
68 {
69     uint32_t uTotalSum = 0;
70 
71     /* Calculates the network checksum by 2 bytes. */
72     while (nBytes >= DHCP_UINT16_BYTES)  {
73         uTotalSum += *pData++;
74         nBytes -= DHCP_UINT16_BYTES;
75     }
76     /* Calculate the network checksum based on the remaining bytes. */
77     if (nBytes > 0) {
78         uint16_t u16Sum;
79         *(uint8_t *)(&u16Sum) = *(uint8_t *)pData;
80         uTotalSum += u16Sum;
81     }
82     /* Checksum conversion from 32-bit to 16-bit. */
83     while (uTotalSum >> DHCP_UINT16_BITS) {
84         uTotalSum = (uTotalSum & 0xffff) + (uTotalSum >> DHCP_UINT16_BITS);
85     }
86 
87     return (uint16_t)(~uTotalSum);
88 }
89 
90 /* Raw socket can receive data frames or data packets from the local network interface. */
CreateRawSocket(int * rawFd)91 int CreateRawSocket(int *rawFd)
92 {
93     int sockFd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
94     if (sockFd == -1) {
95         DHCP_LOGE("CreateRawSocket() failed, socket error:%{public}d.", errno);
96         return SOCKET_OPT_FAILED;
97     }
98     *rawFd = sockFd;
99     return SOCKET_OPT_SUCCESS;
100 }
101 
102 /* Kernel socket can receive data frames or data packets from the local network interface, ip and port. */
CreateKernelSocket(int * sockFd)103 int CreateKernelSocket(int *sockFd)
104 {
105     if (sockFd == NULL) {
106         DHCP_LOGE("CreateKernelSocket() failed, sockFd is NULL!");
107         return SOCKET_OPT_FAILED;
108     }
109     int nFd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
110     if (nFd == -1) {
111         DHCP_LOGE("CreateKernelSocket() failed, socket error:%{public}d.", errno);
112         return SOCKET_OPT_FAILED;
113     }
114     *sockFd = nFd;
115     return SOCKET_OPT_SUCCESS;
116 }
117 
BindRawSocket(const int rawFd,const int ifaceIndex,const uint8_t * ifaceAddr)118 int BindRawSocket(const int rawFd, const int ifaceIndex, const uint8_t *ifaceAddr)
119 {
120     if (rawFd < 0) {
121         DHCP_LOGE("BindRawSocket() failed, rawFd:%{public}d error!", rawFd);
122         return SOCKET_OPT_FAILED;
123     }
124 
125     struct sockaddr_ll rawAddr;
126     if (memset_s(&rawAddr, sizeof(rawAddr), 0, sizeof(rawAddr)) != EOK) {
127         DHCP_LOGE("BindRawSocket() failed, memset_s rawAddr error!");
128         close(rawFd);
129         return SOCKET_OPT_FAILED;
130     }
131     rawAddr.sll_ifindex = ifaceIndex;
132     rawAddr.sll_protocol = htons(ETH_P_IP);
133     rawAddr.sll_family = AF_PACKET;
134     if (ifaceAddr != NULL) {
135         rawAddr.sll_halen = MAC_ADDR_LEN;
136         if (memcpy_s(rawAddr.sll_addr, sizeof(rawAddr.sll_addr), ifaceAddr, MAC_ADDR_LEN) != EOK) {
137             DHCP_LOGE("BindRawSocket() failed, memcpy_s rawAddr.sll_addr error!");
138             close(rawFd);
139             return SOCKET_OPT_FAILED;
140         }
141     }
142     if (setsockopt(rawFd, SOL_SOCKET, SO_ATTACH_FILTER, &g_filter, sizeof(g_filter)) == -1) {
143         DHCP_LOGE("BindRawSocket() SO_ATTACH_FILTER error:%{public}d.", errno);
144     }
145     int nRet = bind(rawFd, (struct sockaddr *)&rawAddr, sizeof(rawAddr));
146     if (nRet == -1) {
147         DHCP_LOGE("BindRawSocket() index:%{public}d failed, bind error:%{public}d.", ifaceIndex, errno);
148         close(rawFd);
149         return SOCKET_OPT_FAILED;
150     }
151 
152     return SOCKET_OPT_SUCCESS;
153 }
154 
BindKernelSocket(const int sockFd,const char * ifaceName,const uint32_t sockIp,const int sockPort,bool bCast)155 int BindKernelSocket(const int sockFd, const char *ifaceName, const uint32_t sockIp, const int sockPort, bool bCast)
156 {
157     if (sockFd < 0) {
158         DHCP_LOGE("BindKernelSocket() failed, sockFd:%{public}d error!", sockFd);
159         return SOCKET_OPT_FAILED;
160     }
161 
162     /* Bind the specified interface. */
163     if (ifaceName != NULL) {
164         struct ifreq ifaceReq;
165         if (strncpy_s(ifaceReq.ifr_name, sizeof(ifaceReq.ifr_name), ifaceName, strlen(ifaceName)) != EOK) {
166             close(sockFd);
167             return SOCKET_OPT_FAILED;
168         }
169         if (setsockopt(sockFd, SOL_SOCKET, SO_BINDTODEVICE, (char *)&ifaceReq, sizeof(ifaceReq)) == -1) {
170             DHCP_LOGE("BindKernelSocket() %{public}s SO_BINDTODEVICE error:%{public}d.", ifaceName, errno);
171             close(sockFd);
172             return SOCKET_OPT_FAILED;
173         }
174     }
175 
176     /* Set the broadcast feature of the data sent by the socket. */
177     if (bCast) {
178         int broadcast = 1;
179         if (setsockopt(sockFd, SOL_SOCKET, SO_BROADCAST, (const char *)&broadcast, sizeof(int)) == -1) {
180             DHCP_LOGE("BindKernelSocket() sockFd:%{public}d SO_BROADCAST error:%{public}d.", sockFd, errno);
181             close(sockFd);
182             return SOCKET_OPT_FAILED;
183         }
184     }
185     /* Allow multiple sockets to use the same port number. */
186     int bReuseaddr = 1;
187     if (setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, (const char *)&bReuseaddr, sizeof(bReuseaddr)) == -1) {
188         DHCP_LOGE("BindKernelSocket() sockFd:%{public}d SO_REUSEADDR error:%{public}d.", sockFd, errno);
189         close(sockFd);
190         return SOCKET_OPT_FAILED;
191     }
192     if (setsockopt(sockFd, SOL_SOCKET, SO_ATTACH_FILTER, &g_filter, sizeof(g_filter)) == -1) {
193         DHCP_LOGE("BindKernelSocket() SO_ATTACH_FILTER error:%{public}d.", errno);
194         close(sockFd);
195         return SOCKET_OPT_FAILED;
196     }
197     struct sockaddr_in kernelAddr;
198     if (memset_s(&kernelAddr, sizeof(kernelAddr), 0, sizeof(kernelAddr)) != EOK) {
199         close(sockFd);
200         return SOCKET_OPT_FAILED;
201     }
202     kernelAddr.sin_addr.s_addr = sockIp;
203     kernelAddr.sin_port = htons(sockPort);
204     kernelAddr.sin_family = AF_INET;
205     int nRet = bind(sockFd, (struct sockaddr *)&kernelAddr, sizeof(kernelAddr));
206     if (nRet == -1) {
207         DHCP_LOGE("BindKernelSocket() sockFd:%{public}d failed, bind error:%{public}d.", sockFd, errno);
208         close(sockFd);
209         return SOCKET_OPT_FAILED;
210     }
211 
212     return SOCKET_OPT_SUCCESS;
213 }
214 
SendToDhcpPacket(const struct DhcpPacket * sendPacket,uint32_t srcIp,uint32_t destIp,int destIndex,const uint8_t * destHwaddr)215 int SendToDhcpPacket(
216     const struct DhcpPacket *sendPacket, uint32_t srcIp, uint32_t destIp, int destIndex, const uint8_t *destHwaddr)
217 {
218     DHCP_LOGI("SendToDhcpPacket enter, destIndex:%{public}d, destHwaddr:%{public}d", destIndex, *destHwaddr);
219     int nFd = -1;
220     if (CreateRawSocket(&nFd) != SOCKET_OPT_SUCCESS) {
221         DHCP_LOGE("SendToDhcpPacket CreateRawSocket fail.");
222         return SOCKET_OPT_FAILED;
223     }
224 
225     struct sockaddr_ll rawAddr;
226     if ((memset_s(&rawAddr, sizeof(rawAddr), 0, sizeof(rawAddr)) != EOK) ||
227         (memcpy_s(rawAddr.sll_addr, sizeof(rawAddr.sll_addr), destHwaddr, MAC_ADDR_LEN) != EOK)) {
228         close(nFd);
229         DHCP_LOGE("SendToDhcpPacket memcpy_s fail.");
230         return SOCKET_OPT_FAILED;
231     }
232     rawAddr.sll_ifindex = destIndex;
233     rawAddr.sll_protocol = htons(ETH_P_IP);
234     rawAddr.sll_family = AF_PACKET;
235     rawAddr.sll_halen = MAC_ADDR_LEN;
236     if (bind(nFd, (struct sockaddr *)&rawAddr, sizeof(rawAddr)) == -1) {
237         close(nFd);
238         DHCP_LOGE("SendToDhcpPacket bind fail.");
239         return SOCKET_OPT_FAILED;
240     }
241 
242     /* Filling the structure information. */
243     struct UdpDhcpPacket udpPackets;
244     if (memset_s(&udpPackets, sizeof(udpPackets), 0, sizeof(udpPackets)) != EOK) {
245         close(nFd);
246         DHCP_LOGE("SendToDhcpPacket memset_s udpPackets fail.");
247         return SOCKET_OPT_FAILED;
248     }
249     /* get append options length , include endpoint length(3) */
250     int optionLen = GetEndOptionIndex(sendPacket->options) + 3;
251     int sendLen = sizeof(udpPackets) - sizeof(udpPackets.data.options) + optionLen;
252     int dhcpPackLen = sizeof(struct DhcpPacket) - sizeof(udpPackets.data.options) + optionLen;
253     udpPackets.udp.source = htons(BOOTP_CLIENT);
254     udpPackets.udp.dest = htons(BOOTP_SERVER);
255     udpPackets.udp.len = htons(sizeof(udpPackets.udp) + dhcpPackLen);
256     udpPackets.ip.tot_len = udpPackets.udp.len;
257     udpPackets.ip.protocol = IPPROTO_UDP;
258     udpPackets.ip.saddr = srcIp;
259     udpPackets.ip.daddr = destIp;
260     if (memcpy_s(&(udpPackets.data), sizeof(struct DhcpPacket), sendPacket, sizeof(struct DhcpPacket)) != EOK) {
261         close(nFd);
262         DHCP_LOGE("SendToDhcpPacket memcpy_s sendPacket fail.");
263         return SOCKET_OPT_FAILED;
264     }
265     udpPackets.udp.check = GetCheckSum((uint16_t *)&udpPackets, sizeof(struct UdpDhcpPacket));
266     udpPackets.ip.ihl = sizeof(udpPackets.ip) >> DHCP_UINT16_BYTES;
267     udpPackets.ip.version = IPVERSION;
268     udpPackets.ip.tot_len = htons(sendLen);
269     udpPackets.ip.ttl = IPDEFTTL;
270     udpPackets.ip.check = GetCheckSum((uint16_t *)&(udpPackets.ip), sizeof(udpPackets.ip));
271 
272     ssize_t nBytes = sendto(nFd, &udpPackets, sendLen, 0, (struct sockaddr *)&rawAddr, sizeof(rawAddr));
273     if (nBytes <= 0) {
274         DHCP_LOGE("SendToDhcpPacket optionLen:%{public}d sendLen:%{public}d, "
275             "dhcpPackLen:%{public}d fd:%{public}d failed, sendto error:%{public}d.",
276             optionLen, sendLen, dhcpPackLen, nFd, errno);
277     } else {
278         DHCP_LOGI("SendToDhcpPacket optionLen:%{public}d sendLen:%{public}d, "
279             "dhcpPackLen:%{public}d fd:%{public}d, index:%{public}d, bytes:%{public}d.",
280             optionLen, sendLen, dhcpPackLen, nFd, destIndex, static_cast<int>(nBytes));
281     }
282     close(nFd);
283     return (nBytes <= 0) ? SOCKET_OPT_FAILED : SOCKET_OPT_SUCCESS;
284 }
285 
SendDhcpPacket(struct DhcpPacket * sendPacket,uint32_t srcIp,uint32_t destIp)286 int SendDhcpPacket(struct DhcpPacket *sendPacket, uint32_t srcIp, uint32_t destIp)
287 {
288     int nFd = -1;
289     if ((CreateKernelSocket(&nFd) != SOCKET_OPT_SUCCESS) ||
290         (BindKernelSocket(nFd, NULL, srcIp, BOOTP_CLIENT, false) != SOCKET_OPT_SUCCESS)) {
291         DHCP_LOGE("SendDhcpPacket fd:%{public}d failed!", nFd);
292         return SOCKET_OPT_FAILED;
293     }
294 
295     struct sockaddr_in kernelAddr;
296     if (memset_s(&kernelAddr, sizeof(kernelAddr), 0, sizeof(kernelAddr)) != EOK) {
297         close(nFd);
298         return SOCKET_OPT_FAILED;
299     }
300     kernelAddr.sin_addr.s_addr = destIp;
301     kernelAddr.sin_port = htons(BOOTP_SERVER);
302     kernelAddr.sin_family = AF_INET;
303     int nRet = connect(nFd, (struct sockaddr *)&kernelAddr, sizeof(kernelAddr));
304     if (nRet == -1) {
305         DHCP_LOGE("SendDhcpPacket nFd:%{public}d failed, connect error:%{public}d.", nFd, errno);
306         close(nFd);
307         return SOCKET_OPT_FAILED;
308     }
309 
310     ssize_t nBytes = write(nFd, sendPacket, sizeof(struct DhcpPacket));
311     if (nBytes <= 0) {
312         DHCP_LOGE("SendDhcpPacket fd:%{public}d failed, write error:%{public}d.", nFd, errno);
313     } else {
314         DHCP_LOGI("SendDhcpPacket fd:%{public}d, bytes:%{public}d.", nFd, static_cast<int>(nBytes));
315     }
316     close(nFd);
317     return (nBytes <= 0) ? SOCKET_OPT_FAILED : SOCKET_OPT_SUCCESS;
318 }
319 
CheckReadBytes(const int count,const int totLen)320 int CheckReadBytes(const int count, const int totLen)
321 {
322     if (count < 0) {
323         DHCP_LOGE("CheckReadBytes() couldn't read on raw listening socket, count:%{public}d, error:%{public}d!",
324             count, errno);
325         return SOCKET_OPT_ERROR;
326     }
327 
328     int nCommonSize = sizeof(struct iphdr) + sizeof(struct udphdr);
329     if (count < nCommonSize) {
330         DHCP_LOGE("CheckReadBytes() read size:%{public}d less than common size:%{public}d!", count, nCommonSize);
331         return SOCKET_OPT_FAILED;
332     }
333 
334     if (count < totLen) {
335         DHCP_LOGE("CheckReadBytes() count:%{public}d less than totLen:%{public}d, packet is Truncated!", count, totLen);
336         return SOCKET_OPT_FAILED;
337     }
338 
339     DHCP_LOGI("CheckReadBytes() count:%{public}d, tot:%{public}d, common:%{public}d.", count, totLen, nCommonSize);
340     return SOCKET_OPT_SUCCESS;
341 }
342 
CheckUdpPacket(struct UdpDhcpPacket * pPacket,const int totLen)343 int CheckUdpPacket(struct UdpDhcpPacket *pPacket, const int totLen)
344 {
345     if (pPacket == NULL) {
346         DHCP_LOGE("CheckUdpPacket() failed, pPacket == NULL!");
347         return SOCKET_OPT_FAILED;
348     }
349 
350     if (totLen > (int)sizeof(struct UdpDhcpPacket)) {
351         DHCP_LOGE("CheckUdpPacket() totLen:%{public}d more than %{public}d!", totLen,
352             (int)sizeof(struct UdpDhcpPacket));
353         return SOCKET_OPT_FAILED;
354     }
355 
356     if ((pPacket->ip.protocol != IPPROTO_UDP) || (pPacket->ip.version != IPVERSION)) {
357         DHCP_LOGE("CheckUdpPacket() failed, pPacket->ip.protocol:%{public}d or version:%{public}u error!",
358             pPacket->ip.protocol, pPacket->ip.version);
359         return SOCKET_OPT_FAILED;
360     }
361 
362     uint32_t uIhl = (uint32_t)(sizeof(pPacket->ip) >> DHCP_UINT16_BYTES);
363     if (pPacket->ip.ihl != uIhl) {
364         DHCP_LOGE("CheckUdpPacket() failed, pPacket->ip.ihl:%{public}u error, uIhl:%{public}u!", pPacket->ip.ihl, uIhl);
365         return SOCKET_OPT_FAILED;
366     }
367 
368     if (pPacket->udp.dest != htons(BOOTP_CLIENT)) {
369         DHCP_LOGE("CheckUdpPacket() failed, pPacket->udp.dest:%{public}d error, htons:%{public}d!",
370             pPacket->udp.dest, htons(BOOTP_CLIENT));
371         return SOCKET_OPT_FAILED;
372     }
373 
374     uint16_t uLen = (uint16_t)(totLen - (int)sizeof(pPacket->ip));
375     if (ntohs(pPacket->udp.len) != uLen) {
376         DHCP_LOGE("CheckUdpPacket() failed, pPacket->udp.len:%{public}d error, uLen:%{public}d!",
377             pPacket->udp.len, uLen);
378         return SOCKET_OPT_FAILED;
379     }
380     DHCP_LOGI("CheckUdpPacket() success, totLen:%{public}d.", totLen);
381     return SOCKET_OPT_SUCCESS;
382 }
383 
CheckPacketIpSum(struct UdpDhcpPacket * pPacket,const int bytes)384 int CheckPacketIpSum(struct UdpDhcpPacket *pPacket, const int bytes)
385 {
386     if (pPacket == NULL) {
387         return SOCKET_OPT_FAILED;
388     }
389 
390     if (CheckUdpPacket(pPacket, bytes) != SOCKET_OPT_SUCCESS) {
391         return SOCKET_OPT_FAILED;
392     }
393 
394     /* Check packet ip sum. */
395     uint16_t uCheck = pPacket->ip.check;
396     pPacket->ip.check = 0;
397     uint16_t uCheckSum = GetCheckSum((uint16_t *)&(pPacket->ip), sizeof(pPacket->ip));
398     if (uCheck != uCheckSum) {
399         DHCP_LOGE("CheckPacketIpSum() failed, ip.check:%{public}d, uCheckSum:%{public}d!", uCheck, uCheckSum);
400         return SOCKET_OPT_ERROR;
401     }
402     DHCP_LOGI("CheckPacketIpSum() success, bytes:%{public}d.", bytes);
403     return SOCKET_OPT_SUCCESS;
404 }
405 
CheckPacketUdpSum(struct UdpDhcpPacket * pPacket,const int bytes)406 int CheckPacketUdpSum(struct UdpDhcpPacket *pPacket, const int bytes)
407 {
408     if (pPacket == NULL) {
409         DHCP_LOGE("CheckPacketUdpSum() failed, pPacket == NULL!");
410         return SOCKET_OPT_FAILED;
411     }
412 
413     /* Check packet udp sum. */
414     uint16_t uCheck = pPacket->udp.check;
415     pPacket->udp.check = 0;
416     u_int32_t source = pPacket->ip.saddr;
417     u_int32_t dest = pPacket->ip.daddr;
418     if (memset_s(&pPacket->ip, sizeof(pPacket->ip), 0, sizeof(pPacket->ip)) != EOK) {
419         DHCP_LOGE("CheckPacketUdpSum() failed, memset_s ERROR!");
420         return SOCKET_OPT_FAILED;
421     }
422     pPacket->ip.protocol = IPPROTO_UDP;
423     pPacket->ip.saddr = source;
424     pPacket->ip.daddr = dest;
425     pPacket->ip.tot_len = pPacket->udp.len;
426     uint16_t uCheckSum = GetCheckSum((uint16_t *)pPacket, bytes);
427     if (uCheck && (uCheck != uCheckSum)) {
428         DHCP_LOGE("CheckPacketUdpSum() failed, udp.check:%{public}d, uCheckSum:%{public}d!", uCheck, uCheckSum);
429         return SOCKET_OPT_FAILED;
430     }
431     DHCP_LOGI("CheckPacketUdpSum() success, bytes:%{public}d.", bytes);
432     return SOCKET_OPT_SUCCESS;
433 }
434 
GetDhcpRawPacket(struct DhcpPacket * getPacket,int rawFd)435 int GetDhcpRawPacket(struct DhcpPacket *getPacket, int rawFd)
436 {
437     if (getPacket == NULL) {
438         return SOCKET_OPT_FAILED;
439     }
440 
441     /* Get and check udp dhcp packet bytes. */
442     struct UdpDhcpPacket udpPackets;
443     if (memset_s(&udpPackets, sizeof(struct UdpDhcpPacket), 0, sizeof(struct UdpDhcpPacket)) != EOK) {
444         return SOCKET_OPT_FAILED;
445     }
446     int nBytes = read(rawFd, &udpPackets, sizeof(struct UdpDhcpPacket));
447     int nRet = CheckReadBytes(nBytes, (int)ntohs(udpPackets.ip.tot_len));
448     if (nRet != SOCKET_OPT_SUCCESS) {
449         return nRet;
450     }
451 
452     /* Check udp dhcp packet sum. */
453     nBytes = (int)ntohs(udpPackets.ip.tot_len);
454     nRet = CheckPacketIpSum(&udpPackets, nBytes);
455     if (nRet != SOCKET_OPT_SUCCESS) {
456         return nRet;
457     }
458     nRet = CheckPacketUdpSum(&udpPackets, nBytes);
459     if (nRet != SOCKET_OPT_SUCCESS) {
460         return nRet;
461     }
462 
463     int nDhcpPacket = nBytes - (int)(sizeof(udpPackets.ip) + sizeof(udpPackets.udp));
464     if (memcpy_s(getPacket, sizeof(struct DhcpPacket), &(udpPackets.data), nDhcpPacket) != EOK) {
465         DHCP_LOGE("GetDhcpRawPacket() memcpy_s packet.data failed!");
466         return SOCKET_OPT_FAILED;
467     }
468     if (ntohl(getPacket->cookie) != MAGIC_COOKIE) {
469         DHCP_LOGE("GetDhcpRawPacket() cook:%{public}x error, COOK:%{public}x!", ntohl(getPacket->cookie), MAGIC_COOKIE);
470         return SOCKET_OPT_FAILED;
471     }
472     return nDhcpPacket;
473 }
474 
GetDhcpKernelPacket(struct DhcpPacket * getPacket,int sockFd)475 int GetDhcpKernelPacket(struct DhcpPacket *getPacket, int sockFd)
476 {
477     if (getPacket == NULL) {
478         return SOCKET_OPT_FAILED;
479     }
480 
481     int nBytes = -1;
482     if ((nBytes = read(sockFd, getPacket, sizeof(struct DhcpPacket))) == -1) {
483         DHCP_LOGE("GetDhcpKernelPacket() couldn't read on kernel listening socket, error:%{public}d!", errno);
484         return SOCKET_OPT_ERROR;
485     }
486 
487     if (ntohl(getPacket->cookie) != MAGIC_COOKIE) {
488         DHCP_LOGE("GetDhcpKernelPacket() cook:%{public}x error, COOK:%{public}x!", ntohl(getPacket->cookie),
489             MAGIC_COOKIE);
490         return SOCKET_OPT_FAILED;
491     }
492     return nBytes;
493 }
494