From 2dab490cee0d2c175c0eef354b1964d2e147ed64 Mon Sep 17 00:00:00 2001 From: Gregory Nutt <gnutt@nuttx.org> Date: Fri, 13 Oct 2017 13:31:53 -0600 Subject: [PATCH] 6LoWPAN: Fix a whole in the logic of the previous commit. It turns out that g_uncomp_hdrlen has other usages so it cannot be modified as I was doing. Instead, I needed to add a separate localt variable, protosize, to keep track of the two usages of g_uncomp_hdrlen. --- net/sixlowpan/sixlowpan_input.c | 103 ++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 37 deletions(-) diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index ed27d34a04..9890c8a547 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -151,10 +151,9 @@ static uint8_t g_bitbucket[UNCOMP_MAXHDR]; ****************************************************************************/ static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr, - FAR uint8_t *bptr, bool proto) + FAR uint8_t *bptr) { FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; - uint16_t protosize; /* Put uncompressed IPv6 header in d_buf. */ @@ -165,54 +164,75 @@ static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr, g_frame_hdrlen += IPv6_HDRLEN; g_uncomp_hdrlen += IPv6_HDRLEN; +} - /* Does a protocol header follow the IPv6 header? */ +/**************************************************************************** + * Name: sixlowpan_uncompress_ipv6proto + * + * Description: + * Copy the protocol header following the IPv4 header + * + * Input Parameters: + * fptr - Pointer to the beginning of the frame under construction + * bptr - Output goes here. Normally this is a known offset into d_buf, + * may be redirected to g_bitbucket on the case of FRAGN frames. + * proto - True: Copy the protocol header following the IPv6 header too. + * + * Returned Value: + * The size of the protocol header that was copied. + * + ****************************************************************************/ - if (proto) - { - /* Yes.. Copy the following protocol header. */ +static uint16_t sixlowpan_uncompress_ipv6proto(FAR uint8_t *fptr, + FAR uint8_t *bptr) +{ + FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr; + uint16_t protosize = 0; - switch (ipv6->proto) - { + /* Copy the following protocol header. */ + + switch (ipv6->proto) + { #ifdef CONFIG_NET_TCP - case IP_PROTO_TCP: - { - FAR struct tcp_hdr_s *tcp = - (FAR struct tcp_hdr_s *)(fptr + g_frame_hdrlen); + case IP_PROTO_TCP: + { + FAR struct tcp_hdr_s *tcp = + (FAR struct tcp_hdr_s *)(fptr + g_frame_hdrlen); - /* The TCP header length is encoded in the top 4 bits of the - * tcpoffset field (in units of 32-bit words). - */ + /* The TCP header length is encoded in the top 4 bits of the + * tcpoffset field (in units of 32-bit words). + */ - protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2; - } - break; + protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2; + } + break; #endif #ifdef CONFIG_NET_UDP - case IP_PROTO_UDP: - protosize = sizeof(struct udp_hdr_s); - break; + case IP_PROTO_UDP: + protosize = sizeof(struct udp_hdr_s); + break; #endif #ifdef CONFIG_NET_ICMPv6 - case IP_PROTO_ICMP6: - protosize = sizeof(struct icmpv6_hdr_s); - break; + case IP_PROTO_ICMP6: + protosize = sizeof(struct icmpv6_hdr_s); + break; #endif - default: - nwarn("WARNING: Unrecognized proto: %u\n", ipv6->proto); - return; - } + default: + nwarn("WARNING: Unrecognized proto: %u\n", ipv6->proto); + return 0; + } - /* Copy the protocol header. */ + /* Copy the protocol header. */ - memcpy((FAR uint8_t *)ipv6 + g_uncomp_hdrlen, fptr + g_frame_hdrlen, - protosize); + memcpy((FAR uint8_t *)ipv6 + g_uncomp_hdrlen, fptr + g_frame_hdrlen, + protosize); - g_frame_hdrlen += protosize; - } + g_frame_hdrlen += protosize; + g_uncomp_hdrlen += protosize; + return protosize; } /**************************************************************************** @@ -266,6 +286,7 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio, uint16_t paysize; /* Size of the data payload */ uint16_t fragtag = 0; /* Tag of the fragment */ uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */ + uint8_t protosize = 0; /* Length of the protocal header (treated like payload) */ bool isfrag = false; /* true: Frame is a fragment */ bool isfrag1 = false; /* true: Frame is the first fragement of the series */ int reqsize; /* Required buffer size */ @@ -447,11 +468,19 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio, { ninfo("IPv6 Dispatch\n"); - /* NOTE: A protocol header will follow only on a non-fragmented - * packet or on the first fragment of a fragmented packet. + /* Uncompress the IPv6 header */ + + sixlowpan_uncompress_ipv6hdr(fptr, bptr); + + /* A protocol header will follow the IPv6 header only on a non- + * fragmented packet or on the first fragment of a fragmented + * packet. */ - sixlowpan_uncompress_ipv6hdr(fptr, bptr, !isfrag || isfrag1); + if (!isfrag || isfrag1) + { + protosize = sixlowpan_uncompress_ipv6proto(fptr, bptr); + } } else { @@ -470,7 +499,7 @@ static int sixlowpan_frame_process(FAR struct radio_driver_s *radio, * begin placing the data payload. */ - reass->rb_boffset = g_uncomp_hdrlen; + reass->rb_boffset = g_uncomp_hdrlen - protosize; } /* No.. is this a subsequent fragment in the same sequence? */ -- GitLab