net: l2: ieee802154: fix short/ext address endianness

This changes fixes several bugs and inconsistencies in the IEEE 802.15.4
L2 implementation. These bugs were revealed while documenting intended
endianness of driver, IP, socket and L2 attributes (see previous
changes).

Signed-off-by: Florian Grandel <jerico.dev@gmail.com>
This commit is contained in:
Florian Grandel 2022-10-01 10:41:38 +02:00 committed by Carles Cufí
parent b951f062f5
commit bff6a5cce5
5 changed files with 59 additions and 25 deletions

View File

@ -124,6 +124,15 @@ static inline void set_pkt_ll_addr(struct net_linkaddr *addr, bool comp,
addr->len = 0U;
addr->addr = NULL;
}
/* Swap address byte order in place from little to big endian.
* This is ok as the ll address field comes from the header
* part of the packet buffer which will not be directly accessible
* once the packet reaches the upper layers.
*/
if (addr->len > 0) {
sys_mem_swap(addr->addr, addr->len);
}
}
/**
@ -163,7 +172,7 @@ static bool ieeee802154_check_dst_addr(struct net_if *iface, struct ieee802154_m
* address.
*/
if (!(dst_plain->addr.short_addr == IEEE802154_BROADCAST_ADDRESS ||
dst_plain->addr.short_addr == ctx->short_addr)) {
dst_plain->addr.short_addr == sys_cpu_to_le16(ctx->short_addr))) {
LOG_DBG("Frame dst address (short) does not match!");
return false;
}

View File

@ -249,6 +249,7 @@ static inline bool validate_mac_command_cfi_to_mhr(struct ieee802154_mhr *mhr, u
/* This should be set only when comp == 0 */
if (dst_brdcst_chk) {
/* broadcast address is symmetric so no need to swap byte order */
if (mhr->dst_addr->plain.addr.short_addr != IEEE802154_BROADCAST_ADDRESS) {
return false;
}
@ -535,7 +536,7 @@ static inline enum ieee802154_addressing_mode get_dst_addr_mode(struct net_linka
if (dst->len == IEEE802154_SHORT_ADDR_LENGTH) {
uint16_t short_addr = ntohs(*(uint16_t *)(dst->addr));
*broadcast = (short_addr == 0xffff);
*broadcast = (short_addr == IEEE802154_BROADCAST_ADDRESS);
return IEEE802154_ADDR_MODE_SHORT;
} else {
*broadcast = false;
@ -674,6 +675,20 @@ bool ieee802154_create_data_frame(struct ieee802154_context *ctx, struct net_lin
params.pan_id = ctx->pan_id;
if (src->addr && src->len == IEEE802154_SHORT_ADDR_LENGTH) {
params.short_addr = ntohs(*(uint16_t *)(src->addr));
if (ctx->short_addr != params.short_addr) {
return false;
}
} else {
if (src->len != IEEE802154_EXT_ADDR_LENGTH) {
return false;
}
uint8_t ext_addr_le[IEEE802154_EXT_ADDR_LENGTH];
sys_memcpy_swap(ext_addr_le, src->addr, IEEE802154_EXT_ADDR_LENGTH);
if (memcmp(ctx->ext_addr, ext_addr_le, src->len)) {
return false;
}
}
broadcast = data_addr_to_fs_settings(dst, fs, &params);
@ -767,7 +782,7 @@ static inline bool cfi_to_fs_settings(enum ieee802154_cfi cfi, struct ieee802154
break;
case IEEE802154_CFI_DATA_REQUEST:
fs->fc.ar = 1U;
/* TODO: src/dst addr mode: see 5.3.4 */
/* TODO: src/dst addr mode: see section 7.3.4 */
break;
case IEEE802154_CFI_ORPHAN_NOTIFICATION:
@ -782,7 +797,7 @@ static inline bool cfi_to_fs_settings(enum ieee802154_cfi cfi, struct ieee802154
break;
case IEEE802154_CFI_COORDINATOR_REALIGNEMENT:
fs->fc.src_addr_mode = IEEE802154_ADDR_MODE_EXTENDED;
/* Todo: ar and dst addr mode: see 5.3.8 */
/* TODO: ar and dst addr mode: see section 7.3.8 */
break;
case IEEE802154_CFI_GTS_REQUEST:
@ -927,9 +942,11 @@ bool ieee802154_decipher_data_frame(struct net_if *iface, struct net_pkt *pkt,
uint8_t tag_size = level_2_tag_size[level];
uint8_t hdr_len = (uint8_t *)mpdu->payload - net_pkt_data(pkt);
uint8_t payload_len = net_pkt_get_len(pkt) - hdr_len - tag_size;
uint8_t ext_addr_le[IEEE802154_EXT_ADDR_LENGTH];
sys_memcpy_swap(ext_addr_le, net_pkt_lladdr_src(pkt)->addr, IEEE802154_EXT_ADDR_LENGTH);
if (!ieee802154_decrypt_auth(&ctx->sec_ctx, net_pkt_data(pkt), hdr_len, payload_len,
tag_size, net_pkt_lladdr_src(pkt)->addr,
tag_size, ext_addr_le,
sys_le32_to_cpu(mpdu->mhr.aux_sec->frame_counter))) {
NET_ERR("Could not decipher the frame");
return false;

View File

@ -46,7 +46,7 @@ enum net_verdict ieee802154_handle_beacon(struct net_if *iface,
if (mpdu->mhr.fs->fc.src_addr_mode == IEEE802154_ADDR_MODE_SHORT) {
ctx->scan_ctx->len = IEEE802154_SHORT_ADDR_LENGTH;
ctx->scan_ctx->short_addr =
mpdu->mhr.src_addr->plain.addr.short_addr;
sys_le16_to_cpu(mpdu->mhr.src_addr->plain.addr.short_addr);
} else {
ctx->scan_ctx->len = IEEE802154_EXT_ADDR_LENGTH;
sys_memcpy_swap(ctx->scan_ctx->addr,
@ -320,7 +320,9 @@ static int ieee802154_disassociate(uint32_t mgmt_request, struct net_if *iface,
if (params.dst.len == IEEE802154_SHORT_ADDR_LENGTH) {
params.dst.short_addr = ctx->coord.short_addr;
} else {
params.dst.ext_addr = ctx->coord.ext_addr;
params.dst.len = IEEE802154_EXT_ADDR_LENGTH;
sys_memcpy_swap(params.dst.ext_addr, ctx->coord_ext_addr,
IEEE802154_EXT_ADDR_LENGTH);
}
params.pan_id = ctx->pan_id;
@ -413,8 +415,11 @@ static int ieee802154_set_parameters(uint32_t mgmt_request,
return -EINVAL;
}
if (memcmp(ctx->ext_addr, data, IEEE802154_EXT_ADDR_LENGTH)) {
memcpy(ctx->ext_addr, data, IEEE802154_EXT_ADDR_LENGTH);
uint8_t ext_addr_le[IEEE802154_EXT_ADDR_LENGTH];
sys_memcpy_swap(ext_addr_le, data, IEEE802154_EXT_ADDR_LENGTH);
if (memcmp(ctx->ext_addr, ext_addr_le, IEEE802154_EXT_ADDR_LENGTH)) {
memcpy(ctx->ext_addr, ext_addr_le, IEEE802154_EXT_ADDR_LENGTH);
ieee802154_filter_ieee_addr(iface, ctx->ext_addr);
}
} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_SHORT_ADDR) {
@ -472,7 +477,7 @@ static int ieee802154_get_parameters(uint32_t mgmt_request,
return -EINVAL;
}
memcpy(data, ctx->ext_addr, IEEE802154_EXT_ADDR_LENGTH);
sys_memcpy_swap(data, ctx->ext_addr, IEEE802154_EXT_ADDR_LENGTH);
} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_SHORT_ADDR) {
*value = ctx->short_addr;
} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_TX_POWER) {

View File

@ -22,7 +22,7 @@ LOG_MODULE_REGISTER(net_ieee802154_shell, CONFIG_NET_L2_IEEE802154_LOG_LEVEL);
#include "ieee802154_frame.h"
#define MAX_EXT_ADDR_STR_LEN sizeof("xx:xx:xx:xx:xx:xx:xx:xx")
#define EXT_ADDR_STR_LEN sizeof("xx:xx:xx:xx:xx:xx:xx:xx")
struct ieee802154_req_params params;
static struct net_mgmt_event_callback scan_cb;
@ -76,7 +76,7 @@ static int cmd_ieee802154_associate(const struct shell *shell,
size_t argc, char *argv[])
{
struct net_if *iface = net_if_get_ieee802154();
char ext_addr[MAX_EXT_ADDR_STR_LEN];
char ext_addr[EXT_ADDR_STR_LEN];
if (argc < 3) {
shell_help(shell);
@ -90,9 +90,9 @@ static int cmd_ieee802154_associate(const struct shell *shell,
}
params.pan_id = atoi(argv[1]);
strncpy(ext_addr, argv[2], MAX_EXT_ADDR_STR_LEN - 1);
strncpy(ext_addr, argv[2], EXT_ADDR_STR_LEN - 1);
if (strlen(ext_addr) == MAX_EXT_ADDR_STR_LEN) {
if (strlen(ext_addr) == EXT_ADDR_STR_LEN) {
parse_extended_address(ext_addr, params.addr);
params.len = IEEE802154_EXT_ADDR_LENGTH;
} else {
@ -182,7 +182,7 @@ static inline char *print_coordinator_address(char *buf, int buf_len)
pos += snprintk(buf + pos, buf_len - pos, "(extended) ");
for (i = IEEE802154_EXT_ADDR_LENGTH - 1; i > -1; i--) {
for (i = 0; i < IEEE802154_EXT_ADDR_LENGTH; i++) {
pos += snprintk(buf + pos, buf_len - pos,
"%02X:", params.addr[i]);
}
@ -421,9 +421,9 @@ static int cmd_ieee802154_set_ext_addr(const struct shell *shell,
return -ENOEXEC;
}
if (strlen(argv[1]) != MAX_EXT_ADDR_STR_LEN) {
if (strlen(argv[1]) != EXT_ADDR_STR_LEN) {
shell_fprintf(shell, SHELL_INFO,
"%zd characters needed\n", MAX_EXT_ADDR_STR_LEN);
"%zd characters needed\n", EXT_ADDR_STR_LEN);
return -ENOEXEC;
}
@ -461,16 +461,16 @@ static int cmd_ieee802154_get_ext_addr(const struct shell *shell,
"Could not get extended address\n");
return -ENOEXEC;
} else {
static char ext_addr[MAX_EXT_ADDR_STR_LEN];
int i, j;
static char ext_addr[EXT_ADDR_STR_LEN];
int i, pos = 0;
for (j = 0, i = IEEE802154_EXT_ADDR_LENGTH - 1; i > -1; i--) {
snprintf(&ext_addr[j], 4, "%02X:", addr[i]);
j += 3;
for (i = 0; i < IEEE802154_EXT_ADDR_LENGTH; i++) {
pos += snprintk(ext_addr + pos,
IEEE802154_EXT_ADDR_LENGTH - pos,
"%02X:", addr[i]);
}
ext_addr[MAX_EXT_ADDR_STR_LEN - 1] = '\0';
ext_addr[EXT_ADDR_STR_LEN - 1] = '\0';
shell_fprintf(shell, SHELL_NORMAL,
"Extended address: %s\n", ext_addr);

View File

@ -264,7 +264,10 @@ static bool test_dgram_packet_sending(struct sockaddr_ll *pkt_sll, uint32_t secu
goto release_frag;
}
net_pkt_lladdr_src(current_pkt)->addr = ctx->ext_addr;
uint8_t lladdr_be[IEEE802154_EXT_ADDR_LENGTH];
sys_memcpy_swap(lladdr_be, ctx->ext_addr, IEEE802154_EXT_ADDR_LENGTH);
net_pkt_lladdr_src(current_pkt)->addr = lladdr_be;
net_pkt_lladdr_src(current_pkt)->len = IEEE802154_MAX_ADDR_LENGTH;
if (!ieee802154_decipher_data_frame(iface, current_pkt, &mpdu)) {
NET_ERR("*** Cannot decipher/authenticate packet\n");