Skip to content

Commit e854314

Browse files
Florian Grandelcarlescufi
authored andcommitted
net: l2: ieee802154: fix double address swap
As we have to provide LL addresses in big endian to userspace to be POSIX compliant and we also do not want to reserve extra space for such addresses, bff6a5c introduced a change that swaps address bytes in place in the packet before returning the packet with LL address pointers to userspace. Unfortunately a regression sneaked into the code base while doing so: The byte swapping was duplicated when using 6LoWPAN compression and the byte swapping caused decryption to fail in some cases, see #53630. This commit fixes the problem. Fixes: #53630 Signed-off-by: Florian Grandel <[email protected]>
1 parent ce31799 commit e854314

File tree

2 files changed

+18
-26
lines changed

2 files changed

+18
-26
lines changed

subsys/net/l2/ieee802154/ieee802154.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,9 @@ static inline void ieee802154_acknowledge(struct net_if *iface, struct ieee80215
9494
#define ieee802154_acknowledge(...)
9595
#endif /* CONFIG_NET_L2_IEEE802154_ACK_REPLY */
9696

97-
static inline void set_pkt_ll_addr(struct net_linkaddr *addr, bool comp,
98-
enum ieee802154_addressing_mode mode,
99-
struct ieee802154_address_field *ll)
97+
static inline void swap_and_set_pkt_ll_addr(struct net_linkaddr *addr, bool comp,
98+
enum ieee802154_addressing_mode mode,
99+
struct ieee802154_address_field *ll)
100100
{
101101
addr->type = NET_LINK_IEEE802154;
102102

@@ -127,8 +127,9 @@ static inline void set_pkt_ll_addr(struct net_linkaddr *addr, bool comp,
127127
addr->addr = NULL;
128128
}
129129

130-
/* Swap address byte order in place from little to big endian.
131-
* This is ok as the ll address field comes from the header
130+
/* The net stack expects link layer addresses to be in
131+
* big endian format for posix compliance so we must swap it.
132+
* This is ok as the L2 address field comes from the header
132133
* part of the packet buffer which will not be directly accessible
133134
* once the packet reaches the upper layers.
134135
*/
@@ -238,18 +239,22 @@ static enum net_verdict ieee802154_recv(struct net_if *iface, struct net_pkt *pk
238239

239240
ieee802154_acknowledge(iface, &mpdu);
240241

241-
net_pkt_set_ll_proto_type(pkt, ETH_P_IEEE802154);
242-
243-
set_pkt_ll_addr(net_pkt_lladdr_src(pkt), mpdu.mhr.fs->fc.pan_id_comp,
244-
mpdu.mhr.fs->fc.src_addr_mode, mpdu.mhr.src_addr);
245-
246-
set_pkt_ll_addr(net_pkt_lladdr_dst(pkt), false, mpdu.mhr.fs->fc.dst_addr_mode,
247-
mpdu.mhr.dst_addr);
248-
249242
if (!ieee802154_decipher_data_frame(iface, pkt, &mpdu)) {
250243
return NET_DROP;
251244
}
252245

246+
/* Setting L2 addresses must be done after packet authentication and internal
247+
* packet handling as it will mangle the package header to comply with upper
248+
* network layers' (POSIX) requirement to represent network addresses in big endian.
249+
*/
250+
swap_and_set_pkt_ll_addr(net_pkt_lladdr_src(pkt), mpdu.mhr.fs->fc.pan_id_comp,
251+
mpdu.mhr.fs->fc.src_addr_mode, mpdu.mhr.src_addr);
252+
253+
swap_and_set_pkt_ll_addr(net_pkt_lladdr_dst(pkt), false, mpdu.mhr.fs->fc.dst_addr_mode,
254+
mpdu.mhr.dst_addr);
255+
256+
net_pkt_set_ll_proto_type(pkt, ETH_P_IEEE802154);
257+
253258
pkt_hexdump(RX_PKT_TITLE " (with ll)", pkt, true);
254259

255260
hdr_len = (uint8_t *)mpdu.payload - net_pkt_data(pkt);

subsys/net/l2/ieee802154/ieee802154_6lo.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,6 @@ LOG_MODULE_REGISTER(net_ieee802154_6lo, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
2424

2525
enum net_verdict ieee802154_6lo_decode_pkt(struct net_if *iface, struct net_pkt *pkt)
2626
{
27-
/* Upper IP stack expects the link layer address to be in
28-
* big endian format so we must swap it here.
29-
*/
30-
if (net_pkt_lladdr_src(pkt)->addr &&
31-
net_pkt_lladdr_src(pkt)->len == IEEE802154_EXT_ADDR_LENGTH) {
32-
sys_mem_swap(net_pkt_lladdr_src(pkt)->addr, net_pkt_lladdr_src(pkt)->len);
33-
}
34-
35-
if (net_pkt_lladdr_dst(pkt)->addr &&
36-
net_pkt_lladdr_dst(pkt)->len == IEEE802154_EXT_ADDR_LENGTH) {
37-
sys_mem_swap(net_pkt_lladdr_dst(pkt)->addr, net_pkt_lladdr_dst(pkt)->len);
38-
}
39-
4027
#ifdef CONFIG_NET_L2_IEEE802154_FRAGMENT
4128
return ieee802154_6lo_reassemble(pkt);
4229
#else

0 commit comments

Comments
 (0)