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