Skip to content

Commit 46f86d4

Browse files
author
Arto Kinnunen
authored
Add API to set callback for CoAP msg prevalidation (#115)
Application can set callback method that is used to validate message before passing it further. CoAP service will reject requests if prevalidation fails.
1 parent 0eb6630 commit 46f86d4

16 files changed

+218
-12
lines changed

coap-service/coap_service_api.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,25 @@ typedef int coap_service_security_start_cb(int8_t service_id, uint8_t address[st
120120
*/
121121
typedef int coap_service_security_done_cb(int8_t service_id, uint8_t address[static 16], uint8_t keyblock[static 40]);
122122

123+
/**
124+
* \brief Message prevalidation callback
125+
*
126+
* Message prevalidation callback function type used in method coap_service_msg_prevalidate_callback_set.
127+
*
128+
* \param interface_id Application interface ID.
129+
* \param source_address Sender address.
130+
* \param source_port Sender port.
131+
* \param local_address Local address.
132+
* \param local_port Local port.
133+
* \param request_uri CoAP URI, NUL terminated.
134+
*
135+
* \return <0 in case of errors,
136+
* 0 if message is valid to process further,
137+
* >0 if message should be dropped.
138+
*/
139+
140+
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);
141+
123142
/**
124143
* \brief Initialise server instance.
125144
*
@@ -131,7 +150,7 @@ typedef int coap_service_security_done_cb(int8_t service_id, uint8_t address[sta
131150
* \param *start_ptr Callback to inform security handling is started and to fetch device password.
132151
* \param *coap_security_done_cb Callback to inform security handling is done.
133152
*
134-
* \return service_id / -1 for failure
153+
* \return service_id / -1 for failure
135154
*/
136155
extern int8_t coap_service_initialize(int8_t interface_id, uint16_t listen_port, uint8_t service_options, coap_service_security_start_cb *start_ptr, coap_service_security_done_cb *coap_security_done_cb);
137156

@@ -373,6 +392,22 @@ extern int8_t coap_service_certificate_set(int8_t service_id, const unsigned cha
373392
*- 0 For success
374393
*/
375394
extern int8_t coap_service_blockwise_size_set(int8_t service_id, uint16_t size);
395+
396+
/**
397+
* \brief Set message prevalidation callback function.
398+
*
399+
* Set message prevalidation callback function for the service. Callback will be called for all services using the same listen port.
400+
*
401+
* CoAP service will call this function to allow application prevalidate incoming CoAP message before passing it to application.
402+
*
403+
* \param service_id Id number of the current service.
404+
* \param msg_prevalidate_cb Callback to be called to validate incoming message before pprocessing it.
405+
*
406+
* \return -1 For failure
407+
* 0 For success
408+
*/
409+
extern int8_t coap_service_msg_prevalidate_callback_set(int8_t service_id, coap_service_msg_prevalidate_cb *msg_prevalidate_cb);
410+
376411
#ifdef __cplusplus
377412
}
378413
#endif

source/coap_connection_handler.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ typedef enum session_state_e {
3636

3737
typedef struct internal_socket_s {
3838
coap_conn_handler_t *parent;
39+
cch_func_cb *cch_function_callback; // callback function
3940

4041
uint32_t timeout_min;
4142
uint32_t timeout_max;
@@ -1023,3 +1024,22 @@ void coap_connection_handler_exec(uint32_t time)
10231024
}
10241025
}
10251026
}
1027+
1028+
int coap_connection_handler_msg_prevalidate_callback_set(coap_conn_handler_t *handler, cch_func_cb *function_callback)
1029+
{
1030+
if (!handler) {
1031+
return -1;
1032+
}
1033+
handler->socket->cch_function_callback = function_callback;
1034+
return 0;
1035+
}
1036+
1037+
cch_func_cb *coap_connection_handler_msg_prevalidate_callback_get(coap_conn_handler_t *handler, uint16_t *listen_socket_port)
1038+
{
1039+
if (!handler || !listen_socket_port) {
1040+
return NULL;
1041+
}
1042+
1043+
*listen_socket_port = handler->socket->listen_port;
1044+
return handler->socket->cch_function_callback;
1045+
}

source/coap_message_handler.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -294,14 +294,14 @@ coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr,
294294
}
295295

296296
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],
297-
uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *))
297+
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 *))
298298
{
299299
sn_nsdl_addr_s src_addr;
300300
sn_coap_hdr_s *coap_message;
301301
int16_t ret_val = 0;
302302
coap_transaction_t *this = NULL;
303303

304-
if (!cb || !handle) {
304+
if (!msg_process_callback || !handle) {
305305
return -1;
306306
}
307307

@@ -337,21 +337,21 @@ int16_t coap_message_handler_coap_msg_process(coap_msg_handler_t *handle, int8_t
337337
goto exit;
338338
}
339339

340-
/* Request received */
341340
if (coap_message->msg_code > 0 && coap_message->msg_code < 32) {
341+
/* Request received */
342342
transaction_ptr->msg_id = coap_message->msg_id;
343343
transaction_ptr->req_msg_type = coap_message->msg_type;
344344
if (coap_message->token_len) {
345345
memcpy(transaction_ptr->token, coap_message->token_ptr, coap_message->token_len);
346346
transaction_ptr->token_len = coap_message->token_len;
347347
}
348-
if (cb(socket_id, coap_message, transaction_ptr) < 0) {
348+
if (msg_process_callback(socket_id, coap_message, transaction_ptr, dst_addr_ptr) < 0) {
349349
// negative return value = message ignored -> delete transaction
350350
transaction_delete(transaction_ptr);
351351
}
352352
goto exit;
353-
/* Response received */
354353
} else {
354+
/* Response received */
355355
transaction_delete(transaction_ptr); // transaction_ptr not needed in response
356356
if (coap_message->token_ptr) {
357357
this = transaction_find_client_by_token(coap_message->token_ptr, coap_message->token_len, source_addr_ptr, port);

source/coap_service_api.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include "coap_message_handler.h"
3737
#include "mbed-coap/sn_coap_protocol.h"
3838

39-
static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr);
39+
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);
4040

4141
typedef struct uri_registration {
4242
char *uri_ptr;
@@ -211,7 +211,7 @@ static void service_event_handler(arm_event_s *event)
211211
eventOS_event_timer_request((uint8_t)COAP_TICK_TIMER, ARM_LIB_SYSTEM_TIMER_EVENT, tasklet_id, 1000);
212212
}
213213

214-
static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_message, coap_transaction_t *transaction_ptr)
214+
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)
215215
{
216216
coap_service_t *this;
217217
if (!coap_message || !transaction_ptr) {
@@ -239,7 +239,25 @@ static int16_t coap_msg_process_callback(int8_t socket_id, sn_coap_hdr_s *coap_m
239239
// this check can be removed I think
240240
transaction_ptr->options = COAP_REQUEST_OPTIONS_SECURE_BYPASS;
241241
}
242+
coap_service_msg_prevalidate_cb *msg_prevalidate_callback;
243+
uint16_t listen_socket_port;
244+
242245
transaction_ptr->service_id = this->service_id;
246+
247+
msg_prevalidate_callback = (coap_service_msg_prevalidate_cb*)coap_connection_handler_msg_prevalidate_callback_get(this->conn_handler, &listen_socket_port);
248+
if (msg_prevalidate_callback) {
249+
// message prevalidation activated for the port
250+
char request_uri[coap_message->uri_path_len + 1];
251+
memcpy(request_uri, coap_message->uri_path_ptr, coap_message->uri_path_len);
252+
request_uri[coap_message->uri_path_len] = 0;
253+
254+
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);
255+
if (msg_prevalidate_status == 1) {
256+
tr_warn("Drop msg %s", request_uri);
257+
return -1;
258+
}
259+
}
260+
243261
return uri_reg_ptr->request_recv_cb(this->service_id, transaction_ptr->remote_address, transaction_ptr->remote_port, coap_message);
244262
}
245263
return -1;
@@ -261,7 +279,7 @@ static int recv_cb(int8_t socket_id, uint8_t src_address[static 16], uint16_t po
261279
}
262280
memcpy(data_ptr, data, len);
263281
data_len = len;
264-
tr_debug("service recv socket data len %d ", data_len);
282+
tr_debug("Service recv %d bytes", data_len);
265283

266284
//parse coap message what CoAP to use
267285
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);
@@ -626,3 +644,12 @@ int8_t coap_service_blockwise_size_set(int8_t service_id, uint16_t size)
626644

627645
return sn_coap_protocol_set_block_size(coap_service_handle->coap, size);
628646
}
647+
648+
int8_t coap_service_msg_prevalidate_callback_set(int8_t service_id, coap_service_msg_prevalidate_cb *msg_prevalidate_cb)
649+
{
650+
coap_service_t *this = service_find(service_id);
651+
if (this) {
652+
return (int8_t)coap_connection_handler_msg_prevalidate_callback_set(this->conn_handler, (cch_func_cb*)msg_prevalidate_cb);
653+
}
654+
return -1;
655+
}

source/include/coap_connection_handler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ typedef int send_to_socket_cb(int8_t socket_id, const uint8_t address[static 16]
3838
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);
3939
typedef int get_pw_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, coap_security_keys_t *security_ptr);
4040
typedef void security_done_cb(int8_t socket_id, uint8_t address[static 16], uint16_t port, uint8_t keyblock[static 40]);
41+
typedef void cch_func_cb(void);
4142

4243
typedef struct coap_conn_handler_s {
4344
struct internal_socket_s *socket;
@@ -81,4 +82,8 @@ int8_t coap_connection_handler_handshake_limits_set(uint8_t handshakes_limit, ui
8182

8283
void coap_connection_handler_exec(uint32_t time);
8384

85+
int coap_connection_handler_msg_prevalidate_callback_set(coap_conn_handler_t *handler, cch_func_cb *function_callback);
86+
87+
cch_func_cb *coap_connection_handler_msg_prevalidate_callback_get(coap_conn_handler_t *handler, uint16_t *listen_socket_port);
88+
8489
#endif

source/include/coap_message_handler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ extern coap_transaction_t *coap_message_handler_transaction_valid(coap_transacti
8585
extern coap_transaction_t *coap_message_handler_find_transaction(uint8_t *address_ptr, uint16_t port);
8686

8787
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],
88-
uint8_t *data_ptr, uint16_t data_len, int16_t (cb)(int8_t, sn_coap_hdr_s *, coap_transaction_t *));
88+
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 *));
8989

9090
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],
9191
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,

test/coap-service/unittest/coap_connection_handler/coap_connection_handlertest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,8 @@ TEST(coap_connection_handler, test_security_callbacks)
7171
CHECK(test_security_callbacks());
7272
}
7373

74+
TEST(coap_connection_handler, test_coap_connection_handler_msg_prevalidate_cb_read_and_set)
75+
{
76+
CHECK(test_coap_connection_handler_msg_prevalidate_cb_read_and_set());
77+
}
78+

test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,41 @@ bool test_security_callbacks()
511511
sckt_data = NULL;
512512
return true;
513513
}
514+
515+
bool test_coap_connection_handler_msg_prevalidate_cb_read_and_set()
516+
{
517+
coap_security_handler_stub.counter = -1;
518+
519+
coap_security_handler_stub.sec_obj = coap_security_handler_stub_alloc();
520+
521+
nsdynmemlib_stub.returnCounter = 1;
522+
coap_conn_handler_t *handler = connection_handler_create(&receive_from_sock_cb, &send_to_sock_cb, NULL, NULL);
523+
nsdynmemlib_stub.returnCounter = 2;
524+
if (0 != coap_connection_handler_open_connection(handler, 22, false, true, true, false)) {
525+
return false;
526+
}
527+
528+
if (-1 != coap_connection_handler_msg_prevalidate_callback_set(NULL, 1000)) {
529+
return false;
530+
}
531+
532+
if (0 != coap_connection_handler_msg_prevalidate_callback_set(handler, 1000)) {
533+
return false;
534+
}
535+
536+
uint16_t listen_socket_port;
537+
if (NULL != coap_connection_handler_msg_prevalidate_callback_get(NULL, &listen_socket_port)) {
538+
return false;
539+
}
540+
541+
if (1000 != coap_connection_handler_msg_prevalidate_callback_get(handler, &listen_socket_port)) {
542+
return false;
543+
}
544+
545+
connection_handler_destroy(handler, false);
546+
547+
free(coap_security_handler_stub.sec_obj);
548+
coap_security_handler_stub.sec_obj = NULL;
549+
550+
return true;
551+
}

test/coap-service/unittest/coap_connection_handler/test_coap_connection_handler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ bool test_socket_api_callbacks();
4141

4242
bool test_security_callbacks();
4343

44+
bool test_coap_connection_handler_msg_prevalidate_cb_read_and_set();
45+
4446
#ifdef __cplusplus
4547
}
4648
#endif

test/coap-service/unittest/coap_service_api/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ TEST_SRC_FILES = \
3333
../stub/coap_connection_handler_stub.c \
3434
../stub/coap_message_handler_stub.c \
3535
../stub/common_functions_stub.c \
36-
../stub/sn_coap_protocol_stub.c
36+
../stub/sn_coap_protocol_stub.c \
37+
../stub/socket_api_stub.c
3738

3839
include ../MakefileWorker.mk
3940

test/coap-service/unittest/coap_service_api/coap_service_apitest.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,9 @@ TEST(coap_service_api, test_coap_service_handshake_limit_set)
120120
{
121121
CHECK(test_coap_service_handshake_limit_set())
122122
}
123+
124+
TEST(coap_service_api, test_coap_service_msg_prevalidate_cb_read_and_set)
125+
{
126+
CHECK(test_coap_service_msg_prevalidate_cb_read_and_set())
127+
}
128+

test/coap-service/unittest/coap_service_api/test_coap_service_api.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ int virtual_sock_send_cb(int8_t service_id, uint8_t destination_addr_ptr[static
4545
return 2;
4646
}
4747

48+
int msg_prevalidate_cb(int8_t interface_id, uint8_t address[static 16])
49+
{
50+
return 1;
51+
}
52+
4853
bool test_coap_service_initialize()
4954
{
5055
if (-1 != coap_service_initialize(1, 2, 0, NULL, NULL)) {
@@ -439,6 +444,19 @@ bool test_conn_handler_callbacks()
439444

440445
coap_transaction_t *tr = (coap_transaction_t *)malloc(sizeof(coap_transaction_t));
441446
memset(tr, 0, sizeof(coap_transaction_t));
447+
tr->local_address[0] = 2;
448+
449+
if (0 != coap_service_msg_prevalidate_callback_set(1, msg_prevalidate_cb)) {
450+
return false;
451+
}
452+
453+
if (-1 != coap_message_handler_stub.cb(1, coap, tr)) {
454+
return false;
455+
}
456+
457+
if (0 != coap_service_msg_prevalidate_callback_set(1, NULL)) {
458+
return false;
459+
}
442460

443461
if (2 != coap_message_handler_stub.cb(1, coap, tr)) {
444462
return false;
@@ -645,3 +663,36 @@ bool test_coap_service_handshake_limit_set()
645663

646664
return true;
647665
}
666+
667+
bool test_coap_service_msg_prevalidate_cb_read_and_set()
668+
{
669+
/* No valid service ID - return failure */
670+
if (0 == coap_service_msg_prevalidate_callback_set(0, msg_prevalidate_cb)) {
671+
return false;
672+
}
673+
674+
/* Init service */
675+
thread_conn_handler_stub.handler_obj = (coap_conn_handler_t *)malloc(sizeof(coap_conn_handler_t));
676+
memset(thread_conn_handler_stub.handler_obj, 0, sizeof(coap_conn_handler_t));
677+
678+
nsdynmemlib_stub.returnCounter = 1;
679+
thread_conn_handler_stub.bool_value = 0;
680+
if (1 != coap_service_initialize(1, 2, 0, NULL, NULL)) {
681+
return false;
682+
}
683+
684+
if (0 != coap_service_msg_prevalidate_callback_set(1, msg_prevalidate_cb)) {
685+
return false;
686+
}
687+
688+
if (0 != coap_service_msg_prevalidate_callback_set(1, NULL)) {
689+
return false;
690+
}
691+
692+
/* Teardown */
693+
coap_service_delete(1);
694+
free(thread_conn_handler_stub.handler_obj);
695+
thread_conn_handler_stub.handler_obj = NULL;
696+
697+
return true;
698+
}

test/coap-service/unittest/coap_service_api/test_coap_service_api.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ bool test_coap_service_if_find_by_socket();
6161

6262
bool test_coap_service_handshake_limit_set();
6363

64+
bool test_coap_service_msg_prevalidate_cb_read_and_set();
65+
6466

6567
#ifdef __cplusplus
6668
}

0 commit comments

Comments
 (0)