From 89859a867c6baeb482c8872db907eae528839c33 Mon Sep 17 00:00:00 2001 From: skarg Date: Mon, 19 Dec 2005 12:47:19 +0000 Subject: [PATCH] added error, abort, and reject optional handlers. --- bacnet-stack/apdu.c | 72 ++++++++++++++++++++++++++++++++++++++++++++- bacnet-stack/apdu.h | 29 ++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/bacnet-stack/apdu.c b/bacnet-stack/apdu.c index c620ae48..4fdbe275 100644 --- a/bacnet-stack/apdu.c +++ b/bacnet-stack/apdu.c @@ -149,6 +149,33 @@ void apdu_set_confirmed_ack_handler( } } +static error_function +Error_Function[MAX_BACNET_CONFIRMED_SERVICE]; + +void apdu_set_error_handler( + BACNET_CONFIRMED_SERVICE service_choice, + error_function pFunction) +{ + if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) + Error_Function[service_choice] = pFunction; +} + +static abort_function Abort_Function; + +void apdu_set_abort_handler( + abort_function pFunction) +{ + Abort_Function = pFunction; +} + +static reject_function Reject_Function; + +void apdu_set_reject_handler( + reject_function pFunction) +{ + Reject_Function = pFunction; +} + uint16_t apdu_decode_confirmed_service_request( uint8_t *apdu, // APDU data uint16_t apdu_len, @@ -191,6 +218,11 @@ void apdu_handler( uint8_t *service_request = NULL; uint16_t service_request_len = 0; uint16_t len = 0; // counts where we are in PDU + uint8_t tag_number = 0; + uint32_t len_value = 0; + int error_code = 0; + int error_class = 0; + uint8_t reason = 0; (void)data_expecting_reply; if (apdu) @@ -325,11 +357,49 @@ void apdu_handler( } break; case PDU_TYPE_SEGMENT_ACK: + /* FIXME: what about a denial of service attack here? + we could check src to see if that matched the tsm */ + tsm_free_invoke_id(invoke_id); + break; case PDU_TYPE_ERROR: + invoke_id = apdu[1]; + service_choice = apdu[2]; + len = 3; + len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); + /* FIXME: we could validate that the tag is enumerated... */ + len += decode_enumerated(&apdu[len],len_value, &error_class); + len += decode_tag_number_and_value(&apdu[len], &tag_number, &len_value); + /* FIXME: we could validate that the tag is enumerated... */ + len += decode_enumerated(&apdu[len],len_value, &error_code); + if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) + { + if (Error_Function[service_choice]) + Error_Function[service_choice]( + src, + invoke_id, + error_class, + error_code); + } + tsm_free_invoke_id(invoke_id); + break; case PDU_TYPE_REJECT: + invoke_id = apdu[1]; + reason = apdu[2]; + if (Reject_Function) + Reject_Function( + src, + invoke_id, + reason); + tsm_free_invoke_id(invoke_id); + break; case PDU_TYPE_ABORT: invoke_id = apdu[1]; - /* FIXME: what about a way to let a client know? */ + reason = apdu[2]; + if (Abort_Function) + Abort_Function( + src, + invoke_id, + reason); tsm_free_invoke_id(invoke_id); break; default: diff --git a/bacnet-stack/apdu.h b/bacnet-stack/apdu.h index 86dc8672..4a2335d9 100644 --- a/bacnet-stack/apdu.h +++ b/bacnet-stack/apdu.h @@ -109,6 +109,25 @@ typedef void (*confirmed_ack_function)( BACNET_ADDRESS *src, BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data); +// generic error reply function +typedef void (*error_function)( + BACNET_ADDRESS *src, + uint8_t invoke_id, + BACNET_ERROR_CLASS error_class, + BACNET_ERROR_CODE error_code); + +// generic abort reply function +typedef void (*abort_function)( + BACNET_ADDRESS *src, + uint8_t invoke_id, + uint8_t abort_reason); + +// generic reject reply function +typedef void (*reject_function)( + BACNET_ADDRESS *src, + uint8_t invoke_id, + uint8_t reject_reason); + void apdu_set_confirmed_ack_handler( BACNET_CONFIRMED_SERVICE service_choice, confirmed_ack_function pFunction); @@ -129,6 +148,16 @@ void apdu_set_unconfirmed_handler( BACNET_UNCONFIRMED_SERVICE service_choice, unconfirmed_function pFunction); +void apdu_set_error_handler( + BACNET_CONFIRMED_SERVICE service_choice, + error_function pFunction); + +void apdu_set_abort_handler( + abort_function pFunction); + +void apdu_set_reject_handler( + reject_function pFunction); + uint16_t apdu_decode_confirmed_service_request( uint8_t *apdu, // APDU data uint16_t apdu_len,