diff --git a/net/devif/ipv6_input.c b/net/devif/ipv6_input.c index e1940bf4f0..d55b0739ad 100644 --- a/net/devif/ipv6_input.c +++ b/net/devif/ipv6_input.c @@ -95,6 +95,7 @@ #include "neighbor/neighbor.h" #include "tcp/tcp.h" #include "udp/udp.h" +#include "sixlowpan/sixlowpan.h" #include "pkt/pkt.h" #include "icmpv6/icmpv6.h" diff --git a/net/sixlowpan/sixlowpan.h b/net/sixlowpan/sixlowpan.h index 62a9074acf..c9f54154b5 100644 --- a/net/sixlowpan/sixlowpan.h +++ b/net/sixlowpan/sixlowpan.h @@ -53,8 +53,9 @@ * Public Function Prototypes ****************************************************************************/ -struct socket; /* Forward reference */ -struct sockaddr; /* Forward reference */ +struct net_driver_s; /* Forward reference */ +struct socket; /* Forward reference */ +struct sockaddr; /* Forward reference */ /**************************************************************************** * Name: sixlowpan_initialize @@ -105,6 +106,33 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, size_t len); #endif +/**************************************************************************** + * Function: sixlowpan_tcp_send + * + * Description: + * TCP output comes through two different mechansims. Either from: + * + * 1. TCP socket output. For the case of TCP output to an + * IEEE802.15.4, the TCP output is caught in the socket + * send()/sendto() logic and and redirected to psock_6lowpan_tcp_send(). + * 2. TCP output from the TCP state machine. That will occur + * during TCP packet processing by the TCP state meachine. It + * is detected there when ipv6_tcp_input() returns with d_len > 0. This + * will be redirected here. + * + * Parameters: + * dev - An instance of nework device state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called with the network locked. + * + ****************************************************************************/ + +void sixlowpan_tcp_send(FAR struct net_driver_s *dev); + /**************************************************************************** * Function: psock_6lowpan_udp_send * diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index 882af91708..b89af933d8 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -91,91 +91,6 @@ * Public Functions ****************************************************************************/ -/**************************************************************************** - * Function: sixlowpan_isbroadcast - * - * Description: - * Return the address length associated with a 2-bit address mode - * - * Input parameters: - * addrmode - The address mode - * - * Returned Value: - * The address length associated with the address mode. - * - ****************************************************************************/ - -static bool sixlowpan_isbroadcast(uint8_t mode, FAR uint8_t *addr) -{ - int i = ((mode == FRAME802154_SHORTADDRMODE) ? 2 : 8); - - while (i-- > 0) - { - if (addr[i] != 0xff) - { - return false; - } - } - - return true; -} - -/**************************************************************************** - * Name: sixlowpan_set_pktattrs - * - * Description: - * Setup some packet buffer attributes - * - * Input Parameters: - * ieee - Pointer to IEEE802.15.4 MAC driver structure. - * ipv6 - Pointer to the IPv6 header to "compress" - * - * Returned Value: - * None - * - ****************************************************************************/ - -static void sixlowpan_set_pktattrs(FAR struct ieee802154_driver_s *ieee, - FAR const struct ipv6_hdr_s *ipv6) -{ - int attr = 0; - - /* Set protocol in NETWORK_ID */ - - g_pktattrs[PACKETBUF_ATTR_NETWORK_ID] = ipv6->proto; - - /* Assign values to the channel attribute (port or type + code) */ - - if (ipv6->proto == IP_PROTO_UDP) - { - FAR struct udp_hdr_s *udp = &((FAR struct ipv6udp_hdr_s *)ipv6)->udp; - - attr = udp->srcport; - if (udp->destport < attr) - { - attr = udp->destport; - } - } - else if (ipv6->proto == IP_PROTO_TCP) - { - FAR struct tcp_hdr_s *tcp = &((FAR struct ipv6tcp_hdr_s *)ipv6)->tcp; - - attr = tcp->srcport; - if (tcp->destport < attr) - { - attr = tcp->destport; - } - } - else if (ipv6->proto == IP_PROTO_ICMP6) - { - FAR struct icmpv6_iphdr_s *icmp = &((FAR struct ipv6icmp_hdr_s *)ipv6)->icmp; - - attr = icmp->type << 8 | icmp->code; - } - - g_pktattrs[PACKETBUF_ATTR_CHANNEL] = attr; -} - /**************************************************************************** * Name: sixlowpan_frame_process * @@ -691,7 +606,10 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee) if (ieee->i_dev.d_len > 0) { FAR struct ipv6_hdr_s *ipv6hdr; + FAR uint8_t *buffer; struct rimeaddr_s destmac; + size_t hdrlen; + size_t buflen; /* The IPv6 header followed by TCP or UDP headers should * lie at the beginning of d_buf since there is no link @@ -707,10 +625,46 @@ int sixlowpan_input(FAR struct ieee802154_driver_s *ieee) sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac); + /* The data payload should follow the IPv6 header plus + * the protocol header. + */ + + if (ipv6hdr->proto != IP_PROTO_TCP) + { + hdrlen = IPv6_HDRLEN + TCP_HDRLEN; + } + else if (ipv6hdr->proto != IP_PROTO_UDP) + { + hdrlen = IPv6_HDRLEN + UDP_HDRLEN; + } + else if (ipv6hdr->proto != IP_PROTO_ICMP6) + { + hdrlen = IPv6_HDRLEN + ICMPv6_HDRLEN; + } + else + { + nwarn("WARNING: Unsupported protoype: %u\n", + ipv6hdr->proto); + ret = -EPROTO; + goto drop; + } + + if (hdrlen < ieee->i_dev.d_len) + { + nwarn("WARNING: Packet to small: Have %u need >%u\n", + ieee->i_dev.d_len, hdrlen); + ret = -ENOBUFS; + goto drop; + } + /* Convert the outgoing packet into a frame list. */ - ret = sixlowpan_queue_frames(ieee, ipv6hdr, ieee->i_dev.d_buf, - ieee->i_dev.d_len, &destmac); + buffer = ieee->i_dev.d_buf + hdrlen; + buflen = ieee->i_dev.d_len - hdrlen; + + ret = sixlowpan_queue_frames(ieee, ipv6hdr, buffer, buflen, + &destmac); +drop: ieee->i_dev.d_len = 0; } } diff --git a/net/sixlowpan/sixlowpan_tcpsend.c b/net/sixlowpan/sixlowpan_tcpsend.c index ae581b150a..bc3e84f934 100644 --- a/net/sixlowpan/sixlowpan_tcpsend.c +++ b/net/sixlowpan/sixlowpan_tcpsend.c @@ -113,7 +113,7 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, conn = (FAR struct tcp_conn_s *)psock->s_conn; DEBUGASSERT(conn != NULL); -#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) +#ifdef CONFIG_NET_IPv4 /* Ignore if not IPv6 domain */ if (conn->domain != PF_INET6) @@ -196,4 +196,86 @@ ssize_t psock_6lowpan_tcp_send(FAR struct socket *psock, FAR const void *buf, return ret; } +/**************************************************************************** + * Function: sixlowpan_tcp_send + * + * Description: + * TCP output comes through two different mechansims. Either from: + * + * 1. TCP socket output. For the case of TCP output to an + * IEEE802.15.4, the TCP output is caught in the socket + * send()/sendto() logic and and redirected to psock_6lowpan_tcp_send(). + * 2. TCP output from the TCP state machine. That will occur + * during TCP packet processing by the TCP state meachine. It + * is detected there when ipv6_tcp_input() returns with d_len > 0. This + * will be redirected here. + * + * Parameters: + * dev - An instance of nework device state structure + * + * Returned Value: + * None + * + * Assumptions: + * Called with the network locked. + * + ****************************************************************************/ + +void sixlowpan_tcp_send(FAR struct net_driver_s *dev) +{ + DEBUGASSERT(dev != NULL && dev->d_len > 0); + + /* Double check */ + + if (dev != NULL && dev->d_len > 0) + { + FAR struct ipv6_hdr_s *ipv6hdr; + + /* The IPv6 header followed by a TCP headers should lie at the + * beginning of d_buf since there is no link layer protocol header + * and the TCP state machine should only response with TCP packets. + */ + + ipv6hdr = (FAR struct ipv6_hdr_s *)(dev->d_buf); + + /* The TCP data payload should follow the IPv6 header plus the + * protocol header. + */ + + if (ipv6hdr->proto != IP_PROTO_TCP) + { + nwarn("WARNING: Expected TCP protoype: %u\n", ipv6hdr->proto); + } + else + { + size_t hdrlen; + + hdrlen = IPv6_HDRLEN + TCP_HDRLEN; + if (hdrlen < dev->d_len) + { + nwarn("WARNING: Packet to small: Have %u need >%u\n", + dev->d_len, hdrlen); + } + else + { + struct rimeaddr_s destmac; + + /* Get the Rime MAC address of the destination. This assumes + * an encoding of the MAC address in the IPv6 address. + */ + + sixlowpan_rimefromip(ipv6hdr->destipaddr, &destmac); + + /* Convert the outgoing packet into a frame list. */ + + (void)sixlowpan_queue_frames( + (FAR struct ieee802154_driver_s *)dev, ipv6hdr, + dev->d_buf + hdrlen, dev->d_len - hdrlen, &destmac); + } + } + } + + dev->d_len = 0; +} + #endif /* CONFIG_NET_6LOWPAN && CONFIG_NET_TCP */