Skip to content

Commit

Permalink
Update message prevalidation API
Browse files Browse the repository at this point in the history
-Change API to use socket listen port instead of service ID
-Add new API to find connection handler based on socket port
-Add source interface ID to callback API
-Reorder callback parameters
  • Loading branch information
Arto Kinnunen committed Dec 28, 2018
1 parent 46f86d4 commit 587e8de
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 78 deletions.
21 changes: 11 additions & 10 deletions coap-service/coap_service_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,20 @@ typedef int coap_service_security_done_cb(int8_t service_id, uint8_t address[sta
*
* Message prevalidation callback function type used in method coap_service_msg_prevalidate_callback_set.
*
* \param interface_id Application interface ID.
* \param source_address Sender address.
* \param source_port Sender port.
* \param local_address Local address.
* \param local_port Local port.
* \param request_uri CoAP URI, NUL terminated.
* \param local_interface_id Local interface ID, message arrived to this interface.
* \param local_address Local address, message arrived to this address.
* \param local_port Local port, message arrived to this port.
* \param recv_interface_id Interface ID where message was received.
* \param source_address Sender address.
* \param source_port Sender port.
* \param coap_uri CoAP URI, NUL terminated.
*
* \return <0 in case of errors,
* 0 if message is valid to process further,
* >0 if message should be dropped.
*/

typedef int coap_service_msg_prevalidate_cb(int8_t interface_id, uint8_t source_address[static 16], uint16_t source_port, uint8_t local_address[static 16], uint16_t local_port, char *request_uri);
typedef int coap_service_msg_prevalidate_cb(int8_t local_interface_id, uint8_t local_address[static 16], uint16_t local_port, int8_t recv_interface_id, uint8_t source_address[static 16], uint16_t source_port, char *coap_uri);

/**
* \brief Initialise server instance.
Expand Down Expand Up @@ -400,13 +401,13 @@ extern int8_t coap_service_blockwise_size_set(int8_t service_id, uint16_t size);
*
* CoAP service will call this function to allow application prevalidate incoming CoAP message before passing it to application.
*
* \param service_id Id number of the current service.
* \param msg_prevalidate_cb Callback to be called to validate incoming message before pprocessing it.
* \param listen_port Socket port where to set callback.
* \param msg_prevalidate_cb Callback to be called to validate incoming message before processing it. Use NULL to clear callback usage.
*
* \return -1 For failure
* 0 For success
*/
extern int8_t coap_service_msg_prevalidate_callback_set(int8_t service_id, coap_service_msg_prevalidate_cb *msg_prevalidate_cb);
extern int8_t coap_service_msg_prevalidate_callback_set(uint16_t listen_port, coap_service_msg_prevalidate_cb *msg_prevalidate_cb);

#ifdef __cplusplus
}
Expand Down
21 changes: 17 additions & 4 deletions source/coap_connection_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef struct internal_socket_s {

int16_t data_len;
uint8_t *data;
int8_t recv_if_id; // interface ID where data is coming from

int8_t socket; //positive value = socket id, negative value virtual socket id
bool real_socket;
Expand Down Expand Up @@ -549,6 +550,7 @@ static int timer_status(int8_t timer_id)
static int read_data(socket_callback_t *sckt_data, internal_socket_t *sock, ns_address_t *src_address, uint8_t dst_address[static 16])
{
sock->data_len = 0;
sock->recv_if_id = -1;
if (sckt_data->event_type == SOCKET_DATA && sckt_data->d_len > 0) {
uint8_t ancillary_databuffer[NS_CMSG_SPACE(sizeof(ns_in6_pktinfo_t))];
ns_iovec_t msg_iov;
Expand Down Expand Up @@ -593,6 +595,7 @@ static int read_data(socket_callback_t *sckt_data, internal_socket_t *sock, ns_a
}
if (pkt) {
memcpy(dst_address, pkt->ipi6_addr, 16);
sock->recv_if_id = pkt->ipi6_ifindex;
} else {
goto return_failure;
}
Expand Down Expand Up @@ -694,7 +697,7 @@ static void secure_recv_sckt_msg(void *cb_res)
ns_dyn_mem_free(data);
} else {
if (sock->parent->_recv_cb) {
sock->parent->_recv_cb(sock->socket, src_address.address, src_address.identifier, dst_address, data, len);
sock->parent->_recv_cb(sock->socket, sock->recv_if_id, src_address.address, src_address.identifier, dst_address, data, len);
}
ns_dyn_mem_free(data);
}
Expand All @@ -713,7 +716,7 @@ static void recv_sckt_msg(void *cb_res)

if (sock && read_data(sckt_data, sock, &src_address, dst_address) == 0) {
if (sock->parent && sock->parent->_recv_cb) {
sock->parent->_recv_cb(sock->socket, src_address.address, src_address.identifier, dst_address, sock->data, sock->data_len);
sock->parent->_recv_cb(sock->socket, sock->recv_if_id, src_address.address, src_address.identifier, dst_address, sock->data, sock->data_len);
}
ns_dyn_mem_free(sock->data);
sock->data = NULL;
Expand Down Expand Up @@ -802,7 +805,7 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
return 0;
} else {
if (sock->parent->_recv_cb) {
sock->parent->_recv_cb(sock->socket, address, port, ns_in6addr_any, data, len);
sock->parent->_recv_cb(sock->socket, sock->recv_if_id, address, port, ns_in6addr_any, data, len);
}
ns_dyn_mem_free(data);
data = NULL;
Expand All @@ -813,7 +816,7 @@ int coap_connection_handler_virtual_recv(coap_conn_handler_t *handler, uint8_t a
} else {
/* unsecure*/
if (sock->parent->_recv_cb) {
sock->parent->_recv_cb(sock->socket, address, port, ns_in6addr_any, sock->data, sock->data_len);
sock->parent->_recv_cb(sock->socket, sock->recv_if_id, address, port, ns_in6addr_any, sock->data, sock->data_len);
}
if (sock->data) {
ns_dyn_mem_free(sock->data);
Expand Down Expand Up @@ -1034,6 +1037,16 @@ int coap_connection_handler_msg_prevalidate_callback_set(coap_conn_handler_t *ha
return 0;
}

coap_conn_handler_t *coap_connection_handler_find_by_socket_port(uint16_t listen_port)
{
ns_list_foreach(internal_socket_t, cur_ptr, &socket_list) {
if (cur_ptr->listen_port == listen_port) {
return cur_ptr->parent;
}
}
return NULL;
}

cch_func_cb *coap_connection_handler_msg_prevalidate_callback_get(coap_conn_handler_t *handler, uint16_t *listen_socket_port)
{
if (!handler || !listen_socket_port) {
Expand Down
6 changes: 3 additions & 3 deletions source/coap_message_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,8 @@ coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr,
return transaction_find_by_address(address_ptr, port);
}

int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, const uint8_t source_addr_ptr[static 16], uint16_t port, const uint8_t dst_addr_ptr[static 16],
uint8_t *data_ptr, uint16_t data_len, int16_t (msg_process_callback)(int8_t, sn_coap_hdr_s *, coap_transaction_t *, const uint8_t *))
int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, int8_t recv_if_id, const uint8_t source_addr_ptr[static 16], uint16_t port, const uint8_t dst_addr_ptr[static 16],
uint8_t *data_ptr, uint16_t data_len, int16_t (msg_process_callback)(int8_t, int8_t, sn_coap_hdr_s *, coap_transaction_t *, const uint8_t *))
{
sn_nsdl_addr_s src_addr;
sn_coap_hdr_s *coap_message;
Expand Down Expand Up @@ -345,7 +345,7 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
transaction_ptr->token_len = coap_message->token_len;
}
if (msg_process_callback(socket_id, coap_message, transaction_ptr, dst_addr_ptr) < 0) {
if (msg_process_callback(socket_id, recv_if_id, coap_message, transaction_ptr, dst_addr_ptr) < 0) {
// negative return value = message ignored -> delete transaction
transaction_delete(transaction_ptr);
}
Expand Down
81 changes: 48 additions & 33 deletions source/coap_service_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "coap_message_handler.h"
#include "mbed-coap/sn_coap_protocol.h"

static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr, const uint8_t * local_addr);
static int16_t coap_msg_process_callback(int8_t socket_id, int8_t recv_if_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr, const uint8_t * local_addr);

typedef struct uri_registration {
char *uri_ptr;
Expand Down Expand Up @@ -70,6 +70,13 @@ static uint32_t coap_ticks = 1;

#define COAP_TICK_TIMER 0xf1

#define TRACE_DEEP
#ifdef TRACE_DEEP
#define tr_deep tr_debug
#else
#define tr_deep(...)
#endif

static uri_registration_t *uri_registration_find(coap_service_t *this, const void *uri_ptr, uint16_t uri_len)
{
ns_list_foreach(uri_registration_t, cur_ptr, &this->uri_list) {
Expand Down Expand Up @@ -165,7 +172,7 @@ static uint8_t coap_tx_function(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_ad
return 0;
}

tr_debug("Service %d, CoAP TX Function - mid: %d", transaction_ptr->service_id, common_read_16_bit(data_ptr + 2));
tr_debug("Service %d, CoAP TX - mid: %d", transaction_ptr->service_id, common_read_16_bit(data_ptr + 2));

this = service_find(transaction_ptr->service_id);
if (!this) {
Expand Down Expand Up @@ -211,17 +218,44 @@ static void service_event_handler(arm_event_s *event)
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
}

static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr, const uint8_t * local_addr)
static int16_t coap_msg_process_callback(int8_t socket_id, int8_t recv_if_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr, const uint8_t * local_addr)
{
coap_service_t *this;
coap_service_msg_prevalidate_cb *msg_prevalidate_callback;
uint16_t listen_socket_port;

if (!coap_message || !transaction_ptr) {
return -1;
}

// Message is request, find correct handle
// Message is request, find correct handle based on URI
this = service_find_by_uri(socket_id, coap_message->uri_path_ptr, coap_message->uri_path_len);
if (!this) {
tr_debug("not registered uri %.*s", coap_message->uri_path_len, coap_message->uri_path_ptr);
tr_deep("URI %.*s not registered", coap_message->uri_path_len, coap_message->uri_path_ptr);
// URI is not available, find any service that holds the same shared socket so that we can get msg_prevalidate_callback to validate addresses
this = service_find_by_socket(socket_id);
if (!this) {
return -1;
}
}

msg_prevalidate_callback = (coap_service_msg_prevalidate_cb*)coap_connection_handler_msg_prevalidate_callback_get(this->conn_handler, &listen_socket_port);
if (msg_prevalidate_callback) {
// message prevalidation activated for the port
char request_uri[coap_message->uri_path_len + 1];
memcpy(request_uri, coap_message->uri_path_ptr, coap_message->uri_path_len);
request_uri[coap_message->uri_path_len] = 0;

int msg_prevalidate_status = msg_prevalidate_callback(this->interface_id, (uint8_t*)local_addr, listen_socket_port, recv_if_id, transaction_ptr->remote_address, transaction_ptr->remote_port, request_uri);
if (msg_prevalidate_status >= 1) {
tr_deep("Drop CoAP msg %s from %s to %s", request_uri, trace_ipv6(transaction_ptr->remote_address), trace_ipv6(local_addr));
return -1;
}
}

uri_registration_t *uri_reg_ptr = uri_registration_find(this, coap_message->uri_path_ptr, coap_message->uri_path_len);
if (!uri_reg_ptr) {
/* URI is not available, stop further processing */
if (coap_message->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
coap_message_handler_response_send(coap_service_handle, transaction_ptr->service_id, COAP_SERVICE_OPTIONS_NONE, coap_message,
COAP_MSG_CODE_RESPONSE_NOT_FOUND, COAP_CT_NONE, NULL, 0);
Expand All @@ -230,40 +264,22 @@ static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_m
return -1;
}

uri_registration_t *uri_reg_ptr = uri_registration_find(this, coap_message->uri_path_ptr, coap_message->uri_path_len);
if (uri_reg_ptr && uri_reg_ptr->request_recv_cb) {
tr_debug("Service %d, call request recv cb uri %.*s", this->service_id, coap_message->uri_path_len, coap_message->uri_path_ptr);

if (uri_reg_ptr->request_recv_cb) {
if ((this->service_options & COAP_SERVICE_OPTIONS_SECURE_BYPASS) == COAP_SERVICE_OPTIONS_SECURE_BYPASS) { //TODO Add secure bypass option
// Service has secure bypass active TODO this is not defined in interface
// this check can be removed I think
transaction_ptr->options = COAP_REQUEST_OPTIONS_SECURE_BYPASS;
}
coap_service_msg_prevalidate_cb *msg_prevalidate_callback;
uint16_t listen_socket_port;

transaction_ptr->service_id = this->service_id;

msg_prevalidate_callback = (coap_service_msg_prevalidate_cb*)coap_connection_handler_msg_prevalidate_callback_get(this->conn_handler, &listen_socket_port);
if (msg_prevalidate_callback) {
// message prevalidation activated for the port
char request_uri[coap_message->uri_path_len + 1];
memcpy(request_uri, coap_message->uri_path_ptr, coap_message->uri_path_len);
request_uri[coap_message->uri_path_len] = 0;

int msg_prevalidate_status = msg_prevalidate_callback(this->interface_id, transaction_ptr->remote_address, transaction_ptr->remote_port, (uint8_t*)local_addr, listen_socket_port, request_uri);
if (msg_prevalidate_status == 1) {
tr_warn("Drop msg %s", request_uri);
return -1;
}
}

tr_debug("Service %d, recv msg: %.*s", this->service_id, coap_message->uri_path_len, coap_message->uri_path_ptr);
return uri_reg_ptr->request_recv_cb(this->service_id, transaction_ptr->remote_address, transaction_ptr->remote_port, coap_message);
}

return -1;
}

static int recv_cb(int8_t socket_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *data, int len)
static int recv_cb(int8_t socket_id, int8_t recv_if_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *data, int len)
{
uint8_t *data_ptr = NULL;
uint16_t data_len = 0;
Expand All @@ -279,10 +295,9 @@ static int recv_cb(int8_t socket_id, uint8_t src_address[static 16], uint16_t po
}
memcpy(data_ptr, data, len);
data_len = len;
tr_debug("Service recv %d bytes", data_len);

//parse coap message what CoAP to use
int ret = coap_message_handler_coap_msg_process(coap_service_handle, socket_id, src_address, port, dst_address, data_ptr, data_len, &coap_msg_process_callback);
int ret = coap_message_handler_coap_msg_process(coap_service_handle, socket_id, recv_if_id, src_address, port, dst_address, data_ptr, data_len, &coap_msg_process_callback);
own_free(data_ptr);
return ret;
}
Expand Down Expand Up @@ -645,11 +660,11 @@ int8_t coap_service_blockwise_size_set(int8_t service_id, uint16_t size)
return sn_coap_protocol_set_block_size(coap_service_handle->coap, size);
}

int8_t coap_service_msg_prevalidate_callback_set(int8_t service_id, coap_service_msg_prevalidate_cb *msg_prevalidate_cb)
int8_t coap_service_msg_prevalidate_callback_set(uint16_t listen_socket, coap_service_msg_prevalidate_cb *msg_prevalidate_cb)
{
coap_service_t *this = service_find(service_id);
if (this) {
return (int8_t)coap_connection_handler_msg_prevalidate_callback_set(this->conn_handler, (cch_func_cb*)msg_prevalidate_cb);
coap_conn_handler_t *conn_handler = coap_connection_handler_find_by_socket_port(listen_socket);
if (conn_handler) {
return (int8_t)coap_connection_handler_msg_prevalidate_callback_set(conn_handler, (cch_func_cb*)msg_prevalidate_cb);
}
return -1;
}
4 changes: 3 additions & 1 deletion source/include/coap_connection_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
struct internal_socket_s;

typedef int send_to_socket_cb(int8_t socket_id, const uint8_t address[static 16], uint16_t port, const void *, int);
typedef int receive_from_socket_cb(int8_t socket_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *, int);
typedef int receive_from_socket_cb(int8_t socket_id, int8_t recv_if_id, uint8_t src_address[static 16], uint16_t port, const uint8_t dst_address[static 16], unsigned char *, int);
typedef int get_pw_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, coap_security_keys_t *security_ptr);
typedef void security_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]);
typedef void cch_func_cb(void);
Expand Down Expand Up @@ -82,6 +82,8 @@ int8_t coap_connection_handler_handshake_limits_set(uint8_t handshakes_limit, ui

void coap_connection_handler_exec(uint32_t time);

coap_conn_handler_t *coap_connection_handler_find_by_socket_port(uint16_t listen_port);

int coap_connection_handler_msg_prevalidate_callback_set(coap_conn_handler_t *handler, cch_func_cb *function_callback);

cch_func_cb *coap_connection_handler_msg_prevalidate_callback_get(coap_conn_handler_t *handler, uint16_t *listen_socket_port);
Expand Down
5 changes: 3 additions & 2 deletions source/include/coap_message_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ extern coap_transaction_t *coap_message_handler_transaction_valid(coap_transacti

extern coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr, uint16_t port);

extern int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, const uint8_t source_addr_ptr[static 16], uint16_t port, const uint8_t dst_addr_ptr[static 16],
uint8_t *data_ptr, uint16_t data_len, int16_t (msg_process_callback)(int8_t, sn_coap_hdr_s *, coap_transaction_t *, const uint8_t *));
extern int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t socket_id, int8_t source_if_id, const uint8_t source_addr_ptr[static 16], uint16_t port,
const uint8_t dst_addr_ptr[static 16], uint8_t *data_ptr, uint16_t data_len,
int16_t (msg_process_callback)(int8_t, int8_t, sn_coap_hdr_s *, coap_transaction_t *, const uint8_t *));

extern uint16_t coap_message_handler_request_send(coap_msg_handler_t *handle, int8_t service_id, uint8_t options, const uint8_t destination_addr[static 16],
uint16_t destination_port, sn_coap_msg_type_e msg_type, sn_coap_msg_code_e msg_code, const char *uri, sn_coap_content_format_e cont_type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,8 @@ TEST(coap_connection_handler, test_coap_connection_handler_msg_prevalidate_cb_re
CHECK(test_coap_connection_handler_msg_prevalidate_cb_read_and_set());
}

TEST(coap_connection_handler, test_coap_connection_handler_find_by_socket_port)
{
CHECK(test_coap_connection_handler_find_by_socket_port());
}

Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,37 @@ bool test_coap_connection_handler_msg_prevalidate_cb_read_and_set()

return true;
}

bool test_coap_connection_handler_find_by_socket_port()
{
coap_conn_handler_t *handler_ref;
coap_security_handler_stub.counter = -1;

coap_security_handler_stub.sec_obj = coap_security_handler_stub_alloc();

nsdynmemlib_stub.returnCounter = 1;
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
nsdynmemlib_stub.returnCounter = 2;
if (0 != coap_connection_handler_open_connection(handler, 22, false, true, true, false)) {
return false;
}

handler_ref = coap_connection_handler_find_by_socket_port(1000);
if (NULL != handler_ref) {
return false;
}

handler_ref = coap_connection_handler_find_by_socket_port(22);
if (handler_ref->_recv_cb != receive_from_sock_cb) {
return false;
}

connection_handler_destroy(handler, false);

free(coap_security_handler_stub.sec_obj);
coap_security_handler_stub.sec_obj = NULL;

return true;
}


Loading

0 comments on commit 587e8de

Please sign in to comment.