From 391b50163982793e4fa0d439ff71ea04dc23fa61 Mon Sep 17 00:00:00 2001 From: liyi Date: Tue, 29 Nov 2022 11:23:43 +0800 Subject: [PATCH] net: extract l3 header build code into new functions Signed-off-by: liyi --- include/nuttx/net/ip.h | 9 ++ include/nuttx/net/netdev.h | 21 --- net/devif/ipv4_input.c | 3 +- net/icmp/icmp_reply.c | 27 +--- net/icmp/icmp_sendmsg.c | 29 +--- net/icmpv6/icmpv6_advertise.c | 22 +-- net/icmpv6/icmpv6_radvertise.c | 26 +-- net/icmpv6/icmpv6_reply.c | 23 +-- net/icmpv6/icmpv6_rsolicit.c | 27 +--- net/icmpv6/icmpv6_sendmsg.c | 19 +-- net/icmpv6/icmpv6_solicit.c | 29 +--- net/igmp/igmp_send.c | 34 +--- net/inet/Make.defs | 4 +- net/inet/inet.h | 58 ++++++- net/inet/inet_globals.c | 6 - net/inet/ipv4_build_header.c | 109 +++++++++++++ net/inet/ipv6_build_header.c | 81 ++++++++++ net/mld/mld_send.c | 24 +-- net/tcp/tcp_send.c | 280 +++++++-------------------------- net/udp/udp_send.c | 61 ++----- net/utils/Kconfig | 2 +- net/utils/net_ipchksum.c | 5 +- net/utils/utils.h | 21 +++ 23 files changed, 398 insertions(+), 522 deletions(-) create mode 100644 net/inet/ipv4_build_header.c create mode 100644 net/inet/ipv6_build_header.c diff --git a/include/nuttx/net/ip.h b/include/nuttx/net/ip.h index f503f777f2..864a729212 100644 --- a/include/nuttx/net/ip.h +++ b/include/nuttx/net/ip.h @@ -88,6 +88,7 @@ #ifdef CONFIG_NET_IPv4 # define IPv4_HDRLEN 20 /* Size of IPv4 header (without options) */ # define IPv4_HLMASK 0x0f /* Isolates headler length in VHL field */ +# define IPV4_OPTMAX 40 /* The limit of ip option length */ #endif #ifdef CONFIG_NET_IPv6 @@ -164,6 +165,14 @@ struct ipv4_hdr_s uint16_t srcipaddr[2]; /* 32-bit Source IP address */ uint16_t destipaddr[2]; /* 32-bit Destination IP address */ }; + +/* The IPv4 options */ + +struct ipv4_opt_s +{ + uint8_t len; + uint8_t data[IPV4_OPTMAX]; +}; #endif /* CONFIG_NET_IPv4 */ #ifdef CONFIG_NET_IPv6 diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index 0c6e628abf..371bb23ab0 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -668,27 +668,6 @@ uint16_t net_chksum(FAR uint16_t *data, uint16_t len); void net_incr32(FAR uint8_t *op32, uint16_t op16); -/**************************************************************************** - * Name: ipv4_chksum - * - * Description: - * Calculate the IPv4 header checksum of the packet header in d_buf. - * - * The IPv4 header checksum is the Internet checksum of the 20 bytes of - * the IPv4 header. - * - * If CONFIG_NET_ARCH_CHKSUM is defined, then this function must be - * provided by architecture-specific logic. - * - * Returned Value: - * The IPv4 header checksum of the IPv4 header in the d_buf buffer. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_IPv4 -uint16_t ipv4_chksum(FAR struct net_driver_s *dev); -#endif - /**************************************************************************** * Name: netdev_ipv4_hdrlen * diff --git a/net/devif/ipv4_input.c b/net/devif/ipv4_input.c index 8bd5932650..b726f40096 100644 --- a/net/devif/ipv4_input.c +++ b/net/devif/ipv4_input.c @@ -105,6 +105,7 @@ #include "ipforward/ipforward.h" #include "devif/devif.h" #include "nat/nat.h" +#include "utils/utils.h" /**************************************************************************** * Private Data @@ -342,7 +343,7 @@ int ipv4_input(FAR struct net_driver_s *dev) } #endif - if (ipv4_chksum(dev) != 0xffff) + if (ipv4_chksum(IPv4BUF) != 0xffff) { /* Compute and check the IP header checksum. */ diff --git a/net/icmp/icmp_reply.c b/net/icmp/icmp_reply.c index e87073af90..82b758339b 100644 --- a/net/icmp/icmp_reply.c +++ b/net/icmp/icmp_reply.c @@ -127,27 +127,9 @@ void icmp_reply(FAR struct net_driver_s *dev, int type, int code) memmove(icmp + 1, ipv4, datalen); - /* Initialize the IP header. */ - - ipv4->vhl = 0x45; - ipv4->tos = 0; - ipv4->len[0] = (dev->d_len >> 8); - ipv4->len[1] = (dev->d_len & 0xff); - ++g_ipid; - ipv4->ipid[0] = g_ipid >> 8; - ipv4->ipid[1] = g_ipid & 0xff; - ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; - ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; - ipv4->ttl = IP_TTL_DEFAULT; - ipv4->proto = IP_PROTO_ICMP; - - /* Calculate IP checksum. */ - - ipv4->ipchksum = 0; - ipv4->ipchksum = ~ipv4_chksum(dev); - - net_ipv4addr_hdrcopy(ipv4->destipaddr, ipv4->srcipaddr); - net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); + ipv4_build_header(IPv4BUF, dev->d_len, IP_PROTO_ICMP, + &dev->d_ipaddr, (FAR in_addr_t *)ipv4->srcipaddr, + IP_TTL_DEFAULT, NULL); /* Initialize the ICMP header */ @@ -165,8 +147,7 @@ void icmp_reply(FAR struct net_driver_s *dev, int type, int code) icmp->icmpchksum = 0xffff; } - ninfo("Outgoing ICMP packet length: %d (%d)\n", - dev->d_len, (ipv4->len[0] << 8) | ipv4->len[1]); + ninfo("Outgoing ICMP packet length: %d\n", dev->d_len); } #endif /* CONFIG_NET_ICMP */ diff --git a/net/icmp/icmp_sendmsg.c b/net/icmp/icmp_sendmsg.c index fb0fc659bf..f3ddcd43cd 100644 --- a/net/icmp/icmp_sendmsg.c +++ b/net/icmp/icmp_sendmsg.c @@ -97,7 +97,6 @@ struct icmp_sendto_s static void sendto_request(FAR struct net_driver_s *dev, FAR struct icmp_sendto_s *pstate) { - FAR struct ipv4_hdr_s *ipv4; FAR struct icmp_hdr_s *icmp; IFF_SET_IPv4(dev->d_flags); @@ -112,33 +111,16 @@ static void sendto_request(FAR struct net_driver_s *dev, dev->d_sndlen += pstate->snd_buflen; - /* Initialize the IP header. */ - - ipv4 = IPv4BUF; - ipv4->vhl = 0x45; - ipv4->tos = 0; - ipv4->len[0] = (dev->d_len >> 8); - ipv4->len[1] = (dev->d_len & 0xff); - ++g_ipid; - ipv4->ipid[0] = g_ipid >> 8; - ipv4->ipid[1] = g_ipid & 0xff; - ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; - ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; - ipv4->ttl = IP_TTL_DEFAULT; - ipv4->proto = IP_PROTO_ICMP; - - net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); - net_ipv4addr_hdrcopy(ipv4->destipaddr, &pstate->snd_toaddr); - /* Copy the ICMP header and payload into place after the IPv4 header */ icmp = IPBUF(IPv4_HDRLEN); memcpy(icmp, pstate->snd_buf, pstate->snd_buflen); - /* Calculate IP checksum. */ + /* Initialize the IP header. */ - ipv4->ipchksum = 0; - ipv4->ipchksum = ~(ipv4_chksum(dev)); + ipv4_build_header(IPv4BUF, dev->d_len, IP_PROTO_ICMP, + &dev->d_ipaddr, &pstate->snd_toaddr, + IP_TTL_DEFAULT, NULL); /* Calculate the ICMP checksum. */ @@ -149,8 +131,7 @@ static void sendto_request(FAR struct net_driver_s *dev, icmp->icmpchksum = 0xffff; } - ninfo("Outgoing ICMP packet length: %d (%d)\n", - dev->d_len, (ipv4->len[0] << 8) | ipv4->len[1]); + ninfo("Outgoing ICMP packet length: %d\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.icmp.sent++; diff --git a/net/icmpv6/icmpv6_advertise.c b/net/icmpv6/icmpv6_advertise.c index 5485246eed..1ca008eacf 100644 --- a/net/icmpv6/icmpv6_advertise.c +++ b/net/icmpv6/icmpv6_advertise.c @@ -38,6 +38,7 @@ #include "netdev/netdev.h" #include "utils/utils.h" #include "icmpv6/icmpv6.h" +#include "inet/inet.h" #ifdef CONFIG_NET_ICMPv6 @@ -66,31 +67,17 @@ void icmpv6_advertise(FAR struct net_driver_s *dev, const net_ipv6addr_t destipaddr) { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; FAR struct icmpv6_neighbor_advertise_s *adv; uint16_t lladdrsize; uint16_t l3size; - /* Set up the IPv6 header */ - - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class (LS)/Flow label (MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - /* Length excludes the IPv6 header */ lladdrsize = netdev_lladdrsize(dev); l3size = SIZEOF_ICMPV6_NEIGHBOR_ADVERTISE_S(lladdrsize); - ipv6->len[0] = (l3size >> 8); - ipv6->len[1] = (l3size & 0xff); - ipv6->proto = IP_PROTO_ICMP6; /* Next header */ - ipv6->ttl = 255; /* Hop limit */ - - /* Swap source for destination IP address, add our source IP address */ - - net_ipv6addr_copy(ipv6->destipaddr, destipaddr); - net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr); + ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6, + dev->d_ipv6addr, destipaddr, 255); /* Set up the ICMPv6 Neighbor Advertise response */ @@ -125,8 +112,7 @@ void icmpv6_advertise(FAR struct net_driver_s *dev, dev->d_len = IPv6_HDRLEN + l3size; - ninfo("Outgoing ICMPv6 Neighbor Advertise length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + ninfo("Outgoing ICMPv6 Neighbor Advertise length: %d\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.icmpv6.sent++; diff --git a/net/icmpv6/icmpv6_radvertise.c b/net/icmpv6/icmpv6_radvertise.c index 37ff4ac236..e818229ca0 100644 --- a/net/icmpv6/icmpv6_radvertise.c +++ b/net/icmpv6/icmpv6_radvertise.c @@ -116,20 +116,14 @@ static inline void ipv6addr_mask(FAR uint16_t *dest, FAR const uint16_t *src, void icmpv6_radvertise(FAR struct net_driver_s *dev) { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; FAR struct icmpv6_router_advertise_s *adv; FAR struct icmpv6_srclladdr_s *srcaddr; FAR struct icmpv6_mtu_s *mtu; FAR struct icmpv6_prefixinfo_s *prefix; + net_ipv6addr_t srcv6addr; uint16_t lladdrsize; uint16_t l3size; - /* Set up the IPv6 header */ - - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class (LS)/Flow label (MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - /* Length excludes the IPv6 header */ lladdrsize = netdev_lladdrsize(dev); @@ -138,19 +132,12 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev) sizeof(struct icmpv6_mtu_s) + sizeof(struct icmpv6_prefixinfo_s); - ipv6->len[0] = (l3size >> 8); - ipv6->len[1] = (l3size & 0xff); - - ipv6->proto = IP_PROTO_ICMP6; /* Next header */ - ipv6->ttl = 255; /* Hop limit */ - - /* Swap source for destination IP address, add our source IP address */ - - net_ipv6addr_copy(ipv6->destipaddr, g_ipv6_allnodes); - /* Source IP address must be set to link-local IP */ - icmpv6_linkipaddr(dev, ipv6->srcipaddr); + icmpv6_linkipaddr(dev, srcv6addr); + + ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6, + srcv6addr, g_ipv6_allnodes, 255); /* Set up the ICMPv6 Router Advertise response */ @@ -215,8 +202,7 @@ void icmpv6_radvertise(FAR struct net_driver_s *dev) dev->d_len = IPv6_HDRLEN + l3size; - ninfo("Outgoing ICMPv6 Router Advertise length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + ninfo("Outgoing ICMPv6 Router Advertise length: %d\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.icmpv6.sent++; diff --git a/net/icmpv6/icmpv6_reply.c b/net/icmpv6/icmpv6_reply.c index 3d5ce1849a..2784823d49 100644 --- a/net/icmpv6/icmpv6_reply.c +++ b/net/icmpv6/icmpv6_reply.c @@ -88,7 +88,6 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data) FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; FAR struct icmpv6_hdr_s *icmpv6 = (FAR struct icmpv6_hdr_s *)(ipv6 + 1); uint16_t datalen; - uint16_t paylen; if (net_ipv6addr_cmp(ipv6->destipaddr, g_ipv6_unspecaddr) # ifdef CONFIG_NET_BROADCAST @@ -112,24 +111,9 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data) } dev->d_len = ipicmplen + datalen; - paylen = dev->d_len - IPv6_HDRLEN; - /* Copy fields from original packet */ - - memmove(icmpv6 + 1, ipv6, datalen); - - /* Set up the IPv6 header (most is probably already in place) */ - - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class(LS)/Flow label(MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - ipv6->len[0] = (paylen >> 8); /* Length excludes the IPv6 header */ - ipv6->len[1] = (paylen & 0xff); - ipv6->proto = IP_PROTO_ICMP6; /* Next header */ - ipv6->ttl = 255; /* Hop limit */ - - net_ipv6addr_hdrcopy(ipv6->destipaddr, ipv6->srcipaddr); - net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); + ipv6_build_header(IPv6BUF, dev->d_len - IPv6_HDRLEN, IP_PROTO_ICMP6, + dev->d_ipv6addr, ipv6->srcipaddr, 255); /* Initialize the ICMPv6 header */ @@ -147,8 +131,7 @@ void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data) icmpv6->chksum = 0xffff; } - ninfo("Outgoing ICMPv6 packet length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + ninfo("Outgoing ICMPv6 packet length: %d\n", dev->d_len); } #endif /* CONFIG_NET_ICMPv6 */ diff --git a/net/icmpv6/icmpv6_rsolicit.c b/net/icmpv6/icmpv6_rsolicit.c index 2f9953478e..253d3cb0a9 100644 --- a/net/icmpv6/icmpv6_rsolicit.c +++ b/net/icmpv6/icmpv6_rsolicit.c @@ -66,37 +66,17 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev) { - FAR struct ipv6_hdr_s *ipv6; FAR struct icmpv6_router_solicit_s *sol; uint16_t lladdrsize; uint16_t l3size; - /* Set up the IPv6 header (most is probably already in place) */ - - ipv6 = IPv6BUF; - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class (LS)/Flow label (MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - /* Length excludes the IPv6 header */ lladdrsize = netdev_lladdrsize(dev); l3size = SIZEOF_ICMPV6_ROUTER_SOLICIT_S(lladdrsize); - ipv6->len[0] = (l3size >> 8); - ipv6->len[1] = (l3size & 0xff); - ipv6->proto = IP_PROTO_ICMP6; /* Next header */ - ipv6->ttl = 255; /* Hop limit */ - - /* Set the multicast destination IP address to the IPv6 all link- - * local routers address: ff02::2 - */ - - net_ipv6addr_copy(ipv6->destipaddr, g_ipv6_allrouters); - - /* Add our link local IPv6 address as the source address */ - - net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr); + ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6, + dev->d_ipv6addr, g_ipv6_allrouters, 255); /* Set up the ICMPv6 Router Solicitation message */ @@ -126,8 +106,7 @@ void icmpv6_rsolicit(FAR struct net_driver_s *dev) dev->d_len = IPv6_HDRLEN + l3size; - ninfo("Outgoing ICMPv6 Router Solicitation length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + ninfo("Outgoing ICMPv6 Router Solicitation length: %d\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.icmpv6.sent++; diff --git a/net/icmpv6/icmpv6_sendmsg.c b/net/icmpv6/icmpv6_sendmsg.c index 2e5f2d9943..12336e1ef8 100644 --- a/net/icmpv6/icmpv6_sendmsg.c +++ b/net/icmpv6/icmpv6_sendmsg.c @@ -96,7 +96,6 @@ struct icmpv6_sendto_s static void sendto_request(FAR struct net_driver_s *dev, FAR struct icmpv6_sendto_s *pstate) { - FAR struct ipv6_hdr_s *ipv6; FAR struct icmpv6_echo_request_s *icmpv6; IFF_SET_IPv6(dev->d_flags); @@ -111,19 +110,8 @@ static void sendto_request(FAR struct net_driver_s *dev, dev->d_sndlen += pstate->snd_buflen; - /* Set up the IPv6 header (most is probably already in place) */ - - ipv6 = IPv6BUF; - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class(LS)/Flow label(MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - ipv6->len[0] = (pstate->snd_buflen >> 8); /* Length excludes the IPv6 header */ - ipv6->len[1] = (pstate->snd_buflen & 0xff); - ipv6->proto = IP_PROTO_ICMP6; /* Next header */ - ipv6->ttl = 255; /* Hop limit */ - - net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); - net_ipv6addr_hdrcopy(ipv6->destipaddr, pstate->snd_toaddr.s6_addr16); + ipv6_build_header(IPv6BUF, pstate->snd_buflen, IP_PROTO_ICMP6, + dev->d_ipv6addr, pstate->snd_toaddr.s6_addr16, 255); /* Copy the ICMPv6 request and payload into place after the IPv6 header */ @@ -139,8 +127,7 @@ static void sendto_request(FAR struct net_driver_s *dev, icmpv6->chksum = 0xffff; } - ninfo("Outgoing ICMPv6 packet length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + ninfo("Outgoing ICMPv6 packet length: %d\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.icmpv6.sent++; diff --git a/net/icmpv6/icmpv6_solicit.c b/net/icmpv6/icmpv6_solicit.c index ca039742b0..e4c22445fa 100644 --- a/net/icmpv6/icmpv6_solicit.c +++ b/net/icmpv6/icmpv6_solicit.c @@ -36,6 +36,7 @@ #include "netdev/netdev.h" #include "utils/utils.h" #include "icmpv6/icmpv6.h" +#include "inet/inet.h" #ifdef CONFIG_NET_ICMPv6 @@ -77,37 +78,24 @@ static const uint16_t g_icmpv_mcastaddr[6] = void icmpv6_solicit(FAR struct net_driver_s *dev, FAR const net_ipv6addr_t ipaddr) { - FAR struct ipv6_hdr_s *ipv6; FAR struct icmpv6_neighbor_solicit_s *sol; + net_ipv6addr_t dstaddr; uint16_t lladdrsize; uint16_t l3size; - /* Set up the IPv6 header (most is probably already in place) */ - - ipv6 = IPv6BUF; - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class (LS)/Flow label (MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - /* Length excludes the IPv6 header */ lladdrsize = netdev_lladdrsize(dev); l3size = SIZEOF_ICMPV6_NEIGHBOR_SOLICIT_S(lladdrsize); - ipv6->len[0] = (l3size >> 8); - ipv6->len[1] = (l3size & 0xff); - - ipv6->proto = IP_PROTO_ICMP6; /* Next header */ - ipv6->ttl = 255; /* Hop limit */ /* Set the multicast destination IP address */ - memcpy(ipv6->destipaddr, g_icmpv_mcastaddr, 6*sizeof(uint16_t)); - ipv6->destipaddr[6] = ipaddr[6] | HTONS(0xff00); - ipv6->destipaddr[7] = ipaddr[7]; + memcpy(dstaddr, g_icmpv_mcastaddr, sizeof(g_icmpv_mcastaddr)); + dstaddr[6] = ipaddr[6] | HTONS(0xff00); + dstaddr[7] = ipaddr[7]; - /* Add out IPv6 address as the source address */ - - net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr); + ipv6_build_header(IPv6BUF, l3size, IP_PROTO_ICMP6, + dev->d_ipv6addr, dstaddr, 255); /* Set up the ICMPv6 Neighbor Solicitation message */ @@ -141,8 +129,7 @@ void icmpv6_solicit(FAR struct net_driver_s *dev, dev->d_len = IPv6_HDRLEN + l3size; - ninfo("Outgoing ICMPv6 Neighbor Solicitation length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + ninfo("Outgoing ICMPv6 Neighbor Solicitation length: %d\n", dev->d_len); #ifdef CONFIG_NET_STATISTICS g_netstats.icmpv6.sent++; diff --git a/net/igmp/igmp_send.c b/net/igmp/igmp_send.c index fa001212a7..1146e81ea9 100644 --- a/net/igmp/igmp_send.c +++ b/net/igmp/igmp_send.c @@ -102,9 +102,10 @@ 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, FAR const in_addr_t *destipaddr, uint8_t msgid) { - FAR struct igmp_iphdr_s *ipv4 = IPBUF(0); FAR struct igmp_hdr_s *igmp; uint16_t iphdrlen; + struct ipv4_opt_s opt; + uint32_t tmp; ninfo("msgid: %02x destipaddr: %08x\n", msgid, (int)*destipaddr); @@ -125,30 +126,12 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group, /* Add the router alert option to the IPv4 header (RFC 2113) */ - ipv4->ra[0] = HTONS(IPOPT_RA >> 16); - ipv4->ra[1] = HTONS(IPOPT_RA & 0xffff); + tmp = HTONL(IPOPT_RA); + memcpy(opt.data, &tmp, sizeof(uint32_t)); + opt.len = sizeof(uint32_t); - /* Initialize the IPv4 header */ - - ipv4->vhl = 0x46; /* 4->IP; 6->24 bytes */ - ipv4->tos = 0; - ipv4->len[0] = (dev->d_len >> 8); - ipv4->len[1] = (dev->d_len & 0xff); - ++g_ipid; - ipv4->ipid[0] = g_ipid >> 8; - ipv4->ipid[1] = g_ipid & 0xff; - ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; - ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; - ipv4->ttl = IGMP_TTL; - ipv4->proto = IP_PROTO_IGMP; - - net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); - net_ipv4addr_hdrcopy(ipv4->destipaddr, destipaddr); - - /* Calculate IP checksum. */ - - ipv4->ipchksum = 0; - ipv4->ipchksum = ~igmp_chksum((FAR uint8_t *)igmp, iphdrlen); + ipv4_build_header(IPv4BUF, dev->d_len, IP_PROTO_IGMP, + &dev->d_ipaddr, destipaddr, IGMP_TTL, &opt); /* Set up the IGMP message */ @@ -164,8 +147,7 @@ void igmp_send(FAR struct net_driver_s *dev, FAR struct igmp_group_s *group, IGMP_STATINCR(g_netstats.igmp.poll_send); IGMP_STATINCR(g_netstats.ipv4.sent); - ninfo("Outgoing IGMP packet length: %d (%d)\n", - dev->d_len, (ipv4->len[0] << 8) | ipv4->len[1]); + ninfo("Outgoing IGMP packet length: %d\n", dev->d_len); igmp_dumppkt(RA, iphdrlen + IGMP_HDRLEN); } diff --git a/net/inet/Make.defs b/net/inet/Make.defs index 986561a818..0fcbf4f2bc 100644 --- a/net/inet/Make.defs +++ b/net/inet/Make.defs @@ -31,11 +31,11 @@ SOCK_CSRCS += inet_globals.c endif ifeq ($(CONFIG_NET_IPv4),y) -SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockname.c ipv4_getpeername.c +SOCK_CSRCS += ipv4_setsockopt.c ipv4_getsockname.c ipv4_getpeername.c ipv4_build_header.c endif ifeq ($(CONFIG_NET_IPv6),y) -SOCK_CSRCS += ipv6_setsockopt.c ipv6_getsockname.c ipv6_getpeername.c +SOCK_CSRCS += ipv6_setsockopt.c ipv6_getsockname.c ipv6_getpeername.c ipv6_build_header.c endif # Include inet build support diff --git a/net/inet/inet.h b/net/inet/inet.h index 73838365bf..2eaf1d8a07 100644 --- a/net/inet/inet.h +++ b/net/inet/inet.h @@ -67,12 +67,6 @@ extern "C" #define EXTERN extern #endif -#ifdef CONFIG_NET_IPv4 -/* Increasing number used for the IP ID field. */ - -EXTERN uint16_t g_ipid; -#endif /* CONFIG_NET_IPv4 */ - /* Well-known IPv6 addresses */ #ifdef CONFIG_NET_IPv6 @@ -261,6 +255,58 @@ int inet_close(FAR struct socket *psock); int inet_txdrain(FAR struct socket *psock, unsigned int timeout); +/**************************************************************************** + * Name: ipv4_build_header + * + * Description: + * build IPv4 header + * + * Input Parameters: + * ipv4 Pointer to IPv4 header's buffer + * total_len total length of the IPv4 packet + * prot the next level protocol used in IPv4 packet + * src_ip Source IPv4 address + * dst_ip Destination IPv4 address + * ttl Time to live(IPv4) + * opt IPv4 options + * + * Returned Value: + * length of IPv4 header + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +uint16_t ipv4_build_header(FAR struct ipv4_hdr_s *ipv4, uint16_t total_len, + uint16_t prot, FAR const in_addr_t *src_ip, + FAR const in_addr_t *dst_ip, uint8_t ttl, + FAR struct ipv4_opt_s *opt); +#endif + +/**************************************************************************** + * Name: ipv6_build_header + * + * Description: + * build IPv6 header + * + * Input Parameters: + * ipv6 Pointer to IPv6 header's buffer + * payload_len Length of the IPv6 payload(without IPv6 header length) + * prot Type of header immediately following the IPv6 header + * src_ip Source IPv6 address + * dst_ip Destination IPv6 address + * ttl hop limit(IPv6) + * + * Returned Value: + * length of IPv6 header + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv6 +uint16_t ipv6_build_header(FAR struct ipv6_hdr_s *ipv6, uint16_t payload_len, + uint16_t prot, const net_ipv6addr_t src_ip, + const net_ipv6addr_t dst_ip, uint8_t ttl); +#endif + #undef EXTERN #if defined(__cplusplus) } diff --git a/net/inet/inet_globals.c b/net/inet/inet_globals.c index 4abf0e8d1b..0f7580468a 100644 --- a/net/inet/inet_globals.c +++ b/net/inet/inet_globals.c @@ -38,12 +38,6 @@ * Public Data ****************************************************************************/ -#ifdef CONFIG_NET_IPv4 -/* Increasing number used for the IP ID field. */ - -uint16_t g_ipid; -#endif /* CONFIG_NET_IPv4 */ - #ifdef CONFIG_NET_IPv6 /* Unspecified address (all zero). See RFC 4291 (replaces 3513) */ diff --git a/net/inet/ipv4_build_header.c b/net/inet/ipv4_build_header.c new file mode 100644 index 0000000000..61b1cd979a --- /dev/null +++ b/net/inet/ipv4_build_header.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * net/inet/ipv4_build_header.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "inet.h" +#include "utils/utils.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 + +/* Increasing number used for the IP ID field. */ + +static uint16_t g_ipid; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipv4_build_header + * + * Description: + * build IPv4 header + * + * Input Parameters: + * ipv4 Pointer to IPv4 header's buffer + * total_len total length of the IPv4 packet + * prot the next level protocol used in IPv4 packet + * src_ip Source IPv4 address + * dst_ip Destination IPv4 address + * ttl Time to live(IPv4) + * opt IPv4 options + * + * Returned Value: + * length of IPv4 header + * + ****************************************************************************/ + +uint16_t ipv4_build_header(FAR struct ipv4_hdr_s *ipv4, uint16_t total_len, + uint16_t prot, FAR const in_addr_t *src_ip, + FAR const in_addr_t *dst_ip, uint8_t ttl, + FAR struct ipv4_opt_s *opt) +{ + /* Initialize the IP header. */ + + ipv4->vhl = 0x45; /* orginal initial value like this */ + ipv4->tos = 0; + ipv4->len[0] = (total_len >> 8); + ipv4->len[1] = (total_len & 0xff); + ++g_ipid; + ipv4->ipid[0] = g_ipid >> 8; + ipv4->ipid[1] = g_ipid & 0xff; + ipv4->ipoffset[0] = IP_FLAG_DONTFRAG >> 8; + ipv4->ipoffset[1] = IP_FLAG_DONTFRAG & 0xff; + ipv4->ttl = ttl; + ipv4->proto = prot; + + /* It's possible to use its own src_ip to initialize its dest_ip */ + + net_ipv4addr_hdrcopy(ipv4->destipaddr, dst_ip); + net_ipv4addr_hdrcopy(ipv4->srcipaddr, src_ip); + + /* if ip has options, build it now */ + + if (opt != NULL) + { + ipv4->vhl += opt->len >> 2; + memcpy(ipv4 + 1, opt->data, opt->len); + } + + /* Calculate IP checksum. */ + + ipv4->ipchksum = 0; + ipv4->ipchksum = ~ipv4_chksum(ipv4); + + ninfo("IPv4 Packet: ipid:%d, length: %d\n", g_ipid, total_len); + + return (ipv4->vhl & IPv4_HLMASK) << 2; +} + +#endif /* CONFIG_NET_IPv4 */ diff --git a/net/inet/ipv6_build_header.c b/net/inet/ipv6_build_header.c new file mode 100644 index 0000000000..bf049dc30e --- /dev/null +++ b/net/inet/ipv6_build_header.c @@ -0,0 +1,81 @@ +/**************************************************************************** + * net/inet/ipv6_build_header.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "inet.h" + +#ifdef CONFIG_NET_IPv6 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ipv6_build_header + * + * Description: + * build IPv6 header + * + * Input Parameters: + * ipv6 Pointer to IPv6 header's buffer + * payload_len Length of the IPv6 payload(without IPv6 header length) + * prot Type of header immediately following the IPv6 header + * src_ip Source IPv6 address + * dst_ip Destination IPv6 address + * ttl Time to live(IPv4) hop limit(IPv6) + * + * Returned Value: + * length of IPv6 header + * + ****************************************************************************/ + +uint16_t ipv6_build_header(FAR struct ipv6_hdr_s *ipv6, uint16_t payload_len, + uint16_t prot, const net_ipv6addr_t src_ip, + const net_ipv6addr_t dst_ip, uint8_t ttl) +{ + /* Set up the IPv6 header */ + + ipv6->vtc = 0x60; /* Version/traffic class (MS) */ + ipv6->tcf = 0; /* Traffic class(LS)/Flow label(MS) */ + ipv6->flow = 0; /* Flow label (LS) */ + ipv6->len[0] = (payload_len >> 8); /* Length excludes the IPv6 header */ + ipv6->len[1] = (payload_len & 0xff); + ipv6->proto = prot; /* Next header */ + ipv6->ttl = ttl; + + /* It's possible to use srcip to initialize destip */ + + net_ipv6addr_hdrcopy(ipv6->destipaddr, dst_ip); + net_ipv6addr_hdrcopy(ipv6->srcipaddr, src_ip); + + ninfo("IPv6 Payload length: %d\n", payload_len); + + return IPv6_HDRLEN; +} + +#endif /* CONFIG_NET_IPv6 */ diff --git a/net/mld/mld_send.c b/net/mld/mld_send.c index d19c1b44a3..60903686c8 100644 --- a/net/mld/mld_send.c +++ b/net/mld/mld_send.c @@ -87,7 +87,6 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group, uint8_t msgtype) { - FAR struct ipv6_hdr_s *ipv6; FAR struct ipv6_router_alert_s *ra; FAR const uint16_t *destipaddr; unsigned int mldsize; @@ -160,23 +159,6 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group, dev->d_sndlen = RASIZE + mldsize; - /* Set up the IPv6 header */ - - ipv6 = IPv6BUF; - ipv6->vtc = 0x60; /* Version/traffic class (MS) */ - ipv6->tcf = 0; /* Traffic class(LS)/Flow label(MS) */ - ipv6->flow = 0; /* Flow label (LS) */ - ipv6->len[0] = (dev->d_sndlen >> 8); /* Length excludes the IPv6 header */ - ipv6->len[1] = (dev->d_sndlen & 0xff); /* but includes the extension headers */ - ipv6->proto = NEXT_HOPBYBOT_EH; /* Hop-to-hop extension header */ - ipv6->ttl = MLD_TTL; /* MLD Time-to-live */ - - /* Select the IPv6 source address (the local interface assigned to the - * network device). - */ - - net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); - /* Select the IPv6 destination address. * This varies with the type of message being sent: * @@ -216,7 +198,8 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group, destipaddr[0], destipaddr[1], destipaddr[2], destipaddr[3], destipaddr[4], destipaddr[5], destipaddr[6], destipaddr[7]); - net_ipv6addr_hdrcopy(ipv6->destipaddr, destipaddr); + ipv6_build_header(IPv6BUF, dev->d_sndlen, NEXT_HOPBYBOT_EH, + dev->d_ipv6addr, destipaddr, MLD_TTL); /* Add the router alert IP header option. * @@ -379,8 +362,7 @@ void mld_send(FAR struct net_driver_s *dev, FAR struct mld_group_s *group, MLD_STATINCR(g_netstats.icmpv6.sent); MLD_STATINCR(g_netstats.ipv6.sent); - mldinfo("Outgoing ICMPv6 MLD packet length: %d (%d)\n", - dev->d_len, (ipv6->len[0] << 8) | ipv6->len[1]); + mldinfo("Outgoing ICMPv6 MLD packet length: %d\n", dev->d_len); mld_dumppkt((FAR const uint8_t *)IPv6BUF, MLD_HDRLEN + mldsize); } diff --git a/net/tcp/tcp_send.c b/net/tcp/tcp_send.c index a067f7ca53..6b1da6190e 100644 --- a/net/tcp/tcp_send.c +++ b/net/tcp/tcp_send.c @@ -101,184 +101,6 @@ static inline FAR struct tcp_hdr_s *tcp_header(FAR struct net_driver_s *dev) #endif /* CONFIG_NET_IPv4 */ } -/**************************************************************************** - * Name: tcp_sendcomplete, tcp_ipv4_sendcomplete, and tcp_ipv6_sendcomplete - * - * Description: - * Complete the final portions of the send operation. This function sets - * up IP header and computes the TCP checksum - * - * Input Parameters: - * dev - The device driver structure to use in the send operation - * - * Returned Value: - * None - * - * Assumptions: - * Called with the network locked. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_IPv4 -static inline void tcp_ipv4_sendcomplete(FAR struct net_driver_s *dev, - FAR struct tcp_hdr_s *tcp, - FAR struct ipv4_hdr_s *ipv4) -{ - /* Set up some IP header fields that are needed for TCP checksum - * calculation. - */ - - ipv4->proto = IP_PROTO_TCP; - ipv4->ttl = IP_TTL_DEFAULT; - ipv4->vhl = 0x45; - - /* At this point the TCP header holds the size of the payload, the - * TCP header, and the IP header. - */ - - ipv4->len[0] = (dev->d_len >> 8); - ipv4->len[1] = (dev->d_len & 0xff); - - /* Calculate TCP checksum. */ - - tcp->urgp[0] = 0; - tcp->urgp[1] = 0; - - tcp->tcpchksum = 0; - tcp->tcpchksum = ~tcp_ipv4_chksum(dev); - - /* Finish initializing the IP header and calculate the IP checksum */ - - ipv4->vhl = 0x45; - ipv4->tos = 0; - ipv4->ipoffset[0] = 0; - ipv4->ipoffset[1] = 0; - ++g_ipid; - ipv4->ipid[0] = g_ipid >> 8; - ipv4->ipid[1] = g_ipid & 0xff; - - /* Calculate IP checksum. */ - - ipv4->ipchksum = 0; - ipv4->ipchksum = ~ipv4_chksum(dev); - - ninfo("IPv4 length: %d\n", ((int)ipv4->len[0] << 8) + ipv4->len[1]); - -#ifdef CONFIG_NET_STATISTICS - g_netstats.ipv4.sent++; -#endif -} -#endif /* CONFIG_NET_IPv4 */ - -/**************************************************************************** - * Name: tcp_ipv6_sendcomplete - * - * Description: - * Complete the final portions of the send operation. This function sets - * up IP header and computes the TCP checksum - * - * Input Parameters: - * dev - The device driver structure to use in the send operation - * - * Returned Value: - * None - * - * Assumptions: - * Called with the network locked. - * - ****************************************************************************/ - -#ifdef CONFIG_NET_IPv6 -static inline void tcp_ipv6_sendcomplete(FAR struct net_driver_s *dev, - FAR struct tcp_hdr_s *tcp, - FAR struct ipv6_hdr_s *ipv6) -{ - uint16_t iplen; - - /* Set up some IP header fields that are needed for TCP checksum - * calculation. - */ - - ipv6->proto = IP_PROTO_TCP; - ipv6->ttl = IP_TTL_DEFAULT; - - /* At this point the TCP header holds the size of the payload, the - * TCP header, and the IP header. For IPv6, the IP length field does - * not include the size of IPv6 IP header length. - */ - - iplen = dev->d_len - IPv6_HDRLEN; - ipv6->len[0] = (iplen >> 8); - ipv6->len[1] = (iplen & 0xff); - - /* Calculate TCP checksum. */ - - tcp->urgp[0] = 0; - tcp->urgp[1] = 0; - - tcp->tcpchksum = 0; - tcp->tcpchksum = ~tcp_ipv6_chksum(dev); - - /* Finish initializing the IP header (no IPv6 checksum) */ - - ipv6->vtc = 0x60; - ipv6->tcf = 0x00; - ipv6->flow = 0x00; - - ninfo("IPv6 length: %d\n", ((int)ipv6->len[0] << 8) + ipv6->len[1]); - -#ifdef CONFIG_NET_STATISTICS - g_netstats.ipv6.sent++; -#endif -} -#endif /* CONFIG_NET_IPv6 */ - -/**************************************************************************** - * Name: tcp_sendcomplete - * - * Description: - * Complete the final portions of the send operation. This function sets - * up IP header and computes the TCP checksum - * - * Input Parameters: - * dev - The device driver structure to use in the send operation - * - * Returned Value: - * None - * - * Assumptions: - * Called with the network locked. - * - ****************************************************************************/ - -static void tcp_sendcomplete(FAR struct net_driver_s *dev, - FAR struct tcp_hdr_s *tcp) -{ -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - if (IFF_IS_IPv6(dev->d_flags)) -#endif - { - tcp_ipv6_sendcomplete(dev, tcp, IPv6BUF); - } -#endif /* CONFIG_NET_IPv6 */ - -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - else -#endif - { - tcp_ipv4_sendcomplete(dev, tcp, IPv4BUF); - } -#endif /* CONFIG_NET_IPv4 */ - - ninfo("Outgoing TCP packet length: %d bytes\n", dev->d_len); - -#ifdef CONFIG_NET_STATISTICS - g_netstats.tcp.sent++; -#endif -} - /**************************************************************************** * Name: tcp_sendcommon * @@ -303,32 +125,6 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn, FAR struct tcp_hdr_s *tcp) { - /* Copy the IP address into the IPv6 header */ - -#ifdef CONFIG_NET_IPv6 -#ifdef CONFIG_NET_IPv4 - if (IFF_IS_IPv6(dev->d_flags)) -#endif - { - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; - - net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); - net_ipv6addr_hdrcopy(ipv6->destipaddr, conn->u.ipv6.raddr); - } -#endif /* CONFIG_NET_IPv6 */ - -#ifdef CONFIG_NET_IPv4 -#ifdef CONFIG_NET_IPv6 - else -#endif - { - FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; - - net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); - net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr); - } -#endif /* CONFIG_NET_IPv4 */ - /* Set TCP sequence numbers and port numbers */ memcpy(tcp->ackno, conn->rcvseq, 4); @@ -369,9 +165,55 @@ static void tcp_sendcommon(FAR struct net_driver_s *dev, tcp->wnd[1] = recvwndo & 0xff; } - /* Finish the IP portion of the message and calculate checksums */ + tcp->urgp[0] = 0; + tcp->urgp[1] = 0; - tcp_sendcomplete(dev, tcp); + /* Calculate chk & build L3 header */ + +#ifdef CONFIG_NET_IPv6 +#ifdef CONFIG_NET_IPv4 + if (IFF_IS_IPv6(dev->d_flags)) +#endif + { + ninfo("do IPv6 IP header build!\n"); + ipv6_build_header(IPv6BUF, dev->d_len - IPv6_HDRLEN, + IP_PROTO_TCP, dev->d_ipv6addr, conn->u.ipv6.raddr, + IP_TTL_DEFAULT); + + /* Calculate TCP checksum. */ + + tcp->tcpchksum = 0; + tcp->tcpchksum = ~tcp_ipv6_chksum(dev); +#ifdef CONFIG_NET_STATISTICS + g_netstats.ipv6.sent++; +#endif + } +#endif /* CONFIG_NET_IPv6 */ + +#ifdef CONFIG_NET_IPv4 +#ifdef CONFIG_NET_IPv6 + else +#endif + { + ninfo("do IPv4 IP header build!\n"); + ipv4_build_header(IPv4BUF, dev->d_len, IP_PROTO_TCP, + &dev->d_ipaddr, &conn->u.ipv4.raddr, + IP_TTL_DEFAULT, NULL); + + /* Calculate TCP checksum. */ + + tcp->tcpchksum = 0; + tcp->tcpchksum = ~tcp_ipv4_chksum(dev); +#ifdef CONFIG_NET_STATISTICS + g_netstats.ipv4.sent++; +#endif + } +#endif /* CONFIG_NET_IPv4 */ + + ninfo("Outgoing TCP packet length: %d bytes\n", dev->d_len); +#ifdef CONFIG_NET_STATISTICS + g_netstats.tcp.sent++; +#endif #if !defined(CONFIG_NET_TCP_WRITE_BUFFERS) if ((tcp->flags & (TCP_SYN | TCP_FIN)) != 0) @@ -524,14 +366,14 @@ void tcp_reset(FAR struct net_driver_s *dev) tcp->destport = tmp16; /* Initialize the rest of the tcp header to sane values. - * - * Note: urgp is set by tcp_ipv4_sendcomplete/tcp_ipv6_sendcomplete. */ tcp->wnd[0] = 0; tcp->wnd[1] = 0; + tcp->urgp[0] = 0; + tcp->urgp[0] = 0; - /* Set the packet length and swap IP addresses. */ + /* Calculate chk & build L3 header */ #ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv4 @@ -544,10 +386,12 @@ void tcp_reset(FAR struct net_driver_s *dev) dev->d_len = IPv6TCP_HDRLEN; - /* Swap IPv6 addresses */ + ipv6_build_header(ipv6, dev->d_len - IPv6_HDRLEN, + IP_PROTO_TCP, dev->d_ipv6addr, ipv6->srcipaddr, + IP_TTL_DEFAULT); - net_ipv6addr_hdrcopy(ipv6->destipaddr, ipv6->srcipaddr); - net_ipv6addr_hdrcopy(ipv6->srcipaddr, dev->d_ipv6addr); + tcp->tcpchksum = 0; + tcp->tcpchksum = ~tcp_ipv6_chksum(dev); } #endif /* CONFIG_NET_IPv6 */ @@ -562,16 +406,14 @@ void tcp_reset(FAR struct net_driver_s *dev) dev->d_len = IPv4TCP_HDRLEN; - /* Swap IPv4 addresses */ + ipv4_build_header(IPv4BUF, dev->d_len, IP_PROTO_TCP, + &dev->d_ipaddr, (FAR in_addr_t *)ipv4->srcipaddr, + IP_TTL_DEFAULT, NULL); - net_ipv4addr_hdrcopy(ipv4->destipaddr, ipv4->srcipaddr); - net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); + tcp->tcpchksum = 0; + tcp->tcpchksum = ~tcp_ipv4_chksum(dev); } #endif /* CONFIG_NET_IPv4 */ - - /* And send out the RST packet */ - - tcp_sendcomplete(dev, tcp); } /**************************************************************************** diff --git a/net/udp/udp_send.c b/net/udp/udp_send.c index 385e87bea6..7298e1e174 100644 --- a/net/udp/udp_send.c +++ b/net/udp/udp_send.c @@ -86,13 +86,14 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn) { FAR struct udp_hdr_s *udp; +#ifdef CONFIG_NET_IPv4 + in_addr_t raddr; +#endif ninfo("UDP payload: %d (%d) bytes\n", dev->d_sndlen, dev->d_len); if (dev->d_sndlen > 0) { - /* Initialize the IP header. */ - #ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET || @@ -100,39 +101,19 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn) ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr))) #endif { - /* Get pointers to the IPv4 header and the offset UDP header */ - - FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; - DEBUGASSERT(IFF_IS_IPv4(dev->d_flags)); udp = UDPIPv4BUF; - - /* Initialize the IPv4 header. */ - - ipv4->vhl = 0x45; - ipv4->tos = 0; - ++g_ipid; - ipv4->ipid[0] = g_ipid >> 8; - ipv4->ipid[1] = g_ipid & 0xff; - ipv4->ipoffset[0] = 0; - ipv4->ipoffset[1] = 0; - ipv4->ttl = conn->ttl; - ipv4->proto = IP_PROTO_UDP; - - net_ipv4addr_hdrcopy(ipv4->srcipaddr, &dev->d_ipaddr); - #ifdef CONFIG_NET_IPv6 if (conn->domain == PF_INET6 && ip6_is_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr)) { - in_addr_t raddr = + raddr = ip6_get_ipv4addr((FAR struct in6_addr *)conn->u.ipv6.raddr); - net_ipv4addr_hdrcopy(ipv4->destipaddr, &raddr); } else #endif { - net_ipv4addr_hdrcopy(ipv4->destipaddr, &conn->u.ipv4.raddr); + raddr = conn->u.ipv4.raddr; } /* The total length to send is the size of the application data @@ -142,15 +123,9 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn) dev->d_len = dev->d_sndlen + IPv4UDP_HDRLEN; - /* The IPv4 length includes the size of the IPv4 header */ - - ipv4->len[0] = (dev->d_len >> 8); - ipv4->len[1] = (dev->d_len & 0xff); - - /* Calculate IP checksum. */ - - ipv4->ipchksum = 0; - ipv4->ipchksum = ~ipv4_chksum(dev); + ipv4_build_header(IPv4BUF, dev->d_len, IP_PROTO_UDP, + &dev->d_ipaddr, &raddr, IP_TTL_DEFAULT, + NULL); #ifdef CONFIG_NET_STATISTICS g_netstats.ipv4.sent++; @@ -165,31 +140,17 @@ void udp_send(FAR struct net_driver_s *dev, FAR struct udp_conn_s *conn) { /* Get pointers to the IPv6 header and the offset UDP header */ - FAR struct ipv6_hdr_s *ipv6 = IPv6BUF; - DEBUGASSERT(IFF_IS_IPv6(dev->d_flags)); udp = UDPIPv6BUF; - /* Initialize the IPv6 header. Note that the IP length field - * does not include the IPv6 IP header length. - */ - - ipv6->vtc = 0x60; - ipv6->tcf = 0x00; - ipv6->flow = 0x00; - ipv6->proto = IP_PROTO_UDP; - ipv6->ttl = conn->ttl; - - net_ipv6addr_copy(ipv6->srcipaddr, dev->d_ipv6addr); - net_ipv6addr_copy(ipv6->destipaddr, conn->u.ipv6.raddr); - /* The IPv6 length, Includes the UDP header size but not the IPv6 * header size */ dev->d_len = dev->d_sndlen + UDP_HDRLEN; - ipv6->len[0] = (dev->d_len >> 8); - ipv6->len[1] = (dev->d_len & 0xff); + + ipv6_build_header(IPv6BUF, dev->d_len, IP_PROTO_UDP, + dev->d_ipv6addr, conn->u.ipv6.raddr, conn->ttl); /* The total length to send is the size of the application data * plus the IPv6 and UDP headers (and, eventually, the link layer diff --git a/net/utils/Kconfig b/net/utils/Kconfig index 7eeb537b02..b8d1a0484c 100644 --- a/net/utils/Kconfig +++ b/net/utils/Kconfig @@ -21,6 +21,6 @@ config NET_ARCH_CHKSUM uint16_t chksum(uint16_t sum, FAR const uint8_t *data, uint16_t len) uint16_t net_chksum(FAR uint16_t *data, uint16_t len) - uint16_t ipv4_chksum(FAR struct net_driver_s *dev) + uint16_t ipv4_chksum(FAR struct ipv4_hdr_s *ipv4) uint16_t ipv4_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto) uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev, uint8_t proto, unsigned int iplen) diff --git a/net/utils/net_ipchksum.c b/net/utils/net_ipchksum.c index af77fbeeb6..1da647f719 100644 --- a/net/utils/net_ipchksum.c +++ b/net/utils/net_ipchksum.c @@ -183,9 +183,8 @@ uint16_t ipv6_upperlayer_chksum(FAR struct net_driver_s *dev, ****************************************************************************/ #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 ipv4_hdr_s *ipv4) { - FAR struct ipv4_hdr_s *ipv4 = IPv4BUF; uint16_t iphdrlen; uint16_t sum; @@ -193,7 +192,7 @@ uint16_t ipv4_chksum(FAR struct net_driver_s *dev) iphdrlen = (ipv4->vhl & IPv4_HLMASK) << 2; - sum = chksum(0, IPBUF(0), iphdrlen); + sum = chksum(0, (FAR const uint8_t *)ipv4, iphdrlen); return (sum == 0) ? 0xffff : HTONS(sum); } #endif /* CONFIG_NET_ARCH_CHKSUM */ diff --git a/net/utils/utils.h b/net/utils/utils.h index 1cc3410f9e..67212c3660 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -260,6 +260,27 @@ void net_chksum_adjust(FAR uint16_t *chksum, FAR const uint16_t *optr, ssize_t olen, FAR const uint16_t *nptr, ssize_t nlen); +/**************************************************************************** + * Name: ipv4_chksum + * + * Description: + * Calculate the IPv4 header checksum of the packet header in d_buf. + * + * The IPv4 header checksum is the Internet checksum of the 20 bytes of + * the IPv4 header. + * + * If CONFIG_NET_ARCH_CHKSUM is defined, then this function must be + * provided by architecture-specific logic. + * + * Returned Value: + * The IPv4 header checksum of the IPv4 header in the d_buf buffer. + * + ****************************************************************************/ + +#ifdef CONFIG_NET_IPv4 +uint16_t ipv4_chksum(FAR struct ipv4_hdr_s *ipv4); +#endif + /**************************************************************************** * Name: ipv4_upperlayer_chksum *