net: lib: coap: Handle truncated messages in CoAP server
If the CoAP server receives a message that doesn't fit into the receive buffer, we should stop processing the message and respond to the client with 4.13 "Request Entity too large". Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
This commit is contained in:
parent
ee326138ca
commit
81b87ac35b
2 changed files with 51 additions and 4 deletions
|
@ -247,6 +247,14 @@ config COAP_SERVER_PENDING_ALLOCATOR_STATIC_BLOCKS
|
|||
help
|
||||
The number of data blocks to reserve for pending messages to retransmit.
|
||||
|
||||
config COAP_SERVER_TRUNCATE_MSGS
|
||||
bool "Handle truncated messages"
|
||||
default y
|
||||
help
|
||||
Include ZSOCK_MSG_TRUNC in flags passed to zsock_recvfrom() to
|
||||
receive network stack notifications about block truncation.
|
||||
Otherwise it happens silently.
|
||||
|
||||
config COAP_SERVER_SHELL
|
||||
bool "CoAP service shell commands"
|
||||
depends on SHELL
|
||||
|
|
|
@ -135,10 +135,13 @@ static int coap_server_process(int sock_fd)
|
|||
uint8_t type;
|
||||
ssize_t received;
|
||||
int ret;
|
||||
int flags = ZSOCK_MSG_DONTWAIT;
|
||||
|
||||
received = zsock_recvfrom(sock_fd, buf, sizeof(buf), ZSOCK_MSG_DONTWAIT, &client_addr,
|
||||
&client_addr_len);
|
||||
__ASSERT_NO_MSG(received <= sizeof(buf));
|
||||
if (IS_ENABLED(CONFIG_COAP_SERVER_TRUNCATE_MSGS)) {
|
||||
flags |= ZSOCK_MSG_TRUNC;
|
||||
}
|
||||
|
||||
received = zsock_recvfrom(sock_fd, buf, sizeof(buf), flags, &client_addr, &client_addr_len);
|
||||
|
||||
if (received < 0) {
|
||||
if (errno == EWOULDBLOCK) {
|
||||
|
@ -149,7 +152,7 @@ static int coap_server_process(int sock_fd)
|
|||
return -errno;
|
||||
}
|
||||
|
||||
ret = coap_packet_parse(&request, buf, received, options, opt_num);
|
||||
ret = coap_packet_parse(&request, buf, MIN(received, sizeof(buf)), options, opt_num);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed To parse coap message (%d)", ret);
|
||||
return ret;
|
||||
|
@ -170,6 +173,42 @@ static int coap_server_process(int sock_fd)
|
|||
|
||||
type = coap_header_get_type(&request);
|
||||
|
||||
if (received > sizeof(buf)) {
|
||||
/* The message was truncated and can't be processed further */
|
||||
struct coap_packet response;
|
||||
uint8_t token[COAP_TOKEN_MAX_LEN];
|
||||
uint8_t tkl = coap_header_get_token(&request, token);
|
||||
uint16_t id = coap_header_get_id(&request);
|
||||
|
||||
if (type == COAP_TYPE_CON) {
|
||||
type = COAP_TYPE_ACK;
|
||||
} else {
|
||||
type = COAP_TYPE_NON_CON;
|
||||
}
|
||||
|
||||
ret = coap_packet_init(&response, buf, sizeof(buf), COAP_VERSION_1, type, tkl,
|
||||
token, COAP_RESPONSE_CODE_REQUEST_TOO_LARGE, id);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to init response (%d)", ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = coap_append_option_int(&response, COAP_OPTION_SIZE1,
|
||||
CONFIG_COAP_SERVER_MESSAGE_SIZE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to add SIZE1 option (%d)", ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ret = coap_service_send(service, &response, &client_addr, client_addr_len, NULL);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to reply \"Request Entity Too Large\" (%d)", ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
pending = coap_pending_received(&request, service->data->pending, MAX_PENDINGS);
|
||||
if (pending) {
|
||||
uint8_t token[COAP_TOKEN_MAX_LEN];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue