Skip to content

Ieee80215 bug fix #31908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions subsys/net/l2/ieee802154/ieee802154.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ static enum net_verdict ieee802154_recv(struct net_if *iface,
return NET_DROP;
}

if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_ACK) {
return NET_DROP;
}

if (mpdu.mhr.fs->fc.frame_type == IEEE802154_FRAME_TYPE_BEACON) {
return ieee802154_handle_beacon(iface, &mpdu,
net_pkt_ieee802154_lqi(pkt));
Expand Down
64 changes: 45 additions & 19 deletions subsys/net/l2/ieee802154/ieee802154_fragment.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ void ieee802154_fragment(struct ieee802154_fragment_ctx *ctx,
ctx->offset = ctx->processed >> 3;
}

static inline uint8_t get_datagram_type(uint8_t *ptr)
{
return ptr[0] & NET_FRAG_DISPATCH_MASK;
}

static inline uint16_t get_datagram_size(uint8_t *ptr)
{
return ((ptr[0] & 0x1F) << 8) | ptr[1];
Expand Down Expand Up @@ -344,8 +349,7 @@ static inline struct frag_cache *get_reass_cache(uint16_t size, uint16_t tag)

static inline void fragment_append(struct net_pkt *pkt, struct net_buf *frag)
{
if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
NET_6LO_DISPATCH_FRAG1) {
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
/* Always make sure first fragment is inserted first
* This will be useful for fragment_cached_pkt_len()
*/
Expand All @@ -367,8 +371,7 @@ static inline size_t fragment_cached_pkt_len(struct net_pkt *pkt)
while (frag) {
uint16_t hdr_len = NET_6LO_FRAGN_HDR_LEN;

if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
NET_6LO_DISPATCH_FRAG1) {
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
hdr_len = NET_6LO_FRAG1_HDR_LEN;
}

Expand Down Expand Up @@ -396,8 +399,7 @@ static inline size_t fragment_cached_pkt_len(struct net_pkt *pkt)

static inline uint16_t fragment_offset(struct net_buf *frag)
{
if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
NET_6LO_DISPATCH_FRAG1) {
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
return 0;
}

Expand Down Expand Up @@ -435,8 +437,7 @@ static inline void fragment_remove_headers(struct net_pkt *pkt)
while (frag) {
uint16_t hdr_len = NET_6LO_FRAGN_HDR_LEN;

if ((frag->data[0] & NET_FRAG_DISPATCH_MASK) ==
NET_6LO_DISPATCH_FRAG1) {
if (get_datagram_type(frag->data) == NET_6LO_DISPATCH_FRAG1) {
hdr_len = NET_6LO_FRAG1_HDR_LEN;
}

Expand Down Expand Up @@ -471,6 +472,11 @@ static inline void fragment_reconstruct_packet(struct net_pkt *pkt)
fragment_remove_headers(pkt);
}

static inline bool fragment_packet_valid(struct net_pkt *pkt)
{
return (get_datagram_type(pkt->buffer->data) == NET_6LO_DISPATCH_FRAG1);
}

/**
* Parse size and tag from the fragment, check if we have any cache
* related to it. If not create a new cache.
Expand All @@ -486,18 +492,28 @@ static inline enum net_verdict fragment_add_to_cache(struct net_pkt *pkt)
struct net_buf *frag;
uint16_t size;
uint16_t tag;
uint8_t type;

frag = pkt->buffer;
type = get_datagram_type(frag->data);

if ((type == NET_6LO_DISPATCH_FRAG1 &&
frag->len < NET_6LO_FRAG1_HDR_LEN) ||
(type == NET_6LO_DISPATCH_FRAGN &&
frag->len < NET_6LO_FRAGN_HDR_LEN)) {
return NET_DROP;
}

/* Parse total size of packet */
size = get_datagram_size(pkt->buffer->data);
size = get_datagram_size(frag->data);

/* Parse the datagram tag */
tag = get_datagram_tag(pkt->buffer->data +
tag = get_datagram_tag(frag->data +
NET_6LO_FRAG_DATAGRAM_SIZE_LEN);

/* If there are no fragments in the cache means this frag
* is the first one. So cache Rx pkt otherwise not.
*/
frag = pkt->buffer;
pkt->buffer = NULL;

cache = get_reass_cache(size, tag);
Expand All @@ -515,15 +531,26 @@ static inline enum net_verdict fragment_add_to_cache(struct net_pkt *pkt)
fragment_append(cache->pkt, frag);

if (fragment_cached_pkt_len(cache->pkt) == cache->size) {
/* Assign buffer back to input packet. */
pkt->buffer = cache->pkt->buffer;
cache->pkt->buffer = NULL;

fragment_reconstruct_packet(pkt);
if (!first_frag) {
/* Assign buffer back to input packet. */
pkt->buffer = cache->pkt->buffer;
cache->pkt->buffer = NULL;
} else {
/* in case pkt == cache->pkt, we don't want
* to unref it while clearing the cach.
*/
cache->pkt = NULL;
}

/* Once reassemble is done, cache is no longer needed. */
clear_reass_cache(size, tag);

if (!fragment_packet_valid(pkt)) {
NET_ERR("Invalid fragmented packet");
return NET_DROP;
}

fragment_reconstruct_packet(pkt);

if (!net_6lo_uncompress(pkt)) {
NET_ERR("Could not uncompress. Bogus packet?");
return NET_DROP;
Expand Down Expand Up @@ -556,8 +583,7 @@ enum net_verdict ieee802154_reassemble(struct net_pkt *pkt)
return NET_DROP;
}

if ((pkt->buffer->data[0] & NET_FRAG_DISPATCH_MASK) >=
NET_6LO_DISPATCH_FRAG1) {
if (get_datagram_type(pkt->buffer->data) >= NET_6LO_DISPATCH_FRAG1) {
return fragment_add_to_cache(pkt);
} else {
NET_DBG("No frag dispatch (%02x)", pkt->buffer->data[0]);
Expand Down
33 changes: 19 additions & 14 deletions subsys/net/l2/ieee802154/ieee802154_frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ struct ieee802154_fcf_seq *ieee802154_validate_fc_seq(uint8_t *buf, uint8_t **p_
return fs;
}

static inline struct ieee802154_address_field *
validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
enum ieee802154_addressing_mode mode,
bool pan_id_compression)
static inline bool validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
enum ieee802154_addressing_mode mode,
bool pan_id_compression,
struct ieee802154_address_field **addr)
{
uint8_t len = 0;

Expand All @@ -102,7 +102,8 @@ validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
buf, mode, pan_id_compression);

if (mode == IEEE802154_ADDR_MODE_NONE) {
return NULL;
*addr = NULL;
return true;
}

if (!pan_id_compression) {
Expand All @@ -117,13 +118,15 @@ validate_addr(uint8_t *buf, uint8_t **p_buf, uint8_t *length,
}

if (len > *length) {
return NULL;
return false;
}

*p_buf += len;
*length -= len;

return (struct ieee802154_address_field *)buf;
*addr = (struct ieee802154_address_field *)buf;

return true;
}

#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
Expand Down Expand Up @@ -439,13 +442,15 @@ bool ieee802154_validate_frame(uint8_t *buf, uint8_t length,
return false;
}

mpdu->mhr.dst_addr = validate_addr(p_buf, &p_buf, &length,
mpdu->mhr.fs->fc.dst_addr_mode,
false);

mpdu->mhr.src_addr = validate_addr(p_buf, &p_buf, &length,
mpdu->mhr.fs->fc.src_addr_mode,
(mpdu->mhr.fs->fc.pan_id_comp));
if (!validate_addr(p_buf, &p_buf, &length,
mpdu->mhr.fs->fc.dst_addr_mode,
false, &mpdu->mhr.dst_addr) ||
!validate_addr(p_buf, &p_buf, &length,
mpdu->mhr.fs->fc.src_addr_mode,
(mpdu->mhr.fs->fc.pan_id_comp),
&mpdu->mhr.src_addr)) {
return false;
}

#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
if (mpdu->mhr.fs->fc.security_enabled) {
Expand Down