From efe4850e75bbfe34780617d5cbfad46c42714233 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Thu, 10 Feb 2022 18:16:28 +0100 Subject: [PATCH] ranap_rab_ass: add function to check if RAB is in FailureList A RANAP RAB-AssignmentResponse may contain a FailedList. In order to detect that a RAB Assignment failed at the HNB we need to be able to check if the RAB we are dealing with is contained an such a FailedList. Change-Id: I4319f7caa45ea758ccd792cc8570521df075cf45 Related: OS#5152 --- include/osmocom/hnbgw/ranap_rab_ass.h | 2 + src/osmo-hnbgw/ranap_rab_ass.c | 73 ++++++++++++++++++++++- tests/ranap_rab_ass/ranap_rab_ass_test.c | 27 +++++++++ tests/ranap_rab_ass/ranap_rab_ass_test.ok | 2 + 4 files changed, 102 insertions(+), 2 deletions(-) diff --git a/include/osmocom/hnbgw/ranap_rab_ass.h b/include/osmocom/hnbgw/ranap_rab_ass.h index f4d5cb6..b3406f0 100644 --- a/include/osmocom/hnbgw/ranap_rab_ass.h +++ b/include/osmocom/hnbgw/ranap_rab_ass.h @@ -14,3 +14,5 @@ int ranap_rab_ass_req_ies_replace_inet_addr(RANAP_RAB_AssignmentRequestIEs_t *ie uint8_t rab_id); int ranap_rab_ass_resp_ies_replace_inet_addr(RANAP_RAB_AssignmentResponseIEs_t *ies, struct osmo_sockaddr *addr, uint8_t rab_id); + +bool ranap_rab_ass_resp_ies_check_failure(RANAP_RAB_AssignmentResponseIEs_t *ies, uint8_t rab_id); diff --git a/src/osmo-hnbgw/ranap_rab_ass.c b/src/osmo-hnbgw/ranap_rab_ass.c index 5edbd3d..030a1af 100644 --- a/src/osmo-hnbgw/ranap_rab_ass.c +++ b/src/osmo-hnbgw/ranap_rab_ass.c @@ -141,8 +141,7 @@ static RANAP_IE_t *setup_or_modif_item_from_rab_ass_resp(const RANAP_RAB_Assignm { /* Make sure we indeed deal with a setup-or-modified list */ if (!(ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_SETUPORMODIFIEDLIST_PRESENT)) { - RANAP_DEBUG - ("Decoding failed, the RANAP RAB AssignmentResponse did not contain a setup-or-modified list!\n"); + RANAP_DEBUG("RANAP RAB AssignmentResponse did not contain a setup-or-modified list!\n"); return NULL; } @@ -153,6 +152,23 @@ static RANAP_IE_t *setup_or_modif_item_from_rab_ass_resp(const RANAP_RAB_Assignm return ies->raB_SetupOrModifiedList.raB_SetupOrModifiedList_ies.list.array[index]; } +/* Pick the indexed item from the RAB failed list and return a pointer to it */ +static RANAP_IE_t *failed_list_item_from_rab_ass_resp(const RANAP_RAB_AssignmentResponseIEs_t *ies, + unsigned int index) +{ + /* Make sure we indeed deal with a failed list */ + if (!(ies->presenceMask & RAB_ASSIGNMENTRESPONSEIES_RANAP_RAB_FAILEDLIST_PRESENT)) { + RANAP_DEBUG("RANAP RAB AssignmentResponse did not contain a failed list!\n"); + return NULL; + } + + /* Detect the end of the list */ + if (index >= ies->raB_FailedList.raB_FailedList_ies.list.count) + return NULL; + + return ies->raB_FailedList.raB_FailedList_ies.list.array[index]; +} + /* find the RAB specified by rab_id in ies and when found, decode the result into items_ies */ static int decode_rab_smditms_from_resp_ies(RANAP_RAB_SetupOrModifiedItemIEs_t *items_ies, RANAP_RAB_AssignmentResponseIEs_t *ies, uint8_t rab_id) @@ -184,6 +200,37 @@ static int decode_rab_smditms_from_resp_ies(RANAP_RAB_SetupOrModifiedItemIEs_t * } } +/* See comment above decode_rab_smditms_from_resp_ies() */ +static int decode_rab_flitms_from_resp_ies(RANAP_RAB_FailedItemIEs_t *items_ies, + RANAP_RAB_AssignmentResponseIEs_t *ies, uint8_t rab_id) +{ + RANAP_IE_t *failed_list_ie; + RANAP_RAB_FailedItem_t *rab_failed_item; + int rc; + uint8_t rab_id_decoded; + unsigned int index = 0; + + while (1) { + failed_list_ie = failed_list_item_from_rab_ass_resp(ies, index); + if (!failed_list_ie) + return -EINVAL; + + rc = ranap_decode_rab_faileditemies_fromlist(items_ies, &failed_list_ie->value); + if (rc < 0) + return -EINVAL; + + rab_failed_item = &items_ies->raB_FailedItem; + /* The RAB-ID is defined as a bitstring with a size of 8 (1 byte), + * See also RANAP-IEs.asn, RAB-ID ::= BIT STRING (SIZE (8)) */ + rab_id_decoded = rab_failed_item->rAB_ID.buf[0]; + if (rab_id_decoded == rab_id) + return index; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_FailedItem, items_ies); + index++; + } +} + /* find the RAB specified by rab_id in ies and when found, decode the result into item */ static int decode_rab_smditms_from_req_ies(RANAP_RAB_SetupOrModifyItemFirst_t *item, RANAP_RAB_AssignmentRequestIEs_t *ies, uint8_t rab_id) @@ -477,3 +524,25 @@ error: return rc; } + +/*! Check if a specific RAB is present in an RAB-Failed-Item-List inside RANAP_RAB_AssignmentResponseIEs. + * \ptmap[in] ies user provided memory with RANAP_RAB_AssignmentResponseIEs. + * \ptmap[in] rab_id expected rab id to look for. + * \returns true when RAB could be identified as failed; false otherwise */ +bool ranap_rab_ass_resp_ies_check_failure(RANAP_RAB_AssignmentResponseIEs_t *ies, uint8_t rab_id) +{ + RANAP_RAB_FailedItemIEs_t _rab_failed_items_ies; + RANAP_RAB_FailedItemIEs_t *rab_failed_items_ies = &_rab_failed_items_ies; + int rc; + bool result = true; + + /* If we can get a failed item for the specified RAB ID, then we know that the + * HNB reported the RAB Assignment as failed */ + rc = decode_rab_flitms_from_resp_ies(rab_failed_items_ies, ies, rab_id); + if (rc < 0) + result = false; + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_RANAP_RAB_FailedItem, rab_failed_items_ies); + + return result; +} diff --git a/tests/ranap_rab_ass/ranap_rab_ass_test.c b/tests/ranap_rab_ass/ranap_rab_ass_test.c index d7bee09..5bb4efc 100644 --- a/tests/ranap_rab_ass/ranap_rab_ass_test.c +++ b/tests/ranap_rab_ass/ranap_rab_ass_test.c @@ -269,6 +269,32 @@ void test_ranap_rab_ass_resp_replace_inet_addr(void) ranap_cn_rx_co_free(&message); } +void test_ranap_rab_ass_resp_ies_check_failure(void) +{ + int rc; + ranap_message message; + bool rab_failed_at_hnb; + uint8_t testvec[] = { + 0x60, 0x00, 0x00, 0x11, 0x00, 0x00, 0x01, 0x00, + 0x23, 0x40, 0x0a, 0x00, 0x00, 0x01, 0x00, 0x22, + 0x40, 0x03, 0x05, 0xd0, 0x00 + }; + + rc = ranap_cn_rx_co_decode(talloc_asn1_ctx, &message, testvec, sizeof(testvec)); + OSMO_ASSERT(rc == 0); + + rab_failed_at_hnb = + ranap_rab_ass_resp_ies_check_failure(&message.msg.raB_AssignmentResponseIEs, 23); + printf("ranap_rab_ass_resp_ies_check_failure rab_failed_at_hnb=%u (RAB ID 23)\n", rab_failed_at_hnb); + + rab_failed_at_hnb = + ranap_rab_ass_resp_ies_check_failure(&message.msg.raB_AssignmentResponseIEs, 44); + printf("ranap_rab_ass_resp_ies_check_failure rab_failed_at_hnb=%u (RAB ID 44, which is not in the message)\n", + rab_failed_at_hnb); + + ranap_cn_rx_co_free(&message); +} + static const struct log_info_cat log_cat[] = { [DRANAP] = { .name = "RANAP", .loglevel = LOGL_DEBUG, .enabled = 1, @@ -329,6 +355,7 @@ int main(int argc, char **argv) test_ranap_rab_ass_resp_extract_inet_addr(); test_ranap_rab_ass_req_replace_inet_addr(); test_ranap_rab_ass_resp_replace_inet_addr(); + test_ranap_rab_ass_resp_ies_check_failure(); test_cleanup(); return 0; diff --git a/tests/ranap_rab_ass/ranap_rab_ass_test.ok b/tests/ranap_rab_ass/ranap_rab_ass_test.ok index 97756cb..d372550 100644 --- a/tests/ranap_rab_ass/ranap_rab_ass_test.ok +++ b/tests/ranap_rab_ass/ranap_rab_ass_test.ok @@ -14,3 +14,5 @@ after: addr=1.2.3.4, port=1234, rab_id=39 before: addr=10.9.1.164, port=1034 ranap_rab_ass_resp_replace_inet_addr rc=0 after: addr=1.2.3.4, port=1234 +ranap_rab_ass_resp_ies_check_failure rab_failed_at_hnb=1 (RAB ID 23) +ranap_rab_ass_resp_ies_check_failure rab_failed_at_hnb=0 (RAB ID 44, which is not in the message)