diff --git a/include/osmocom/cbc/sbcap_msg.h b/include/osmocom/cbc/sbcap_msg.h index 285c35c..286642c 100644 --- a/include/osmocom/cbc/sbcap_msg.h +++ b/include/osmocom/cbc/sbcap_msg.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include "cbc_data.h" @@ -9,3 +10,4 @@ typedef struct SBcAP_SBC_AP_PDU SBcAP_SBC_AP_PDU_t; SBcAP_SBC_AP_PDU_t *sbcap_gen_write_replace_warning_req(void *ctx, const struct cbc_message *cbcmsg); SBcAP_SBC_AP_PDU_t *sbcap_gen_stop_warning_req(void *ctx, const struct cbc_message *cbcmsg); +SBcAP_SBC_AP_PDU_t *sbcap_gen_error_ind(void *ctx, SBcAP_Cause_t cause, SBcAP_SBC_AP_PDU_t *rx_pdu); diff --git a/include/osmocom/sbcap/sbcap_common.h b/include/osmocom/sbcap/sbcap_common.h index 795bf25..303cf6d 100644 --- a/include/osmocom/sbcap/sbcap_common.h +++ b/include/osmocom/sbcap/sbcap_common.h @@ -141,8 +141,14 @@ const char *sbcap_cause_str(SBcAP_Cause_t cause); void sbcap_set_log_area(int log_area); +SBcAP_ProcedureCode_t sbcap_pdu_get_procedure_code(const SBcAP_SBC_AP_PDU_t *pdu); +SBcAP_Criticality_t sbcap_pdu_get_criticality(const SBcAP_SBC_AP_PDU_t *pdu); + SBcAP_Write_Replace_Warning_Request_IEs_t *sbcap_alloc_Write_Replace_Warning_Request_IE( long id, SBcAP_Criticality_t criticality, SBcAP_Write_Replace_Warning_Request_IEs__value_PR present); SBcAP_Stop_Warning_Request_IEs_t *sbcap_alloc_Stop_Warning_Request_IE( long id, SBcAP_Criticality_t criticality, SBcAP_Stop_Warning_Request_IEs__value_PR present); + +SBcAP_ErrorIndicationIEs_t *sbcap_alloc_Error_Indication_IE( + long id, SBcAP_Criticality_t criticality, SBcAP_Stop_Warning_Request_IEs__value_PR present); diff --git a/src/sbcap/sbcap_common.c b/src/sbcap/sbcap_common.c index 3968c71..86ca0b2 100644 --- a/src/sbcap/sbcap_common.c +++ b/src/sbcap/sbcap_common.c @@ -111,6 +111,36 @@ void sbcap_pdu_free(SBcAP_SBC_AP_PDU_t *pdu) ASN_STRUCT_FREE(asn_DEF_SBcAP_SBC_AP_PDU, pdu); } +SBcAP_ProcedureCode_t sbcap_pdu_get_procedure_code(const SBcAP_SBC_AP_PDU_t *pdu) +{ + switch (pdu->present) { + case SBcAP_SBC_AP_PDU_PR_initiatingMessage: + return pdu->choice.initiatingMessage.procedureCode; + case SBcAP_SBC_AP_PDU_PR_successfulOutcome: + return pdu->choice.successfulOutcome.procedureCode; + case SBcAP_SBC_AP_PDU_PR_unsuccessfulOutcome: + return pdu->choice.unsuccessfulOutcome.procedureCode; + case SBcAP_SBC_AP_PDU_PR_NOTHING: + default: + return -1; + } +} + +SBcAP_Criticality_t sbcap_pdu_get_criticality(const SBcAP_SBC_AP_PDU_t *pdu) +{ + switch (pdu->present) { + case SBcAP_SBC_AP_PDU_PR_initiatingMessage: + return pdu->choice.initiatingMessage.criticality; + case SBcAP_SBC_AP_PDU_PR_successfulOutcome: + return pdu->choice.successfulOutcome.criticality; + case SBcAP_SBC_AP_PDU_PR_unsuccessfulOutcome: + return pdu->choice.unsuccessfulOutcome.criticality; + case SBcAP_SBC_AP_PDU_PR_NOTHING: + default: + return -1; + } +} + void sbcap_set_log_area(int log_area) { _sbcap_DSBCAP = log_area; @@ -135,3 +165,13 @@ SBcAP_Stop_Warning_Request_IEs_t *sbcap_alloc_Stop_Warning_Request_IE( ie->value.present = present; return ie; } + +SBcAP_ErrorIndicationIEs_t *sbcap_alloc_Error_Indication_IE( + long id, SBcAP_Criticality_t criticality, SBcAP_Stop_Warning_Request_IEs__value_PR present) +{ + SBcAP_ErrorIndicationIEs_t *ie = CALLOC(1, sizeof(*ie)); + ie->id = id; + ie->criticality = criticality; + ie->value.present = present; + return ie; +} diff --git a/src/sbcap_link.c b/src/sbcap_link.c index 6459c58..8a3af59 100644 --- a/src/sbcap_link.c +++ b/src/sbcap_link.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -166,6 +167,13 @@ static int cbc_sbcap_link_cli_read_cb(struct osmo_stream_cli *conn) g_cbc->sbcap.mgr->rx_cb(link, pdu); } else { LOGPSBCAPC(link, LOGL_ERROR, "Unable to decode %s\n", msgb_hexdump(msg)); + pdu = sbcap_gen_error_ind(link, SBcAP_Cause_unrecognised_message, NULL); + if (pdu) { + cbc_sbcap_link_tx(link, pdu); + } else { + LOGPSBCAPC(link, LOGL_ERROR, + "Tx SBc-AP Error-Indication: msg gen failed\n"); + } } out: msgb_free(msg); diff --git a/src/sbcap_msg.c b/src/sbcap_msg.c index 8f597b2..bd83045 100644 --- a/src/sbcap_msg.c +++ b/src/sbcap_msg.c @@ -291,3 +291,48 @@ SBcAP_SBC_AP_PDU_t *sbcap_gen_stop_warning_req(void *ctx, const struct cbc_messa return pdu; } + +/* generate a SBc-AP ERROR INDICATION, 3GPP TS 29.168 4.3.4.2A.1. + * rx_pdu can be NULL. + */ +SBcAP_SBC_AP_PDU_t *sbcap_gen_error_ind(void *ctx, SBcAP_Cause_t cause, SBcAP_SBC_AP_PDU_t *rx_pdu) +{ + SBcAP_SBC_AP_PDU_t *pdu; + SBcAP_ErrorIndicationIEs_t *ie; + + pdu = sbcap_pdu_alloc(); + if (!pdu) + return NULL; + pdu->present = SBcAP_SBC_AP_PDU_PR_initiatingMessage; + pdu->choice.initiatingMessage.procedureCode = SBcAP_ProcedureId_Error_Indication; + pdu->choice.initiatingMessage.criticality = SBcAP_Criticality_ignore; + pdu->choice.initiatingMessage.value.present = SBcAP_InitiatingMessage__value_PR_Error_Indication; + + A_SEQUENCE_OF(void) *as_pdu = (void *)&pdu->choice.initiatingMessage.value.choice.Error_Indication.protocolIEs.list; + + /* Cause, Optional: + * 3GPP TS 36.413 4.3.4.3.2 + * static const long asn_VAL_19_SBcAP_id_Cause = 1; */ + ie = sbcap_alloc_Error_Indication_IE(1, SBcAP_Criticality_ignore, + SBcAP_ErrorIndicationIEs__value_PR_Cause); + ie->value.choice.Cause = cause; + ASN_SEQUENCE_ADD(as_pdu, ie); + + if (rx_pdu) { + SBcAP_Criticality_Diagnostics_t *diag_ie; + /* Criticality Diagnostics, Optional: + * 3GPP TS 36.413 4.3.4.3.3 + * static const long asn_VAL_20_SBcAP_id_Criticality_Diagnostics = 2; */ + ie = sbcap_alloc_Error_Indication_IE(1, SBcAP_Criticality_ignore, + SBcAP_ErrorIndicationIEs__value_PR_Criticality_Diagnostics); + diag_ie = &ie->value.choice.Criticality_Diagnostics; + diag_ie->procedureCode = MALLOC(sizeof(*diag_ie->procedureCode)); + *diag_ie->procedureCode = sbcap_pdu_get_procedure_code(rx_pdu); + diag_ie->triggeringMessage = MALLOC(sizeof(*diag_ie->triggeringMessage)); + *diag_ie->triggeringMessage = rx_pdu->present; + diag_ie->procedureCriticality = MALLOC(sizeof(*diag_ie->procedureCriticality)); + *diag_ie->procedureCriticality = sbcap_pdu_get_criticality(rx_pdu); + ASN_SEQUENCE_ADD(as_pdu, ie); + } + return pdu; +}