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