From e64b48183c29db48da5ce55a32f5b7524981b3a4 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Fri, 17 Jan 2025 15:54:30 +0100 Subject: [PATCH] net: coap: Fix response matching algorithm The algorithm for matching request with response was incorrect, which could lead to false matches (for example if request had a token, and piggybacked reply had no token but matching message ID only, that would still be counted as a match). This commit fixes it. The request/reply matching is implemented based on RFC now, with separate conditions for piggybacked/separate responses. Signed-off-by: Robert Lubos --- subsys/net/lib/coap/coap.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/subsys/net/lib/coap/coap.c b/subsys/net/lib/coap/coap.c index 70f2610adf0227..93852fd29298ef 100644 --- a/subsys/net/lib/coap/coap.c +++ b/subsys/net/lib/coap/coap.c @@ -1808,6 +1808,8 @@ struct coap_reply *coap_response_received( { struct coap_reply *r; uint8_t token[COAP_TOKEN_MAX_LEN]; + bool piggybacked = false; + uint8_t type; uint16_t id; uint8_t tkl; size_t i; @@ -1817,9 +1819,14 @@ struct coap_reply *coap_response_received( return NULL; } + type = coap_header_get_type(response); id = coap_header_get_id(response); tkl = coap_header_get_token(response, token); + if (type == COAP_TYPE_ACK || type == COAP_TYPE_RESET) { + piggybacked = true; + } + for (i = 0, r = replies; i < len; i++, r++) { int age; @@ -1827,13 +1834,29 @@ struct coap_reply *coap_response_received( continue; } - /* Piggybacked must match id when token is empty */ - if ((r->id != id) && (tkl == 0U)) { - continue; - } + if (piggybacked) { + /* In a piggybacked response, the Message ID of the + * Confirmable request and the Acknowledgment MUST + * match, and the tokens of the response and original + * request MUST match. + */ + if ((r->id != id || (r->tkl != tkl))) { + continue; + } - if (tkl > 0 && memcmp(r->token, token, tkl)) { - continue; + if (r->tkl > 0) { + if (memcmp(r->token, token, r->tkl) != 0) { + continue; + } + } + } else { + /* In a separate response, just the tokens of the + * response and original request MUST match. + */ + if ((r->tkl == 0) || (r->tkl != tkl) || + (memcmp(r->token, token, r->tkl) != 0)) { + continue; + } } age = coap_get_option_int(response, COAP_OPTION_OBSERVE);