Skip to content

Commit

Permalink
gcoap: ensure response address is the same as request address
Browse files Browse the repository at this point in the history
If a node has multiple addresses we must reply to a request with the
same address on which the request was received.
  • Loading branch information
benpicco committed May 10, 2022
1 parent cc8b4f5 commit e621afb
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 16 deletions.
1 change: 1 addition & 0 deletions sys/Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ endif
ifneq (,$(filter gcoap,$(USEMODULE)))
USEMODULE += nanocoap
USEMODULE += sock_async_event
USEMODULE += sock_aux_local
USEMODULE += sock_udp
USEMODULE += sock_util
USEMODULE += ztimer_msec
Expand Down
44 changes: 28 additions & 16 deletions sys/net/application_layer/gcoap/gcoap.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@
/* Internal functions */
static void *_event_loop(void *arg);
static void _on_sock_udp_evt(sock_udp_t *sock, sock_async_flags_t type, void *arg);
static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote,
static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux,
uint8_t *buf, size_t len, bool truncated);
static int _tl_init_coap_socket(gcoap_socket_t *sock, gcoap_socket_type_t type);
static ssize_t _tl_send(gcoap_socket_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote);
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux);
static ssize_t _tl_authenticate(gcoap_socket_t *sock, const sock_udp_ep_t *remote,
uint32_t timeout);
static ssize_t _well_known_core_handler(coap_pkt_t* pdu, uint8_t *buf, size_t len, void *ctx);
Expand Down Expand Up @@ -264,7 +264,7 @@ static void _on_sock_dtls_evt(sock_dtls_t *sock, sock_async_flags_t type, void *
sock_udp_ep_t ep;
sock_dtls_session_get_udp_ep(&socket.ctx_dtls_session, &ep);
/* Truncated DTLS messages would already have gotten lost at verification */
_process_coap_pdu(&socket, &ep, _listen_buf, res, false);
_process_coap_pdu(&socket, &ep, NULL, _listen_buf, res, false);
}
}

Expand Down Expand Up @@ -295,6 +295,9 @@ static void _on_sock_udp_evt(sock_udp_t *sock, sock_async_flags_t type, void *ar
void *buf_ctx = NULL;
bool truncated = false;
size_t cursor = 0;
sock_udp_aux_rx_t aux_in = {
.flags = SOCK_AUX_GET_LOCAL,
};

/* The zero-copy _buf API is not used to its full potential here -- we
* still copy out data in what is a manual version of sock_udp_recv,
Expand All @@ -307,7 +310,7 @@ static void _on_sock_udp_evt(sock_udp_t *sock, sock_async_flags_t type, void *ar
* single slice (but that may be a realistic assumption).
*/
while (true) {
ssize_t res = sock_udp_recv_buf(sock, &stackbuf, &buf_ctx, 0, &remote);
ssize_t res = sock_udp_recv_buf_aux(sock, &stackbuf, &buf_ctx, 0, &remote, &aux_in);
if (res < 0) {
DEBUG("gcoap: udp recv failure: %d\n", (int)res);
return;
Expand All @@ -322,13 +325,24 @@ static void _on_sock_udp_evt(sock_udp_t *sock, sock_async_flags_t type, void *ar
memcpy(&_listen_buf[cursor], stackbuf, res);
cursor += res;
}
gcoap_socket_t socket = { .type = GCOAP_SOCKET_TYPE_UDP, .socket.udp = sock };
_process_coap_pdu(&socket, &remote, _listen_buf, cursor, truncated);

/* make sure we reply with the same address that the request was destined for */
sock_udp_aux_tx_t aux_out = {
.flags = SOCK_AUX_SET_LOCAL,
.local = aux_in.local,
};

gcoap_socket_t socket = {
.type = GCOAP_SOCKET_TYPE_UDP,
.socket.udp = sock,
};

_process_coap_pdu(&socket, &remote, &aux_out, _listen_buf, cursor, truncated);
}
}

/* Processes and evaluates the coap pdu */
static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote,
static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux,
uint8_t *buf, size_t len, bool truncated)
{
coap_pkt_t pdu;
Expand Down Expand Up @@ -393,8 +407,7 @@ static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote,
}

if (pdu_len > 0) {
ssize_t bytes = _tl_send(sock, _listen_buf, pdu_len,
remote);
ssize_t bytes = _tl_send(sock, _listen_buf, pdu_len, remote, aux);
if (bytes <= 0) {
DEBUG("gcoap: send response failed: %d\n", (int)bytes);
}
Expand Down Expand Up @@ -454,8 +467,7 @@ static void _process_coap_pdu(gcoap_socket_t *sock, sock_udp_ep_t *remote,
* */
pdu.hdr->ver_t_tkl &= 0xf0;

ssize_t bytes = _tl_send(sock, buf,
sizeof(coap_hdr_t), remote);
ssize_t bytes = _tl_send(sock, buf, sizeof(coap_hdr_t), remote, aux);
if (bytes <= 0) {
DEBUG("gcoap: empty response failed: %d\n", (int)bytes);
}
Expand Down Expand Up @@ -492,7 +504,7 @@ static void _on_resp_timeout(void *arg) {
}

ssize_t bytes = _tl_send(&memo->socket, memo->msg.data.pdu_buf,
memo->msg.data.pdu_len, &memo->remote_ep);
memo->msg.data.pdu_len, &memo->remote_ep, NULL);
if (bytes <= 0) {
DEBUG("gcoap: sock resend failed: %d\n", (int)bytes);
_expire_request(memo);
Expand Down Expand Up @@ -978,12 +990,12 @@ static int _tl_init_coap_socket(gcoap_socket_t *sock, gcoap_socket_type_t type)
}

static ssize_t _tl_send(gcoap_socket_t *sock, const void *data, size_t len,
const sock_udp_ep_t *remote)
const sock_udp_ep_t *remote, sock_udp_aux_tx_t *aux)
{
ssize_t res = -1;
switch (sock->type) {
case GCOAP_SOCKET_TYPE_UDP:
res = sock_udp_send(sock->socket.udp, data, len, remote);
res = sock_udp_send_aux(sock->socket.udp, data, len, remote, aux);
break;
#if IS_USED(MODULE_GCOAP_DTLS)
case GCOAP_SOCKET_TYPE_DTLS:
Expand Down Expand Up @@ -1268,7 +1280,7 @@ ssize_t gcoap_req_send_tl(const uint8_t *buf, size_t len,
}

if (res == 0) {
res = _tl_send(&socket, buf, len, remote);
res = _tl_send(&socket, buf, len, remote, NULL);
}
if (res <= 0) {
if (memo != NULL) {
Expand Down Expand Up @@ -1346,7 +1358,7 @@ size_t gcoap_obs_send(const uint8_t *buf, size_t len,
_find_obs_memo_resource(&memo, resource);

if (memo) {
ssize_t bytes = _tl_send(&memo->socket, buf, len, memo->observer);
ssize_t bytes = _tl_send(&memo->socket, buf, len, memo->observer, NULL);
return (size_t)((bytes > 0) ? bytes : 0);
}
else {
Expand Down

0 comments on commit e621afb

Please sign in to comment.