From 7a01988c64cf57e3fd17ed0c33e5f8a753cfc187 Mon Sep 17 00:00:00 2001 From: Ravi kumar Veeramally Date: Mon, 5 Jun 2017 15:58:16 +0300 Subject: [PATCH] net: 6lo: Fix source address uncompression When src and dst addresses are compressed based on context information, uncompression method should verify CID bit, SAC and DAC bits and context ID's. But it has missed some cases which resulted in invalid uncompressed IPv6 header. e.g. CID is set, SAC is 0 and DAC is 1 and context id's provided. Uncompression method assumed that src address is compressed based on context information but it is not. Signed-off-by: Ravi kumar Veeramally --- subsys/net/ip/6lo.c | 89 +++++++++--------------- tests/net/6lo/src/main.c | 24 ++++++- tests/net/ieee802154/fragment/src/main.c | 4 +- 3 files changed, 57 insertions(+), 60 deletions(-) diff --git a/subsys/net/ip/6lo.c b/subsys/net/ip/6lo.c index ab53cb9b7db..924d78aaf23 100644 --- a/subsys/net/ip/6lo.c +++ b/subsys/net/ip/6lo.c @@ -862,11 +862,6 @@ static inline u8_t uncompress_sa(struct net_pkt *pkt, struct net_ipv6_hdr *ipv6, u8_t offset) { - if (CIPHC[1] & NET_6LO_IPHC_SAC_1) { - NET_DBG("SAC_1"); - NET_DBG("SAM_00 unspecified address"); - return offset; - } NET_DBG("SAC_0"); @@ -913,16 +908,11 @@ static inline u8_t uncompress_sa_ctx(struct net_pkt *pkt, u8_t offset, struct net_6lo_context *ctx) { - if (!ctx) { - return uncompress_sa(pkt, ipv6, offset); - } + NET_DBG("SAC_1"); switch (CIPHC[1] & NET_6LO_IPHC_SAM_11) { case NET_6LO_IPHC_SAM_00: - NET_DBG("SAM_00 full src addr inlined"); - - memcpy(ipv6->src.s6_addr, &CIPHC[offset], 16); - offset += 16; + NET_DBG("SAM_00 unspecified address"); break; case NET_6LO_IPHC_SAM_01: NET_DBG("SAM_01 last 64 bits are inlined"); @@ -978,8 +968,6 @@ static inline u8_t uncompress_da_mcast(struct net_pkt *pkt, NET_DBG("Dst is multicast"); if (CIPHC[1] & NET_6LO_IPHC_DAC_1) { - /* TODO: DAM00 Unicast-Prefix-based IPv6 Multicast Addresses */ - /* Reserved DAM_01, DAM_10, DAM_11 */ NET_WARN("Unsupported DAM options"); return 0; } @@ -1033,17 +1021,12 @@ static inline u8_t uncompress_da(struct net_pkt *pkt, struct net_ipv6_hdr *ipv6, u8_t offset) { + NET_DBG("DAC_0"); + if (CIPHC[1] & NET_6LO_IPHC_M_1) { return uncompress_da_mcast(pkt, ipv6, offset); } - if (CIPHC[1] & NET_6LO_IPHC_DAC_1) { - /* Invalid case: ctx doesn't exists , but DAC is 1*/ - return 0; - } - - NET_DBG("DAC_0"); - switch (CIPHC[1] & NET_6LO_IPHC_DAM_11) { case NET_6LO_IPHC_DAM_00: NET_DBG("DAM_00 full dst addr inlined"); @@ -1087,21 +1070,12 @@ static inline u8_t uncompress_da_ctx(struct net_pkt *pkt, u8_t offset, struct net_6lo_context *ctx) { - if (!ctx) { - return uncompress_da(pkt, ipv6, offset); - } + NET_DBG("DAC_1"); if (CIPHC[1] & NET_6LO_IPHC_M_1) { return uncompress_da_mcast(pkt, ipv6, offset); } - if (!(CIPHC[1] & NET_6LO_IPHC_DAC_1)) { - /* Invalid case: ctx exists but DAC is 0. */ - return 0; - } - - NET_DBG("DAC_1"); - switch (CIPHC[1] & NET_6LO_IPHC_DAM_11) { case NET_6LO_IPHC_DAM_01: NET_DBG("DAM_01 last 64 bits are inlined"); @@ -1210,7 +1184,7 @@ static inline u8_t uncompress_nh_udp(struct net_pkt *pkt, #if defined(CONFIG_NET_6LO_CONTEXT) /* Helper function to uncompress src and dst contexts */ -static inline bool uncompress_cid(struct net_pkt *pkt, +static inline void uncompress_cid(struct net_pkt *pkt, struct net_6lo_context **src, struct net_6lo_context **dst) { @@ -1230,17 +1204,6 @@ static inline bool uncompress_cid(struct net_pkt *pkt, if (!(*dst)) { NET_DBG("Unknown dst cid %d", cid); } - - /* If CID flag set and src or dst context not available means, - * either we don't have context information or we received - * corrupted packet. - */ - if (!*src && !*dst) { - NET_ERR("Context information does not exist in cache"); - return false; - } - - return true; } #endif @@ -1259,10 +1222,7 @@ static inline bool uncompress_IPHC_header(struct net_pkt *pkt) if (CIPHC[1] & NET_6LO_IPHC_CID_1) { #if defined(CONFIG_NET_6LO_CONTEXT) - if (!uncompress_cid(pkt, &src, &dst)) { - return false; - } - + uncompress_cid(pkt, &src, &dst); offset++; #else NET_WARN("Context based uncompression not enabled"); @@ -1298,9 +1258,15 @@ static inline bool uncompress_IPHC_header(struct net_pkt *pkt) /* Uncompress Source Address */ #if defined(CONFIG_NET_6LO_CONTEXT) - offset = uncompress_sa_ctx(pkt, ipv6, offset, src); - if (!offset) { - goto fail; + if (CIPHC[1] & NET_6LO_IPHC_SAC_1) { + if (!src) { + NET_ERR("SAC is set but src context doesn't exists"); + goto fail; + } + + offset = uncompress_sa_ctx(pkt, ipv6, offset, src); + } else { + offset = uncompress_sa(pkt, ipv6, offset); } #else offset = uncompress_sa(pkt, ipv6, offset); @@ -1308,15 +1274,26 @@ static inline bool uncompress_IPHC_header(struct net_pkt *pkt) /* Uncompress Destination Address */ #if defined(CONFIG_NET_6LO_CONTEXT) - offset = uncompress_da_ctx(pkt, ipv6, offset, dst); - if (!offset) { - goto fail; + if (CIPHC[1] & NET_6LO_IPHC_DAC_1) { + if (CIPHC[1] & NET_6LO_IPHC_M_1) { + /* TODO: DAM00 Unicast-Prefix-based IPv6 Multicast + * Addresses. DAM_01, DAM_10 and DAM_11 are reserved. + */ + NET_ERR("DAC_1 and M_1 is not supported"); + goto fail; + } + + if (!dst) { + NET_ERR("DAC is set but dst context doesn't exists"); + goto fail; + } + + offset = uncompress_da_ctx(pkt, ipv6, offset, dst); + } else { + offset = uncompress_da(pkt, ipv6, offset); } #else offset = uncompress_da(pkt, ipv6, offset); - if (!offset) { - goto fail; - } #endif net_buf_add(frag, NET_IPV6H_LEN); diff --git a/tests/net/6lo/src/main.c b/tests/net/6lo/src/main.c index 66a76eb109f..835a977e4bc 100644 --- a/tests/net/6lo/src/main.c +++ b/tests/net/6lo/src/main.c @@ -456,7 +456,7 @@ static struct net_6lo_data test_data_4 = { .ipv6.len = { 0x00, 0x00 }, .ipv6.nexthdr = IPPROTO_UDP, .ipv6.hop_limit = 0xff, - .ipv6.src = src_sac1_sam00, + .ipv6.src = src_sam00, .ipv6.dst = dst_m1_dam00, .nh.udp.src_port = htons(udp_src_port_16bit), .nh.udp.dst_port = htons(udp_dst_port_16bit), @@ -795,6 +795,25 @@ static struct net_6lo_data test_data_22 = { .small = true, .iphc = true }; + +static struct net_6lo_data test_data_23 = { + .ipv6.vtc = 0x60, + .ipv6.tcflow = 0x20, + .ipv6.flow = 0x3412, + .ipv6.len = { 0x00, 0x00 }, + .ipv6.nexthdr = IPPROTO_UDP, + .ipv6.hop_limit = 0xff, + .ipv6.src = src_sam00, + .ipv6.dst = dst_dac1_dam01, + .nh.udp.src_port = htons(udp_src_port_8bit_y), + .nh.udp.dst_port = htons(udp_dst_port_8bit), + .nh.udp.len = 0x00, + .nh.udp.chksum = 0x00, + .nh_udp = true, + .nh_icmp = false, + .small = false, + .iphc = true +}; #endif static int test_6lo(struct net_6lo_data *data) @@ -856,7 +875,7 @@ static const struct { { "test_6lo_sam00_dam00", &test_data_1}, { "test_6lo_sam01_dam01", &test_data_2}, { "test_6lo_sam10_dam10", &test_data_3}, - { "test_6lo_sac1_sam00_m1_dam00", &test_data_4}, + { "test_6lo_sam00_m1_dam00", &test_data_4}, { "test_6lo_sam01_m1_dam01", &test_data_5}, { "test_6lo_sam10_m1_dam10", &test_data_6}, { "test_6lo_sam10_m1_dam10_no_udp", &test_data_7}, @@ -876,6 +895,7 @@ static const struct { { "test_6lo_sac1_sam01_m1_dam01", &test_data_20}, { "test_6lo_sac1_sam10_m1_dam10", &test_data_21}, { "test_6lo_sac1_sam11_m1_dam10", &test_data_22}, + { "test_6lo_sac0_sam00_dac1_dam01", &test_data_23}, #endif }; diff --git a/tests/net/ieee802154/fragment/src/main.c b/tests/net/ieee802154/fragment/src/main.c index 34f9d6ca0de..bf94cd447b4 100644 --- a/tests/net/ieee802154/fragment/src/main.c +++ b/tests/net/ieee802154/fragment/src/main.c @@ -337,7 +337,7 @@ static struct net_fragment_data test_data_4 = { .ipv6.len = { 0x00, 0x00 }, .ipv6.nexthdr = IPPROTO_UDP, .ipv6.hop_limit = 0xff, - .ipv6.src = src_sac1_sam00, + .ipv6.src = src_sam00, .ipv6.dst = dst_m1_dam00, .udp.src_port = htons(udp_src_port_16bit), .udp.dst_port = htons(udp_dst_port_16bit), @@ -506,7 +506,7 @@ static const struct { { "test_fragment_sam00_dam00", &test_data_1}, { "test_fragment_sam01_dam01", &test_data_2}, { "test_fragment_sam10_dam10", &test_data_3}, - { "test_fragment_sac1_sam00_m1_dam00", &test_data_4}, + { "test_fragment_sam00_m1_dam00", &test_data_4}, { "test_fragment_sam01_m1_dam01", &test_data_5}, { "test_fragment_sam10_m1_dam10", &test_data_6}, { "test_fragment_ipv6_dispatch_small", &test_data_7},