net/: Now handles reception of IPv4 packets with larger IPv4 headers containing options.
This commit is contained in:
parent
9bdde04636
commit
a52ceac13e
@ -118,40 +118,6 @@ struct icmp_hdr_s
|
|||||||
uint16_t seqno; /* " " "" " " " " " " " " */
|
uint16_t seqno; /* " " "" " " " " " " " " */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The ICMP and IPv4 headers */
|
|
||||||
|
|
||||||
struct icmp_iphdr_s
|
|
||||||
{
|
|
||||||
/* IPv4 IP header */
|
|
||||||
|
|
||||||
uint8_t vhl; /* 8-bit Version (4) and header length (5 or 6) */
|
|
||||||
uint8_t tos; /* 8-bit Type of service (e.g., 6=TCP) */
|
|
||||||
uint8_t len[2]; /* 16-bit Total length */
|
|
||||||
uint8_t ipid[2]; /* 16-bit Identification */
|
|
||||||
uint8_t ipoffset[2]; /* 16-bit IP flags + fragment offset */
|
|
||||||
uint8_t ttl; /* 8-bit Time to Live */
|
|
||||||
uint8_t proto; /* 8-bit Protocol */
|
|
||||||
uint16_t ipchksum; /* 16-bit Header checksum */
|
|
||||||
uint16_t srcipaddr[2]; /* 32-bit Source IP address */
|
|
||||||
uint16_t destipaddr[2]; /* 32-bit Destination IP address */
|
|
||||||
|
|
||||||
/* ICMP header */
|
|
||||||
|
|
||||||
uint8_t type; /* Defines the format of the ICMP message */
|
|
||||||
uint8_t icode; /* Further qualifies the ICMP messsage */
|
|
||||||
uint16_t icmpchksum; /* Checksum of ICMP header and data */
|
|
||||||
|
|
||||||
/* All ICMP packets have an 8-byte header and variable-sized data section.
|
|
||||||
* The first 4 bytes of the header have fixed format, while the last 4 bytes
|
|
||||||
* depend on the type/code of that ICMP packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ICMP_ECHO_REQUEST and ICMP_ECHO_REPLY data */
|
|
||||||
|
|
||||||
uint16_t id; /* Used to match requests with replies */
|
|
||||||
uint16_t seqno; /* " " "" " " " " " " " " */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* The structure holding the ICMP statistics that are gathered if
|
/* The structure holding the ICMP statistics that are gathered if
|
||||||
* CONFIG_NET_STATISTICS is defined.
|
* CONFIG_NET_STATISTICS is defined.
|
||||||
*/
|
*/
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* The definitions in this header file are intended only for internal use
|
* The definitions in this header file are intended only for internal use
|
||||||
* by the NuttX network stack.
|
* by the NuttX network stack.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, 2012, 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2010, 2012, 2014, 2019 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* The NuttX implementation of IGMP was inspired by the IGMP add-on for the
|
* The NuttX implementation of IGMP was inspired by the IGMP add-on for the
|
||||||
@ -72,14 +72,9 @@
|
|||||||
#define IGMPv3_MEMBERSHIP_REPORT 0x22 /* IGMP Ver. 3 Membership Report */
|
#define IGMPv3_MEMBERSHIP_REPORT 0x22 /* IGMP Ver. 3 Membership Report */
|
||||||
#define IGMP_LEAVE_GROUP 0x17 /* Leave Group */
|
#define IGMP_LEAVE_GROUP 0x17 /* Leave Group */
|
||||||
|
|
||||||
/* Header sizes:
|
/* Size of IGMP header in bytes */
|
||||||
*
|
|
||||||
* IGMP_HDRLEN - Size of IGMP header in bytes
|
|
||||||
* IPIGMP_HDRLEN - Size of IP + Size of IGMP header + Size of router alert
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define IGMP_HDRLEN 8
|
#define IGMP_HDRLEN 8
|
||||||
#define IPIGMP_HDRLEN (IGMP_HDRLEN + IPv4_HDRLEN + 4)
|
|
||||||
|
|
||||||
/* Time-to-Live must be one */
|
/* Time-to-Live must be one */
|
||||||
|
|
||||||
@ -89,13 +84,7 @@
|
|||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* IGMPv2 packet structure as defined by RFC 2236.
|
/* Convenience [re-]definition of the IPv4 header with the router alert */
|
||||||
*
|
|
||||||
* The Max Response Time (maxresp) specifies the time limit for the
|
|
||||||
* corresponding report. The field has a resolution of 100 miliseconds, the
|
|
||||||
* value is taken directly. This field is meaningful only in Membership Query
|
|
||||||
* (0x11); in other messages it is set to 0 and ignored by the receiver.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct igmp_iphdr_s
|
struct igmp_iphdr_s
|
||||||
{
|
{
|
||||||
@ -115,7 +104,18 @@ struct igmp_iphdr_s
|
|||||||
/* Router Alert IP header option */
|
/* Router Alert IP header option */
|
||||||
|
|
||||||
uint16_t ra[2]; /* RFC 2113 */
|
uint16_t ra[2]; /* RFC 2113 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* IGMPv2 packet structure as defined by RFC 2236.
|
||||||
|
*
|
||||||
|
* The Max Response Time (maxresp) specifies the time limit for the
|
||||||
|
* corresponding report. The field has a resolution of 100 miliseconds, the
|
||||||
|
* value is taken directly. This field is meaningful only in Membership Query
|
||||||
|
* (0x11); in other messages it is set to 0 and ignored by the receiver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct igmp_hdr_s
|
||||||
|
{
|
||||||
/* IGMPv2 header:
|
/* IGMPv2 header:
|
||||||
*
|
*
|
||||||
* 0 1 2 3
|
* 0 1 2 3
|
||||||
|
@ -86,6 +86,7 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_NET_IPv4
|
#ifdef CONFIG_NET_IPv4
|
||||||
# define IPv4_HDRLEN 20 /* Size of IPv4 header (without options) */
|
# define IPv4_HDRLEN 20 /* Size of IPv4 header (without options) */
|
||||||
|
# define IPv4_HLMASK 0x0f /* Isolates headler length in VHL field */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NET_IPv6
|
#ifdef CONFIG_NET_IPv6
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* net/devif/ipv4_input.c
|
* net/devif/ipv4_input.c
|
||||||
* Device driver IPv4 packet receipt interface
|
* Device driver IPv4 packet receipt interface
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2013-2015, 2018 Gregory Nutt. All rights
|
* Copyright (C) 2007-2009, 2013-2015, 2018-2019 Gregory Nutt. All rights
|
||||||
* reserved.
|
* reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
@ -332,8 +332,8 @@ int ipv4_input(FAR struct net_driver_s *dev)
|
|||||||
{
|
{
|
||||||
FAR struct ipv4_hdr_s *ipv4 = BUF;
|
FAR struct ipv4_hdr_s *ipv4 = BUF;
|
||||||
in_addr_t destipaddr;
|
in_addr_t destipaddr;
|
||||||
uint16_t hdrlen;
|
uint16_t llhdrlen;
|
||||||
uint16_t iplen;
|
uint16_t totlen;
|
||||||
|
|
||||||
/* This is where the input processing starts. */
|
/* This is where the input processing starts. */
|
||||||
|
|
||||||
@ -349,7 +349,8 @@ int ipv4_input(FAR struct net_driver_s *dev)
|
|||||||
* 32-bit words in the HL nibble of the VHL.
|
* 32-bit words in the HL nibble of the VHL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ipv4->vhl != 0x45)
|
if ((ipv4->vhl & IP_VERSION_MASK) != 0x40 ||
|
||||||
|
(ipv4->vhl & IPv4_HLMASK) < 5)
|
||||||
{
|
{
|
||||||
/* IP version and header length. */
|
/* IP version and header length. */
|
||||||
|
|
||||||
@ -364,26 +365,26 @@ int ipv4_input(FAR struct net_driver_s *dev)
|
|||||||
|
|
||||||
/* Get the size of the packet minus the size of link layer header */
|
/* Get the size of the packet minus the size of link layer header */
|
||||||
|
|
||||||
hdrlen = NET_LL_HDRLEN(dev);
|
llhdrlen = NET_LL_HDRLEN(dev);
|
||||||
if ((hdrlen + IPv4_HDRLEN) > dev->d_len)
|
if ((llhdrlen + IPv4_HDRLEN) > dev->d_len)
|
||||||
{
|
{
|
||||||
nwarn("WARNING: Packet shorter than IPv4 header\n");
|
nwarn("WARNING: Packet shorter than IPv4 header\n");
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->d_len -= hdrlen;
|
dev->d_len -= llhdrlen;
|
||||||
|
|
||||||
/* Check the size of the packet. If the size reported to us in d_len is
|
/* Check the size of the packet. If the size reported to us in d_len is
|
||||||
* smaller the size reported in the IP header, we assume that the packet
|
* smaller the size reported in the IP header, we assume that the packet
|
||||||
* has been corrupted in transit. If the size of d_len is larger than the
|
* has been corrupted in transit. If the size of d_len is larger than the
|
||||||
* size reported in the IP packet header, the packet has been padded and
|
* size reported in the IP packet header, the packet has been padded and
|
||||||
* we set d_len to the correct value.
|
* we set d_len to the correct value.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
iplen = (ipv4->len[0] << 8) + ipv4->len[1];
|
totlen = (ipv4->len[0] << 8) + ipv4->len[1];
|
||||||
if (iplen <= dev->d_len)
|
if (totlen <= dev->d_len)
|
||||||
{
|
{
|
||||||
dev->d_len = iplen;
|
dev->d_len = totlen;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -67,10 +67,9 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
#define IPICMPBUF ((FAR struct icmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define ICMPBUF(hl) ((FAR struct icmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + (hl)])
|
||||||
#define ICMPBUF ((FAR struct icmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + IPv4_HDRLEN])
|
#define ICMPSIZE(hl) ((dev)->d_len - (hl))
|
||||||
#define ICMPSIZE ((dev)->d_len - IPv4_HDRLEN)
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -104,6 +103,7 @@ static uint16_t icmp_datahandler(FAR struct net_driver_s *dev,
|
|||||||
FAR struct iob_s *iob;
|
FAR struct iob_s *iob;
|
||||||
uint16_t offset;
|
uint16_t offset;
|
||||||
uint16_t buflen;
|
uint16_t buflen;
|
||||||
|
uint16_t iphdrlen;
|
||||||
uint8_t addrsize;
|
uint8_t addrsize;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -164,11 +164,15 @@ static uint16_t icmp_datahandler(FAR struct net_driver_s *dev,
|
|||||||
|
|
||||||
offset += sizeof(struct sockaddr_in);
|
offset += sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
/* Copy the new ICMP reply into the I/O buffer chain (without waiting) */
|
/* Copy the new ICMP reply into the I/O buffer chain (without waiting) */
|
||||||
|
|
||||||
buflen = ICMPSIZE;
|
buflen = ICMPSIZE(iphdrlen);
|
||||||
ret = iob_trycopyin(iob, (FAR uint8_t *)ICMPBUF, buflen, offset, true,
|
ret = iob_trycopyin(iob, (FAR uint8_t *)ICMPBUF(iphdrlen), buflen, offset,
|
||||||
IOBUSER_NET_SOCK_ICMP);
|
true, IOBUSER_NET_SOCK_ICMP);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
/* On a failure, iob_copyin return a negated error value but does
|
/* On a failure, iob_copyin return a negated error value but does
|
||||||
@ -227,57 +231,71 @@ drop:
|
|||||||
|
|
||||||
void icmp_input(FAR struct net_driver_s *dev)
|
void icmp_input(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
FAR struct icmp_iphdr_s *ipicmp = IPICMPBUF;
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
|
FAR struct icmp_hdr_s *icmp;
|
||||||
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
g_netstats.icmp.recv++;
|
g_netstats.icmp.recv++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
|
/* The ICMP header immediately follows the IP header */
|
||||||
|
|
||||||
|
icmp = ICMPBUF(iphdrlen);
|
||||||
|
|
||||||
/* ICMP echo (i.e., ping) processing. This is simple, we only change the
|
/* ICMP echo (i.e., ping) processing. This is simple, we only change the
|
||||||
* ICMP type from ECHO to ECHO_REPLY and adjust the ICMP checksum before
|
* ICMP type from ECHO to ECHO_REPLY and adjust the ICMP checksum before
|
||||||
* we return the packet.
|
* we return the packet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ipicmp->type == ICMP_ECHO_REQUEST)
|
if (icmp->type == ICMP_ECHO_REQUEST)
|
||||||
{
|
{
|
||||||
/* Change the ICMP type */
|
/* Change the ICMP type */
|
||||||
|
|
||||||
ipicmp->type = ICMP_ECHO_REPLY;
|
icmp->type = ICMP_ECHO_REPLY;
|
||||||
|
|
||||||
/* Swap IP addresses. */
|
/* Swap IP addresses. */
|
||||||
|
|
||||||
net_ipv4addr_hdrcopy(ipicmp->destipaddr, ipicmp->srcipaddr);
|
net_ipv4addr_hdrcopy(ipv4->destipaddr, ipv4->srcipaddr);
|
||||||
net_ipv4addr_hdrcopy(ipicmp->srcipaddr, &dev->d_ipaddr);
|
net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr);
|
||||||
|
|
||||||
/* Recalculate the ICMP checksum */
|
/* Recalculate the ICMP checksum */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
/* The slow way... sum over the ICMP message */
|
/* The slow way... sum over the ICMP message */
|
||||||
|
|
||||||
ipicmp->icmpchksum = 0;
|
icmp->icmpchksum = 0;
|
||||||
ipicmp->icmpchksum = ~icmp_chksum(dev, (((uint16_t)ipicmp->len[0] << 8) |
|
icmp->icmpchksum = ~icmp_chksum(dev, (((uint16_t)ipv4->len[0] << 8) |
|
||||||
(uint16_t)ipicmp->len[1]) - IPv4_HDRLEN);
|
(uint16_t)ipv4->len[1]) - iphdrlen);
|
||||||
if (ipicmp->icmpchksum == 0)
|
if (icmp->icmpchksum == 0)
|
||||||
{
|
{
|
||||||
ipicmp->icmpchksum = 0xffff;
|
icmp->icmpchksum = 0xffff;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* The quick way -- Since only the type has changed, just adjust the
|
/* The quick way -- Since only the type has changed, just adjust the
|
||||||
* checksum for the change of type
|
* checksum for the change of type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ipicmp->icmpchksum >= HTONS(0xffff - (ICMP_ECHO_REQUEST << 8)))
|
if (icmp->icmpchksum >= HTONS(0xffff - (ICMP_ECHO_REQUEST << 8)))
|
||||||
{
|
{
|
||||||
ipicmp->icmpchksum += HTONS(ICMP_ECHO_REQUEST << 8) + 1;
|
icmp->icmpchksum += HTONS(ICMP_ECHO_REQUEST << 8) + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ipicmp->icmpchksum += HTONS(ICMP_ECHO_REQUEST << 8);
|
icmp->icmpchksum += HTONS(ICMP_ECHO_REQUEST << 8);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ninfo("Outgoing ICMP packet length: %d (%d)\n",
|
ninfo("Outgoing ICMP packet length: %d (%d)\n",
|
||||||
dev->d_len, (ipicmp->len[0] << 8) | ipicmp->len[1]);
|
dev->d_len, (ipv4->len[0] << 8) | ipv4->len[1]);
|
||||||
|
|
||||||
#ifdef CONFIG_NET_STATISTICS
|
#ifdef CONFIG_NET_STATISTICS
|
||||||
g_netstats.icmp.sent++;
|
g_netstats.icmp.sent++;
|
||||||
@ -290,7 +308,7 @@ void icmp_input(FAR struct net_driver_s *dev)
|
|||||||
* a thread waiting to received the echo response.
|
* a thread waiting to received the echo response.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (ipicmp->type == ICMP_ECHO_REPLY)
|
else if (icmp->type == ICMP_ECHO_REPLY)
|
||||||
{
|
{
|
||||||
FAR struct icmp_conn_s *conn;
|
FAR struct icmp_conn_s *conn;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
@ -302,7 +320,7 @@ void icmp_input(FAR struct net_driver_s *dev)
|
|||||||
|
|
||||||
/* Is there any connection that might expect this reply? */
|
/* Is there any connection that might expect this reply? */
|
||||||
|
|
||||||
conn = icmp_findconn(dev, ipicmp->id);
|
conn = icmp_findconn(dev, icmp->id);
|
||||||
if (conn == NULL)
|
if (conn == NULL)
|
||||||
{
|
{
|
||||||
/* No.. drop the packet */
|
/* No.. drop the packet */
|
||||||
@ -334,7 +352,7 @@ void icmp_input(FAR struct net_driver_s *dev)
|
|||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nwarn("WARNING: Unknown ICMP cmd: %d\n", ipicmp->type);
|
nwarn("WARNING: Unknown ICMP cmd: %d\n", icmp->type);
|
||||||
goto typeerr;
|
goto typeerr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,8 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define IGMPBUF ((struct igmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv4BUF ((FAR struct igmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
#define IGMPBUF(hl) ((FAR struct igmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + (hl)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -112,16 +113,27 @@
|
|||||||
|
|
||||||
void igmp_input(struct net_driver_s *dev)
|
void igmp_input(struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
|
FAR struct igmp_iphdr_s *ipv4 = IPv4BUF;
|
||||||
|
FAR struct igmp_hdr_s *igmp;
|
||||||
FAR struct igmp_group_s *group;
|
FAR struct igmp_group_s *group;
|
||||||
in_addr_t destipaddr;
|
in_addr_t destipaddr;
|
||||||
in_addr_t grpaddr;
|
in_addr_t grpaddr;
|
||||||
|
uint16_t iphdrlen;
|
||||||
unsigned int ticks;
|
unsigned int ticks;
|
||||||
|
|
||||||
ninfo("IGMP message: %04x%04x\n", IGMPBUF->destipaddr[1], IGMPBUF->destipaddr[0]);
|
ninfo("IGMP message: %04x%04x\n", ipv4->destipaddr[1], ipv4->destipaddr[0]);
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
|
/* The IGMP header immediately follows the IP header */
|
||||||
|
|
||||||
|
igmp = IGMPBUF(iphdrlen);
|
||||||
|
|
||||||
/* Verify the message length */
|
/* Verify the message length */
|
||||||
|
|
||||||
if (dev->d_len < NET_LL_HDRLEN(dev) + IPIGMP_HDRLEN)
|
if (dev->d_len < NET_LL_HDRLEN(dev) + (iphdrlen + IGMP_HDRLEN))
|
||||||
{
|
{
|
||||||
IGMP_STATINCR(g_netstats.igmp.length_errors);
|
IGMP_STATINCR(g_netstats.igmp.length_errors);
|
||||||
nwarn("WARNING: Length error\n");
|
nwarn("WARNING: Length error\n");
|
||||||
@ -130,7 +142,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
/* Calculate and check the IGMP checksum */
|
/* Calculate and check the IGMP checksum */
|
||||||
|
|
||||||
if (net_chksum((FAR uint16_t *)&IGMPBUF->type, IGMP_HDRLEN) != 0)
|
if (net_chksum((FAR uint16_t *)igmp, IGMP_HDRLEN) != 0)
|
||||||
{
|
{
|
||||||
IGMP_STATINCR(g_netstats.igmp.chksum_errors);
|
IGMP_STATINCR(g_netstats.igmp.chksum_errors);
|
||||||
nwarn("WARNING: Checksum error\n");
|
nwarn("WARNING: Checksum error\n");
|
||||||
@ -139,7 +151,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
/* Find the group (or create a new one) using the incoming IP address. */
|
/* Find the group (or create a new one) using the incoming IP address. */
|
||||||
|
|
||||||
destipaddr = net_ip4addr_conv32(IGMPBUF->destipaddr);
|
destipaddr = net_ip4addr_conv32(ipv4->destipaddr);
|
||||||
|
|
||||||
group = igmp_grpallocfind(dev, &destipaddr);
|
group = igmp_grpallocfind(dev, &destipaddr);
|
||||||
if (group == NULL)
|
if (group == NULL)
|
||||||
@ -150,7 +162,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
/* Now handle the message based on the IGMP message type */
|
/* Now handle the message based on the IGMP message type */
|
||||||
|
|
||||||
switch (IGMPBUF->type)
|
switch (igmp->type)
|
||||||
{
|
{
|
||||||
case IGMP_MEMBERSHIP_QUERY:
|
case IGMP_MEMBERSHIP_QUERY:
|
||||||
/* RFC 2236, 2.2. ax Response Time
|
/* RFC 2236, 2.2. ax Response Time
|
||||||
@ -181,17 +193,17 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
* Query."
|
* Query."
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (IGMPBUF->grpaddr == 0)
|
if (igmp->grpaddr == 0)
|
||||||
{
|
{
|
||||||
FAR struct igmp_group_s *member;
|
FAR struct igmp_group_s *member;
|
||||||
|
|
||||||
/* This is the general query */
|
/* This is the general query */
|
||||||
|
|
||||||
ninfo("General multicast query\n");
|
ninfo("General multicast query\n");
|
||||||
if (IGMPBUF->maxresp == 0)
|
if (igmp->maxresp == 0)
|
||||||
{
|
{
|
||||||
IGMP_STATINCR(g_netstats.igmp.v1_received);
|
IGMP_STATINCR(g_netstats.igmp.v1_received);
|
||||||
IGMPBUF->maxresp = 10;
|
igmp->maxresp = 10;
|
||||||
|
|
||||||
nwarn("WARNING: V1 not implemented\n");
|
nwarn("WARNING: V1 not implemented\n");
|
||||||
}
|
}
|
||||||
@ -206,7 +218,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
if (!net_ipv4addr_cmp(member->grpaddr, g_ipv4_allsystems))
|
if (!net_ipv4addr_cmp(member->grpaddr, g_ipv4_allsystems))
|
||||||
{
|
{
|
||||||
ticks = net_dsec2tick((int)IGMPBUF->maxresp);
|
ticks = net_dsec2tick((int)igmp->maxresp);
|
||||||
if (IS_IDLEMEMBER(member->flags) ||
|
if (IS_IDLEMEMBER(member->flags) ||
|
||||||
igmp_cmptimer(member, ticks))
|
igmp_cmptimer(member, ticks))
|
||||||
{
|
{
|
||||||
@ -216,7 +228,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* if (IGMPBUF->grpaddr != 0) */
|
else /* if (igmp->grpaddr != 0) */
|
||||||
{
|
{
|
||||||
ninfo("Group-specific multicast query\n");
|
ninfo("Group-specific multicast query\n");
|
||||||
|
|
||||||
@ -226,12 +238,12 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
IGMP_STATINCR(g_netstats.igmp.ucast_query);
|
IGMP_STATINCR(g_netstats.igmp.ucast_query);
|
||||||
|
|
||||||
grpaddr = net_ip4addr_conv32(IGMPBUF->grpaddr);
|
grpaddr = net_ip4addr_conv32(igmp->grpaddr);
|
||||||
group = igmp_grpallocfind(dev, &grpaddr);
|
group = igmp_grpallocfind(dev, &grpaddr);
|
||||||
|
|
||||||
if (group != NULL)
|
if (group != NULL)
|
||||||
{
|
{
|
||||||
ticks = net_dsec2tick((int)IGMPBUF->maxresp);
|
ticks = net_dsec2tick((int)igmp->maxresp);
|
||||||
|
|
||||||
if (IS_IDLEMEMBER(group->flags) || igmp_cmptimer(group, ticks))
|
if (IS_IDLEMEMBER(group->flags) || igmp_cmptimer(group, ticks))
|
||||||
{
|
{
|
||||||
@ -251,7 +263,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
ninfo("Query to a specific group with the group address as destination\n");
|
ninfo("Query to a specific group with the group address as destination\n");
|
||||||
|
|
||||||
ticks = net_dsec2tick((int)IGMPBUF->maxresp);
|
ticks = net_dsec2tick((int)igmp->maxresp);
|
||||||
if (IS_IDLEMEMBER(group->flags) || igmp_cmptimer(group, ticks))
|
if (IS_IDLEMEMBER(group->flags) || igmp_cmptimer(group, ticks))
|
||||||
{
|
{
|
||||||
igmp_startticks(group, ticks);
|
igmp_startticks(group, ticks);
|
||||||
@ -278,7 +290,7 @@ void igmp_input(struct net_driver_s *dev)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
nwarn("WARNING: Unexpected msg %02x\n", IGMPBUF->type);
|
nwarn("WARNING: Unexpected msg %02x\n", igmp->type);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/igmp/igmp_poll.c
|
* net/igmp/igmp_poll.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010, 2018 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2010, 2018-2019 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* The NuttX implementation of IGMP was inspired by the IGMP add-on for the
|
* The NuttX implementation of IGMP was inspired by the IGMP add-on for the
|
||||||
@ -57,6 +57,16 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_NET_IGMP
|
#ifdef CONFIG_NET_IGMP
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Buffer layout */
|
||||||
|
|
||||||
|
#define RASIZE (4)
|
||||||
|
#define IPv4BUF ((FAR struct igmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
#define IGMPBUF(hl) ((FAR struct igmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + (hl)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -141,10 +151,13 @@ static inline void igmp_sched_send(FAR struct net_driver_s *dev,
|
|||||||
void igmp_poll(FAR struct net_driver_s *dev)
|
void igmp_poll(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
FAR struct igmp_group_s *group;
|
FAR struct igmp_group_s *group;
|
||||||
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
/* Setup the poll operation */
|
/* Setup the poll operation */
|
||||||
|
|
||||||
dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev) + IPIGMP_HDRLEN];
|
iphdrlen = IPv4_HDRLEN + RASIZE;
|
||||||
|
|
||||||
|
dev->d_appdata = &dev->d_buf[NET_LL_HDRLEN(dev) + iphdrlen + IGMP_HDRLEN];
|
||||||
dev->d_len = 0;
|
dev->d_len = 0;
|
||||||
dev->d_sndlen = 0;
|
dev->d_sndlen = 0;
|
||||||
|
|
||||||
|
@ -77,7 +77,8 @@
|
|||||||
/* Buffer layout */
|
/* Buffer layout */
|
||||||
|
|
||||||
#define RASIZE (4)
|
#define RASIZE (4)
|
||||||
#define IGMPBUF ((struct igmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv4BUF ((FAR struct igmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
#define IGMPBUF(hl) ((FAR struct igmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + (hl)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@ -118,62 +119,71 @@ static uint16_t igmp_chksum(FAR uint8_t *buffer, int buflen)
|
|||||||
void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
|
void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group,
|
||||||
FAR in_addr_t *destipaddr, uint8_t msgid)
|
FAR in_addr_t *destipaddr, uint8_t msgid)
|
||||||
{
|
{
|
||||||
|
FAR struct igmp_iphdr_s *ipv4 = IPv4BUF;
|
||||||
|
FAR struct igmp_hdr_s *igmp;
|
||||||
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr);
|
ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr);
|
||||||
|
|
||||||
|
/* The IGMP header immediately follows the IP header */
|
||||||
|
|
||||||
|
iphdrlen = IPv4_HDRLEN + RASIZE;
|
||||||
|
igmp = IGMPBUF(iphdrlen);
|
||||||
|
|
||||||
/* The total length to send is the size of the IP and IGMP headers and 4
|
/* The total length to send is the size of the IP and IGMP headers and 4
|
||||||
* bytes for the ROUTER ALERT (and, eventually, the Ethernet header)
|
* bytes for the ROUTER ALERT (and, eventually, the Ethernet header)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dev->d_len = IPIGMP_HDRLEN;
|
dev->d_len = iphdrlen + IGMP_HDRLEN;
|
||||||
|
|
||||||
/* The total size of the data is the size of the IGMP header */
|
/* The total size of the data is the size of the IGMP header */
|
||||||
|
|
||||||
dev->d_sndlen = IGMP_HDRLEN;
|
dev->d_sndlen = IGMP_HDRLEN;
|
||||||
|
|
||||||
/* Add the router alert option (RFC 2113) */
|
/* Add the router alert option to the IPv4 header (RFC 2113) */
|
||||||
|
|
||||||
IGMPBUF->ra[0] = HTONS(IPOPT_RA >> 16);
|
ipv4->ra[0] = HTONS(IPOPT_RA >> 16);
|
||||||
IGMPBUF->ra[1] = HTONS(IPOPT_RA & 0xffff);
|
ipv4->ra[1] = HTONS(IPOPT_RA & 0xffff);
|
||||||
|
|
||||||
/* Initialize the IPv4 header */
|
/* Initialize the IPv4 header */
|
||||||
|
|
||||||
IGMPBUF->vhl = 0x46; /* 4->IP; 6->24 bytes */
|
ipv4->vhl = 0x46; /* 4->IP; 6->24 bytes */
|
||||||
IGMPBUF->tos = 0;
|
ipv4->tos = 0;
|
||||||
IGMPBUF->len[0] = (dev->d_len >> 8);
|
ipv4->len[0] = (dev->d_len >> 8);
|
||||||
IGMPBUF->len[1] = (dev->d_len & 0xff);
|
ipv4->len[1] = (dev->d_len & 0xff);
|
||||||
++g_ipid;
|
++g_ipid;
|
||||||
IGMPBUF->ipid[0] = g_ipid >> 8;
|
ipv4->ipid[0] = g_ipid >> 8;
|
||||||
IGMPBUF->ipid[1] = g_ipid & 0xff;
|
ipv4->ipid[1] = g_ipid & 0xff;
|
||||||
IGMPBUF->ipoffset[0] = IP_FLAG_DONTFRAG >> 8;
|
ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8;
|
||||||
IGMPBUF->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff;
|
ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff;
|
||||||
IGMPBUF->ttl = IGMP_TTL;
|
ipv4->ttl = IGMP_TTL;
|
||||||
IGMPBUF->proto = IP_PROTO_IGMP;
|
ipv4->proto = IP_PROTO_IGMP;
|
||||||
|
|
||||||
net_ipv4addr_hdrcopy(IGMPBUF->srcipaddr, &dev->d_ipaddr);
|
net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr);
|
||||||
net_ipv4addr_hdrcopy(IGMPBUF->destipaddr, destipaddr);
|
net_ipv4addr_hdrcopy(ipv4->destipaddr, destipaddr);
|
||||||
|
|
||||||
/* Calculate IP checksum. */
|
/* Calculate IP checksum. */
|
||||||
|
|
||||||
IGMPBUF->ipchksum = 0;
|
ipv4->ipchksum = 0;
|
||||||
IGMPBUF->ipchksum = ~igmp_chksum((FAR uint8_t *)IGMPBUF, IPv4_HDRLEN + RASIZE);
|
ipv4->ipchksum = ~igmp_chksum((FAR uint8_t *)igmp, iphdrlen);
|
||||||
|
|
||||||
/* Set up the IGMP message */
|
/* Set up the IGMP message */
|
||||||
|
|
||||||
IGMPBUF->type = msgid;
|
igmp->type = msgid;
|
||||||
IGMPBUF->maxresp = 0;
|
igmp->maxresp = 0;
|
||||||
net_ipv4addr_hdrcopy(IGMPBUF->grpaddr, &group->grpaddr);
|
net_ipv4addr_hdrcopy(igmp->grpaddr, &group->grpaddr);
|
||||||
|
|
||||||
/* Calculate the IGMP checksum. */
|
/* Calculate the IGMP checksum. */
|
||||||
|
|
||||||
IGMPBUF->chksum = 0;
|
igmp->chksum = 0;
|
||||||
IGMPBUF->chksum = ~igmp_chksum(&IGMPBUF->type, IGMP_HDRLEN);
|
igmp->chksum = ~igmp_chksum(&igmp->type, IGMP_HDRLEN);
|
||||||
|
|
||||||
IGMP_STATINCR(g_netstats.igmp.poll_send);
|
IGMP_STATINCR(g_netstats.igmp.poll_send);
|
||||||
IGMP_STATINCR(g_netstats.ipv4.sent);
|
IGMP_STATINCR(g_netstats.ipv4.sent);
|
||||||
|
|
||||||
ninfo("Outgoing IGMP packet length: %d (%d)\n",
|
ninfo("Outgoing IGMP packet length: %d (%d)\n",
|
||||||
dev->d_len, (IGMPBUF->len[0] << 8) | IGMPBUF->len[1]);
|
dev->d_len, (ipv4->len[0] << 8) | ipvr->len[1]);
|
||||||
igmp_dumppkt(RA, IPIGMP_HDRLEN + RASIZE);
|
igmp_dumppkt(RA, iphdrlen + IGMP_HDRLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET_IGMP */
|
#endif /* CONFIG_NET_IGMP */
|
||||||
|
@ -80,7 +80,13 @@
|
|||||||
#ifdef CONFIG_DEBUG_NET_WARN
|
#ifdef CONFIG_DEBUG_NET_WARN
|
||||||
static int ipv4_hdrsize(FAR struct ipv4_hdr_s *ipv4)
|
static int ipv4_hdrsize(FAR struct ipv4_hdr_s *ipv4)
|
||||||
{
|
{
|
||||||
/* Size is determined by the following protocol header, */
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
|
/* Size is also determined by the following protocol header, */
|
||||||
|
|
||||||
switch (ipv4->proto)
|
switch (ipv4->proto)
|
||||||
{
|
{
|
||||||
@ -88,7 +94,7 @@ static int ipv4_hdrsize(FAR struct ipv4_hdr_s *ipv4)
|
|||||||
case IP_PROTO_TCP:
|
case IP_PROTO_TCP:
|
||||||
{
|
{
|
||||||
FAR struct tcp_hdr_s *tcp =
|
FAR struct tcp_hdr_s *tcp =
|
||||||
(FAR struct tcp_hdr_s *)((FAR uint8_t *)ipv4 + IPv4_HDRLEN);
|
(FAR struct tcp_hdr_s *)((FAR uint8_t *)ipv4 + iphdrlen);
|
||||||
unsigned int tcpsize;
|
unsigned int tcpsize;
|
||||||
|
|
||||||
/* The TCP header length is encoded in the top 4 bits of the
|
/* The TCP header length is encoded in the top 4 bits of the
|
||||||
@ -96,20 +102,20 @@ static int ipv4_hdrsize(FAR struct ipv4_hdr_s *ipv4)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
tcpsize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
|
tcpsize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
|
||||||
return IPv4_HDRLEN + tcpsize;
|
return iphdrlen + tcpsize;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NET_UDP
|
#ifdef CONFIG_NET_UDP
|
||||||
case IP_PROTO_UDP:
|
case IP_PROTO_UDP:
|
||||||
return IPv4_HDRLEN + UDP_HDRLEN;
|
return iphdrlen + UDP_HDRLEN;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_NET_ICMP
|
#ifdef CONFIG_NET_ICMP
|
||||||
case IP_PROTO_ICMP:
|
case IP_PROTO_ICMP:
|
||||||
return IPv4_HDRLEN + ICMP_HDRLEN;
|
return iphdrlen + ICMP_HDRLEN;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -146,9 +152,14 @@ static int ipv4_hdrsize(FAR struct ipv4_hdr_s *ipv4)
|
|||||||
|
|
||||||
static int ipv4_decr_ttl(FAR struct ipv4_hdr_s *ipv4)
|
static int ipv4_decr_ttl(FAR struct ipv4_hdr_s *ipv4)
|
||||||
{
|
{
|
||||||
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
|
uint16_t iphdrlen;
|
||||||
uint16_t sum;
|
uint16_t sum;
|
||||||
int ttl = (int)ipv4->ttl - 1;
|
int ttl
|
||||||
|
|
||||||
|
/* Check time-to-live (TTL) */
|
||||||
|
|
||||||
|
ttl = (int)ipv4->ttl - 1;
|
||||||
if (ttl <= 0)
|
if (ttl <= 0)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_NET_ICMP
|
#ifdef CONFIG_NET_ICMP
|
||||||
@ -165,13 +176,17 @@ static int ipv4_decr_ttl(FAR struct ipv4_hdr_s *ipv4)
|
|||||||
|
|
||||||
ipv4->ttl = ttl;
|
ipv4->ttl = ttl;
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
/* Re-calculate the IPv4 checksum. This checksum is the Internet checksum
|
/* Re-calculate the IPv4 checksum. This checksum is the Internet checksum
|
||||||
* of the 20 bytes of the IPv4 header. This checksum will be different
|
* of the 20 bytes of the IPv4 header. This checksum will be different
|
||||||
* because we just modify the IPv4 TTL.
|
* because we just modify the IPv4 TTL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ipv4->ipchksum = 0;
|
ipv4->ipchksum = 0;
|
||||||
sum = chksum(0, (FAR const uint8_t *)ipv4, IPv4_HDRLEN);
|
sum = chksum(0, (FAR const uint8_t *)ipv4, iphdrlen);
|
||||||
if (sum == 0)
|
if (sum == 0)
|
||||||
{
|
{
|
||||||
sum = 0xffff;
|
sum = 0xffff;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* net/tcp/tcp_input.c
|
* net/tcp/tcp_input.c
|
||||||
* Handling incoming TCP input
|
* Handling incoming TCP input
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2014, 2017-2018 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2014, 2017-2019 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
||||||
@ -62,6 +62,12 @@
|
|||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "tcp/tcp.h"
|
#include "tcp/tcp.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1037,13 +1043,20 @@ drop:
|
|||||||
#ifdef CONFIG_NET_IPv4
|
#ifdef CONFIG_NET_IPv4
|
||||||
void tcp_ipv4_input(FAR struct net_driver_s *dev)
|
void tcp_ipv4_input(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
/* Configure to receive an TCP IPv4 packet */
|
/* Configure to receive an TCP IPv4 packet */
|
||||||
|
|
||||||
tcp_ipv4_select(dev);
|
tcp_ipv4_select(dev);
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
/* Then process in the TCP IPv4 input */
|
/* Then process in the TCP IPv4 input */
|
||||||
|
|
||||||
tcp_input(dev, PF_INET, IPv4_HDRLEN);
|
tcp_input(dev, PF_INET, iphdrlen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
* net/udp/udp_input.c
|
* net/udp/udp_input.c
|
||||||
* Handling incoming UDP input
|
* Handling incoming UDP input
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2009, 2011, 2018 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2007-2009, 2011, 2018-2019 Gregory Nutt. All rights
|
||||||
|
* reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
||||||
@ -56,6 +57,12 @@
|
|||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "udp/udp.h"
|
#include "udp/udp.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -254,13 +261,20 @@ static int udp_input(FAR struct net_driver_s *dev, unsigned int iplen)
|
|||||||
#ifdef CONFIG_NET_IPv4
|
#ifdef CONFIG_NET_IPv4
|
||||||
int udp_ipv4_input(FAR struct net_driver_s *dev)
|
int udp_ipv4_input(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
/* Configure to receive an UDP IPv4 packet */
|
/* Configure to receive an UDP IPv4 packet */
|
||||||
|
|
||||||
udp_ipv4_select(dev);
|
udp_ipv4_select(dev);
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
/* Then process in the UDP IPv4 input */
|
/* Then process in the UDP IPv4 input */
|
||||||
|
|
||||||
return udp_input(dev, IPv4_HDRLEN);
|
return udp_input(dev, iphdrlen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -53,8 +53,9 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define ICMPBUF ((struct icmp_iphdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv4BUF ((FAR struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
#define ICMPv6BUF ((struct icmp_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define ICMPBUF(hl) ((FAR struct icmp_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev) + (hl)])
|
||||||
|
#define ICMPv6BUF ((struct icmp_ipv6hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -71,7 +72,17 @@
|
|||||||
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_SOCKET)
|
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_SOCKET)
|
||||||
uint16_t icmp_chksum(FAR struct net_driver_s *dev, int len)
|
uint16_t icmp_chksum(FAR struct net_driver_s *dev, int len)
|
||||||
{
|
{
|
||||||
FAR struct icmp_iphdr_s *icmp = ICMPBUF;
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
|
FAR struct icmp_hdr_s *icmp;
|
||||||
|
uint16_t iphdrlen;
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
|
/* The ICMP header immediately follows the IP header */
|
||||||
|
|
||||||
|
icmp = ICMPBUF(iphdrlen);
|
||||||
return net_chksum((FAR uint16_t *)&icmp->type, len);
|
return net_chksum((FAR uint16_t *)&icmp->type, len);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_SOCKET */
|
#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_SOCKET */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/utils/net_ipchksum.c
|
* net/utils/net_ipchksum.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007-2010, 2012, 2014-2015, 2017-2018 Gregory Nutt. All
|
* Copyright (C) 2007-2010, 2012, 2014-2015, 2017-2019 Gregory Nutt. All
|
||||||
* rights reserved.
|
* rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
@ -55,8 +55,8 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#define IPv4BUF ((struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv4BUF ((struct ipv4_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
#define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
#define IPv6BUF ((struct ipv6_hdr_s *)&dev->d_buf[NET_LL_HDRLEN(dev)])
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
@ -84,14 +84,19 @@ uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto)
|
|||||||
{
|
{
|
||||||
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
uint16_t upperlen;
|
uint16_t upperlen;
|
||||||
|
uint16_t iphdrlen;
|
||||||
uint16_t sum;
|
uint16_t sum;
|
||||||
|
|
||||||
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
/* The length reported in the IPv4 header is the length of both the IPv4
|
/* The length reported in the IPv4 header is the length of both the IPv4
|
||||||
* header and the payload that follows the header. We need to subtract
|
* header and the payload that follows the header. We need to subtract
|
||||||
* the size of the IPv4 header to get the size of the payload.
|
* the size of the IPv4 header to get the size of the payload.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
upperlen = (((uint16_t)(ipv4->len[0]) << 8) + ipv4->len[1]) - IPv4_HDRLEN;
|
upperlen = (((uint16_t)(ipv4->len[0]) << 8) + ipv4->len[1]) - iphdrlen;
|
||||||
|
|
||||||
/* Verify some minimal assumptions */
|
/* Verify some minimal assumptions */
|
||||||
|
|
||||||
@ -113,7 +118,7 @@ uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto)
|
|||||||
|
|
||||||
/* Sum IP payload data. */
|
/* Sum IP payload data. */
|
||||||
|
|
||||||
sum = chksum(sum, &dev->d_buf[IPv4_HDRLEN + NET_LL_HDRLEN(dev)], upperlen);
|
sum = chksum(sum, &dev->d_buf[iphdrlen + NET_LL_HDRLEN(dev)], upperlen);
|
||||||
return (sum == 0) ? 0xffff : htons(sum);
|
return (sum == 0) ? 0xffff : htons(sum);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
||||||
@ -205,9 +210,15 @@ uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev,
|
|||||||
#if defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_ARCH_CHKSUM)
|
#if defined(CONFIG_NET_IPv4) && !defined(CONFIG_NET_ARCH_CHKSUM)
|
||||||
uint16_t ipv4_chksum(FAR struct net_driver_s *dev)
|
uint16_t ipv4_chksum(FAR struct net_driver_s *dev)
|
||||||
{
|
{
|
||||||
|
FAR struct ipv4_hdr_s *ipv4 = IPv4BUF;
|
||||||
|
uint16_t iphdrlen;
|
||||||
uint16_t sum;
|
uint16_t sum;
|
||||||
|
|
||||||
sum = chksum(0, &dev->d_buf[NET_LL_HDRLEN(dev)], IPv4_HDRLEN);
|
/* Get the IP header length (accounting for possible options). */
|
||||||
|
|
||||||
|
iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2;
|
||||||
|
|
||||||
|
sum = chksum(0, &dev->d_buf[NET_LL_HDRLEN(dev)], iphdrlen);
|
||||||
return (sum == 0) ? 0xffff : htons(sum);
|
return (sum == 0) ? 0xffff : htons(sum);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
#endif /* CONFIG_NET_ARCH_CHKSUM */
|
||||||
|
Loading…
Reference in New Issue
Block a user