net: mqtt_sn: Disable support for GWINFO messages

The MQTT-SN v1.2 [0] specification specified the GwAddr as follows:
The GwAdd field has a variable length and contains the address of a GW. Its
depends on the network over which MQTT-SN operates and is indicated in the
first octet of this field. For example, in a ZigBee network the network
address is 2-octet long.

It specifies neither the possible values for the first octet, nor the
format of the network-specific address that follows. Thus, the
specification is incomplete and this functionality unusable.

I also wasn't able to find any implementation which implements a gwinfo
message where the address length is not zero. This includes
https://github.com/eclipse-paho/paho.mqtt-sn.embedded-c .

The current implementation in Zephyr simply copies a `struct sockaddr`
into GwAddr. This is a bad idea for many reasons, the most important one
being that the format is not even specified by POSIX [1]. They only say,
which defines must exist, not what their values are. And in fact, these
even differ between Zephyr and Linux.

Thus, I think it's best to remove the implementation to prevent people from
using this, which may even lead to memory safety issues, depending on the
length of CONFIG_MQTT_SN_LIB_MAX_ADDR_SIZE. If we were to receive an
updated specification, all we'd have to do is to convert between `struct
sockaddr` and mqtt-sn addresses both ways.

[0] https://groups.oasis-open.org/higherlogic/ws/public/download/66091/MQTT-SN_spec_v1.2.pdf
[1] https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_socket.h.html

Signed-off-by: Michael Zimmermann <michael.zimmermann@sevenlab.de>
This commit is contained in:
Michael Zimmermann
2025-10-27 15:22:04 +01:00
committed by Anas Nashif
parent 53012f9cc2
commit 4759e39122
2 changed files with 11 additions and 90 deletions

View File

@@ -595,32 +595,6 @@ static void mqtt_sn_do_searchgw(struct mqtt_sn_client *client)
encode_and_send(client, &p, CONFIG_MQTT_SN_LIB_BROADCAST_RADIUS);
}
/**
* @brief Internal function to send a GWINFO message.
*
* @param client
*/
static void mqtt_sn_do_gwinfo(struct mqtt_sn_client *client)
{
struct mqtt_sn_param response = {.type = MQTT_SN_MSG_TYPE_GWINFO};
struct mqtt_sn_gateway *gw;
struct mqtt_sn_data addr;
gw = SYS_SLIST_PEEK_HEAD_CONTAINER(&client->gateway, gw, next);
if (gw == NULL || gw->addr_len == 0) {
LOG_WRN("No Gateway Address");
return;
}
response.params.gwinfo.gw_id = gw->gw_id;
addr.data = gw->addr;
addr.size = gw->addr_len;
response.params.gwinfo.gw_add = addr;
encode_and_send(client, &response, client->radius_gwinfo);
}
/**
* @brief Internal function to send a PINGREQ message.
*
@@ -1074,8 +1048,11 @@ static int process_search(struct mqtt_sn_client *client, int64_t *next_cycle)
}
if (client->ts_gwinfo != 0 && client->ts_gwinfo <= now) {
LOG_DBG("Sending GWINFO");
mqtt_sn_do_gwinfo(client);
/* The MQTT-SN specification doesn't properly specify the format
* of the address in this message.
* See https://github.com/zephyrproject-rtos/zephyr/pull/100874
*/
LOG_WRN("GwAddr is not specified properly. Ignoring SEARCHGW message");
client->ts_gwinfo = 0;
}
@@ -1559,8 +1536,12 @@ static void handle_gwinfo(struct mqtt_sn_client *client, struct mqtt_sn_param_gw
/* Extract GW info and store */
if (p->gw_add.size > 0) {
rx_addr.data = p->gw_add.data;
rx_addr.size = p->gw_add.size;
/* The MQTT-SN specification doesn't properly specify the format
* of the address in this message.
* See https://github.com/zephyrproject-rtos/zephyr/pull/100874
*/
LOG_WRN("GwAddr is not specified properly. Ignoring GWINFO message");
return;
} else {
}
gw = mqtt_sn_gw_create(p->gw_id, -1, rx_addr);

View File

@@ -15,7 +15,6 @@
LOG_MODULE_REGISTER(test);
static const struct mqtt_sn_data client_id = MQTT_SN_DATA_STRING_LITERAL("zephyr");
static const struct mqtt_sn_data client2_id = MQTT_SN_DATA_STRING_LITERAL("zephyr2");
static const uint8_t gw_id = 12;
static const struct mqtt_sn_data gw_addr = MQTT_SN_DATA_STRING_LITERAL("gw1");
@@ -356,65 +355,6 @@ static ZTEST(mqtt_sn_client, test_mqtt_sn_search_peer_direct)
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_GWINFO, "Wrong event");
}
/* Test send SEARCHGW and expect GWINFO response from another client */
static ZTEST(mqtt_sn_client, test_mqtt_sn_search_peer_indirect)
{
int err;
static uint8_t gwinfo[3 + 3];
gwinfo[0] = 3 + gw_addr.size;
gwinfo[1] = 0x02;
gwinfo[2] = gw_id;
memcpy(&gwinfo[3], gw_addr.data, 3);
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
sizeof(rx));
zassert_equal(err, 0, "unexpected error %d", err);
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
err = mqtt_sn_search(mqtt_client, 1);
zassert_equal(err, 0, "unexpected error %d", err);
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
zassert_equal(err, 0, "Timed out waiting for callback.");
assert_msg_send(1, 3, NULL);
zassert_equal(mqtt_client->state, 0, "Wrong state");
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
err = input(mqtt_client, gwinfo, sizeof(gwinfo), &gw_addr);
zassert_equal(err, 0, "unexpected error %d", err);
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
zassert_equal(evt_cb_data.called, 1, "NO event");
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_GWINFO, "Wrong event");
}
static ZTEST(mqtt_sn_client, test_mqtt_sn_respond_searchgw)
{
int err;
static uint8_t searchgw[] = {3, 0x01, 1};
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
sizeof(rx));
zassert_equal(err, 0, "unexpected error %d", err);
err = mqtt_sn_add_gw(mqtt_client, gw_id, gw_addr);
zassert_equal(err, 0, "unexpected error %d", err);
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
err = input(mqtt_client, searchgw, sizeof(searchgw), &client2_id);
zassert_equal(err, 0, "unexpected error %d", err);
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
zassert_equal(err, 0, "Timed out waiting for callback.");
zassert_equal(evt_cb_data.called, 1, "NO event");
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_SEARCHGW, "Wrong event");
assert_msg_send(1, 3 + gw_addr.size, NULL);
}
static ZTEST(mqtt_sn_client, test_mqtt_sn_connect_no_will)
{
mqtt_sn_connect_no_will(mqtt_client);