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