From 4d40047c50ef916e6b1a38bd77567bc1b4857122 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Tue, 26 Jan 2021 12:57:13 +0100 Subject: gprs_bssgp: agregate RIM related code in gprs_bssgp_rim.c gprs_bssgp and gprs_bssgp_util.c also contains code related to send and receive RIM PDUs via BSSGP and also code to encode and decode RAN INFORMATION PDUs. Lets move this to gprs_bssgp_rim.c Change-Id: Icda279452962b06e552cb1361d2a27b7dc8a6b04 Related: SYS#5103 --- src/gb/gprs_bssgp.c | 41 +------ src/gb/gprs_bssgp_internal.h | 2 + src/gb/gprs_bssgp_rim.c | 270 +++++++++++++++++++++++++++++++++++++++++++ src/gb/gprs_bssgp_util.c | 220 ----------------------------------- 4 files changed, 273 insertions(+), 260 deletions(-) (limited to 'src/gb') diff --git a/src/gb/gprs_bssgp.c b/src/gb/gprs_bssgp.c index 4154c4b5..926b0efa 100644 --- a/src/gb/gprs_bssgp.c +++ b/src/gb/gprs_bssgp.c @@ -41,6 +41,7 @@ #include #include "osmocom/gsm/gsm48.h" +#include "gprs_bssgp_internal.h" void *bssgp_tall_ctx = NULL; @@ -647,46 +648,6 @@ int bssgp_rx_status(struct msgb *msg, struct tlv_parsed *tp, return bssgp_prim_cb(&nmp.oph, NULL); } -static int bssgp_rx_rim(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci) -{ - struct osmo_bssgp_prim nmp; - uint16_t nsei = msgb_nsei(msg); - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg); - enum bssgp_prim prim; - char ri_src_str[64]; - char ri_dest_str[64]; - - /* Specify PRIM type based on the RIM PDU */ - switch (bgph->pdu_type) { - case BSSGP_PDUT_RAN_INFO: - case BSSGP_PDUT_RAN_INFO_REQ: - case BSSGP_PDUT_RAN_INFO_ACK: - case BSSGP_PDUT_RAN_INFO_ERROR: - case BSSGP_PDUT_RAN_INFO_APP_ERROR: - prim = PRIM_BSSGP_RIM_PDU_TRANSFER; - break; - default: - /* Caller already makes sure that this can't happen. */ - OSMO_ASSERT(false); - } - - /* Send BSSGP RIM indication to NM */ - memset(&nmp, 0, sizeof(nmp)); - nmp.nsei = nsei; - nmp.bvci = bvci; - nmp.tp = tp; - if (bssgp_parse_rim_pdu(&nmp.u.rim_pdu, msg) < 0) - return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); - DEBUGP(DLBSSGP, "BSSGP BVCI=%u Rx RIM-PDU:%s, src=%s, dest=%s\n", - bvci, bssgp_pdu_str(bgph->pdu_type), - bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &nmp.u.rim_pdu.routing_info_src), - bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &nmp.u.rim_pdu.routing_info_dest)); - osmo_prim_init(&nmp.oph, SAP_BSSGP_RIM, prim, PRIM_OP_INDICATION, msg); - bssgp_prim_cb(&nmp.oph, NULL); - - return 0; -} - /* One element (msgb) in a BSSGP Flow Control queue */ struct bssgp_fc_queue_element { /* linked list of queue elements */ diff --git a/src/gb/gprs_bssgp_internal.h b/src/gb/gprs_bssgp_internal.h index 2ada027c..5022d32d 100644 --- a/src/gb/gprs_bssgp_internal.h +++ b/src/gb/gprs_bssgp_internal.h @@ -5,3 +5,5 @@ extern bssgp_bvc_send bssgp_ns_send; extern void *bssgp_ns_send_data; + +int bssgp_rx_rim(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci); diff --git a/src/gb/gprs_bssgp_rim.c b/src/gb/gprs_bssgp_rim.c index 25f94066..63b303e5 100644 --- a/src/gb/gprs_bssgp_rim.c +++ b/src/gb/gprs_bssgp_rim.c @@ -27,6 +27,7 @@ #include #include #include +#include "gprs_bssgp_internal.h" /* TVLV IEs use a variable length field. To be sure we will do all buffer * length checks with the maximum possible header length, which is @@ -949,3 +950,272 @@ int bssgp_enc_ran_inf_app_err_rim_cont(uint8_t *buf, size_t len, const struct bs return (int)(buf_ptr - buf); } + +/*! Parse a given message buffer into a rim-pdu struct. + * \param[out] pdu user provided memory for the resulting RAN INFORMATION PDU. + * \param[in] msg BSSGP message buffer that contains the encoded RAN INFORMATION PDU. + * \returns 0 on sccess, -EINVAL on error. */ +int bssgp_parse_rim_pdu(struct bssgp_ran_information_pdu *pdu, const struct msgb *msg) +{ + struct tlv_parsed tp[2]; + struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg); + int data_len; + int rc; + uint16_t nsei = msgb_nsei(msg); + + memset(pdu, 0, sizeof(*pdu)); + + data_len = msgb_bssgp_len(msg) - sizeof(*bgph); + if (data_len < 0) + return -EINVAL; + + rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, tp, ARRAY_SIZE(tp), bgph->pdu_type, bgph->data, data_len, 0, 0, + DLBSSGP, __func__); + if (rc < 0) + return -EINVAL; + + if (TLVP_PRESENT(&tp[0], BSSGP_IE_RIM_ROUTING_INFO)) { + rc = bssgp_parse_rim_ri(&pdu->routing_info_dest, TLVP_VAL(&tp[0], BSSGP_IE_RIM_ROUTING_INFO), + TLVP_LEN(&tp[0], BSSGP_IE_RIM_ROUTING_INFO)); + if (rc < 0) { + LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei); + return -EINVAL; + } + } else { + LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Destination Cell Identifier IE\n", nsei); + return -EINVAL; + } + + if (TLVP_PRESENT(&tp[1], BSSGP_IE_RIM_ROUTING_INFO)) { + rc = bssgp_parse_rim_ri(&pdu->routing_info_src, TLVP_VAL(&tp[1], BSSGP_IE_RIM_ROUTING_INFO), + TLVP_LEN(&tp[1], BSSGP_IE_RIM_ROUTING_INFO)); + if (rc < 0) { + LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei); + return -EINVAL; + } + } else { + LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Source Cell Identifier IE\n", nsei); + return -EINVAL; + } + + if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_REQ_RIM_CONTAINER)) + pdu->rim_cont_iei = BSSGP_IE_RI_REQ_RIM_CONTAINER; + else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_RIM_CONTAINER)) + pdu->rim_cont_iei = BSSGP_IE_RI_RIM_CONTAINER; + else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_APP_ERROR_RIM_CONT)) + pdu->rim_cont_iei = BSSGP_IE_RI_APP_ERROR_RIM_CONT; + else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ACK_RIM_CONTAINER)) + pdu->rim_cont_iei = BSSGP_IE_RI_ACK_RIM_CONTAINER; + else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ERROR_RIM_COINTAINER)) + pdu->rim_cont_iei = BSSGP_IE_RI_ERROR_RIM_COINTAINER; + else { + LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing or wrong RIM Container IE\n", nsei); + return -EINVAL; + } + + pdu->rim_cont = TLVP_VAL(&tp[0], pdu->rim_cont_iei); + pdu->rim_cont_len = TLVP_LEN(&tp[0], pdu->rim_cont_iei); + + /* Make sure the rim container field is not empty */ + if (pdu->rim_cont_len < 1) + return -EINVAL; + if (!pdu->rim_cont) + return -EINVAL; + + /* Note: It is not an error if we fail to parse the RIM container, + * since there are applications where parsing the RIM container + * is not necessary (routing). It is up to the API user to check + * the results. */ + switch (pdu->rim_cont_iei) { + case BSSGP_IE_RI_REQ_RIM_CONTAINER: + rc = bssgp_dec_ran_inf_req_rim_cont(&pdu->decoded.req_rim_cont, pdu->rim_cont, pdu->rim_cont_len); + break; + case BSSGP_IE_RI_RIM_CONTAINER: + rc = bssgp_dec_ran_inf_rim_cont(&pdu->decoded.rim_cont, pdu->rim_cont, pdu->rim_cont_len); + break; + case BSSGP_IE_RI_APP_ERROR_RIM_CONT: + rc = bssgp_dec_ran_inf_app_err_rim_cont(&pdu->decoded.app_err_rim_cont, pdu->rim_cont, + pdu->rim_cont_len); + break; + case BSSGP_IE_RI_ACK_RIM_CONTAINER: + rc = bssgp_dec_ran_inf_ack_rim_cont(&pdu->decoded.ack_rim_cont, pdu->rim_cont, pdu->rim_cont_len); + break; + case BSSGP_IE_RI_ERROR_RIM_COINTAINER: + rc = bssgp_dec_ran_inf_err_rim_cont(&pdu->decoded.err_rim_cont, pdu->rim_cont, pdu->rim_cont_len); + break; + default: + LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) cannot parse unknown RIM container.\n", nsei); + return 0; + } + if (rc < 0) { + LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) unable to parse RIM container.\n", nsei); + return 0; + } + pdu->decoded_present = true; + + return 0; +} + +/*! Encode a given rim-pdu struct into a message buffer. + * \param[out] pdu user provided memory that contains the RAN INFORMATION PDU to encode. + * \returns BSSGP message buffer on sccess, NULL on error. */ +struct msgb *bssgp_encode_rim_pdu(const struct bssgp_ran_information_pdu *pdu) +{ + struct msgb *msg = bssgp_msgb_alloc(); + struct bssgp_normal_hdr *bgph; + uint8_t rim_ri_buf[BSSGP_RIM_ROUTING_INFO_MAXLEN]; + uint8_t *rim_cont_buf; + int rc; + + if (!msg) + return NULL; + bgph = (struct bssgp_normal_hdr *)msgb_put(msg, sizeof(*bgph)); + + /* Set PDU type based on RIM container type */ + switch (pdu->rim_cont_iei) { + case BSSGP_IE_RI_REQ_RIM_CONTAINER: + bgph->pdu_type = BSSGP_PDUT_RAN_INFO_REQ; + break; + case BSSGP_IE_RI_RIM_CONTAINER: + bgph->pdu_type = BSSGP_PDUT_RAN_INFO; + break; + case BSSGP_IE_RI_APP_ERROR_RIM_CONT: + bgph->pdu_type = BSSGP_PDUT_RAN_INFO_APP_ERROR; + break; + case BSSGP_IE_RI_ACK_RIM_CONTAINER: + bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ACK; + break; + case BSSGP_IE_RI_ERROR_RIM_COINTAINER: + bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ERROR; + break; + default: + /* The caller must correctly specify the container type! */ + OSMO_ASSERT(false); + } + + /* Put RIM routing information */ + rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_dest); + if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN) + goto error; + msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf); + rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_src); + if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN) + goto error; + msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf); + + /* Put RIM container */ + if (pdu->decoded_present) { + rim_cont_buf = talloc_zero_size(msg, msg->data_len); + if (!rim_cont_buf) + goto error; + + switch (pdu->rim_cont_iei) { + case BSSGP_IE_RI_REQ_RIM_CONTAINER: + rc = bssgp_enc_ran_inf_req_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.req_rim_cont); + break; + case BSSGP_IE_RI_RIM_CONTAINER: + rc = bssgp_enc_ran_inf_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.rim_cont); + break; + case BSSGP_IE_RI_APP_ERROR_RIM_CONT: + rc = bssgp_enc_ran_inf_app_err_rim_cont(rim_cont_buf, msg->data_len, + &pdu->decoded.app_err_rim_cont); + break; + case BSSGP_IE_RI_ACK_RIM_CONTAINER: + rc = bssgp_enc_ran_inf_ack_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.ack_rim_cont); + break; + case BSSGP_IE_RI_ERROR_RIM_COINTAINER: + rc = bssgp_enc_ran_inf_err_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.err_rim_cont); + break; + default: + /* The API user must set the iei properly! */ + OSMO_ASSERT(false); + } + if (rc < 0) + goto error; + + msgb_tvlv_put(msg, pdu->rim_cont_iei, rc, rim_cont_buf); + talloc_free(rim_cont_buf); + } else { + /* Make sure the RIM container is actually present. */ + OSMO_ASSERT(pdu->rim_cont_iei != 0 && pdu->rim_cont_len > 0 && pdu->rim_cont); + msgb_tvlv_put(msg, pdu->rim_cont_iei, pdu->rim_cont_len, pdu->rim_cont); + } + + return msg; +error: + talloc_free(rim_cont_buf); + msgb_free(msg); + return 0; +} + +/*! Send RIM RAN INFORMATION REQUEST via BSSGP (3GPP TS 48.018, section 10.6.1). + * \param[in] pdu user provided memory for the RAN INFORMATION PDU to be sent. + * \param[in] nsei BSSGP network service entity identifier (NSEI). + * \returns 0 on sccess, -EINVAL on error. */ +int bssgp_tx_rim(const struct bssgp_ran_information_pdu *pdu, uint16_t nsei) +{ + struct msgb *msg; + struct bssgp_normal_hdr *bgph; + char ri_src_str[64]; + char ri_dest_str[64]; + + /* Encode RIM PDU into mesage buffer */ + msg = bssgp_encode_rim_pdu(pdu); + if (!msg) { + LOGP(DLBSSGP, LOGL_ERROR, + "BSSGP RIM (NSEI=%u) unable to encode BSSGP RIM PDU\n", nsei); + return -EINVAL; + } + + msgb_nsei(msg) = nsei; + msgb_bvci(msg) = 0; /* Signalling */ + + bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg); + DEBUGP(DLBSSGP, "BSSGP BVCI=0 Tx RIM-PDU:%s, src=%s, dest=%s\n", + bssgp_pdu_str(bgph->pdu_type), + bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &pdu->routing_info_src), + bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &pdu->routing_info_dest)); + + return bssgp_ns_send(bssgp_ns_send_data, msg); +} + +/* For internal use only (called from gprs_bssgp.c) */ +int bssgp_rx_rim(struct msgb *msg, struct tlv_parsed *tp, uint16_t bvci) +{ + struct osmo_bssgp_prim nmp; + uint16_t nsei = msgb_nsei(msg); + struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg); + enum bssgp_prim prim; + char ri_src_str[64]; + char ri_dest_str[64]; + + /* Specify PRIM type based on the RIM PDU */ + switch (bgph->pdu_type) { + case BSSGP_PDUT_RAN_INFO: + case BSSGP_PDUT_RAN_INFO_REQ: + case BSSGP_PDUT_RAN_INFO_ACK: + case BSSGP_PDUT_RAN_INFO_ERROR: + case BSSGP_PDUT_RAN_INFO_APP_ERROR: + prim = PRIM_BSSGP_RIM_PDU_TRANSFER; + break; + default: + /* Caller already makes sure that this can't happen. */ + OSMO_ASSERT(false); + } + + /* Send BSSGP RIM indication to NM */ + memset(&nmp, 0, sizeof(nmp)); + nmp.nsei = nsei; + nmp.bvci = bvci; + nmp.tp = tp; + if (bssgp_parse_rim_pdu(&nmp.u.rim_pdu, msg) < 0) + return bssgp_tx_status(BSSGP_CAUSE_MISSING_MAND_IE, NULL, msg); + DEBUGP(DLBSSGP, "BSSGP BVCI=%u Rx RIM-PDU:%s, src=%s, dest=%s\n", + bvci, bssgp_pdu_str(bgph->pdu_type), + bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &nmp.u.rim_pdu.routing_info_src), + bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &nmp.u.rim_pdu.routing_info_dest)); + osmo_prim_init(&nmp.oph, SAP_BSSGP_RIM, prim, PRIM_OP_INDICATION, msg); + bssgp_prim_cb(&nmp.oph, NULL); + + return 0; +} diff --git a/src/gb/gprs_bssgp_util.c b/src/gb/gprs_bssgp_util.c index e00aed96..92896c1f 100644 --- a/src/gb/gprs_bssgp_util.c +++ b/src/gb/gprs_bssgp_util.c @@ -588,223 +588,3 @@ int bssgp_tx_status(uint8_t cause, uint16_t *bvci, struct msgb *orig_msg) return bssgp_ns_send(bssgp_ns_send_data, msg); } - -/* Chapter 10.6.1: RAN-INFORMATION-REQUEST */ -int bssgp_tx_rim(const struct bssgp_ran_information_pdu *pdu, uint16_t nsei) -{ - struct msgb *msg; - struct bssgp_normal_hdr *bgph; - char ri_src_str[64]; - char ri_dest_str[64]; - - /* Encode RIM PDU into mesage buffer */ - msg = bssgp_encode_rim_pdu(pdu); - if (!msg) { - LOGP(DLBSSGP, LOGL_ERROR, - "BSSGP RIM (NSEI=%u) unable to encode BSSGP RIM PDU\n", nsei); - return -EINVAL; - } - - msgb_nsei(msg) = nsei; - msgb_bvci(msg) = 0; /* Signalling */ - - bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg); - DEBUGP(DLBSSGP, "BSSGP BVCI=0 Tx RIM-PDU:%s, src=%s, dest=%s\n", - bssgp_pdu_str(bgph->pdu_type), - bssgp_rim_ri_name_buf(ri_src_str, sizeof(ri_src_str), &pdu->routing_info_src), - bssgp_rim_ri_name_buf(ri_dest_str, sizeof(ri_dest_str), &pdu->routing_info_dest)); - - return bssgp_ns_send(bssgp_ns_send_data, msg); -} - -/* Parse a given message buffer into a rim-pdu struct */ -int bssgp_parse_rim_pdu(struct bssgp_ran_information_pdu *pdu, const struct msgb *msg) -{ - struct tlv_parsed tp[2]; - struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *)msgb_bssgph(msg); - int data_len; - int rc; - uint16_t nsei = msgb_nsei(msg); - - memset(pdu, 0, sizeof(*pdu)); - - data_len = msgb_bssgp_len(msg) - sizeof(*bgph); - if (data_len < 0) - return -EINVAL; - - rc = osmo_tlv_prot_parse(&osmo_pdef_bssgp, tp, ARRAY_SIZE(tp), bgph->pdu_type, bgph->data, data_len, 0, 0, - DLBSSGP, __func__); - if (rc < 0) - return -EINVAL; - - if (TLVP_PRESENT(&tp[0], BSSGP_IE_RIM_ROUTING_INFO)) { - rc = bssgp_parse_rim_ri(&pdu->routing_info_dest, TLVP_VAL(&tp[0], BSSGP_IE_RIM_ROUTING_INFO), - TLVP_LEN(&tp[0], BSSGP_IE_RIM_ROUTING_INFO)); - if (rc < 0) { - LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei); - return -EINVAL; - } - } else { - LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Destination Cell Identifier IE\n", nsei); - return -EINVAL; - } - - if (TLVP_PRESENT(&tp[1], BSSGP_IE_RIM_ROUTING_INFO)) { - rc = bssgp_parse_rim_ri(&pdu->routing_info_src, TLVP_VAL(&tp[1], BSSGP_IE_RIM_ROUTING_INFO), - TLVP_LEN(&tp[1], BSSGP_IE_RIM_ROUTING_INFO)); - if (rc < 0) { - LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) invalid Destination Cell Identifier IE\n", nsei); - return -EINVAL; - } - } else { - LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing Source Cell Identifier IE\n", nsei); - return -EINVAL; - } - - if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_REQ_RIM_CONTAINER)) - pdu->rim_cont_iei = BSSGP_IE_RI_REQ_RIM_CONTAINER; - else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_RIM_CONTAINER)) - pdu->rim_cont_iei = BSSGP_IE_RI_RIM_CONTAINER; - else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_APP_ERROR_RIM_CONT)) - pdu->rim_cont_iei = BSSGP_IE_RI_APP_ERROR_RIM_CONT; - else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ACK_RIM_CONTAINER)) - pdu->rim_cont_iei = BSSGP_IE_RI_ACK_RIM_CONTAINER; - else if (TLVP_PRESENT(&tp[0], BSSGP_IE_RI_ERROR_RIM_COINTAINER)) - pdu->rim_cont_iei = BSSGP_IE_RI_ERROR_RIM_COINTAINER; - else { - LOGP(DLBSSGP, LOGL_ERROR, "BSSGP RIM (NSEI=%u) missing or wrong RIM Container IE\n", nsei); - return -EINVAL; - } - - pdu->rim_cont = TLVP_VAL(&tp[0], pdu->rim_cont_iei); - pdu->rim_cont_len = TLVP_LEN(&tp[0], pdu->rim_cont_iei); - - /* Make sure the rim container field is not empty */ - if (pdu->rim_cont_len < 1) - return -EINVAL; - if (!pdu->rim_cont) - return -EINVAL; - - /* Note: It is not an error if we fail to parse the RIM container, - * since there are applications where parsing the RIM container - * is not necessary (routing). It is up to the API user to check - * the results. */ - switch (pdu->rim_cont_iei) { - case BSSGP_IE_RI_REQ_RIM_CONTAINER: - rc = bssgp_dec_ran_inf_req_rim_cont(&pdu->decoded.req_rim_cont, pdu->rim_cont, pdu->rim_cont_len); - break; - case BSSGP_IE_RI_RIM_CONTAINER: - rc = bssgp_dec_ran_inf_rim_cont(&pdu->decoded.rim_cont, pdu->rim_cont, pdu->rim_cont_len); - break; - case BSSGP_IE_RI_APP_ERROR_RIM_CONT: - rc = bssgp_dec_ran_inf_app_err_rim_cont(&pdu->decoded.app_err_rim_cont, pdu->rim_cont, - pdu->rim_cont_len); - break; - case BSSGP_IE_RI_ACK_RIM_CONTAINER: - rc = bssgp_dec_ran_inf_ack_rim_cont(&pdu->decoded.ack_rim_cont, pdu->rim_cont, pdu->rim_cont_len); - break; - case BSSGP_IE_RI_ERROR_RIM_COINTAINER: - rc = bssgp_dec_ran_inf_err_rim_cont(&pdu->decoded.err_rim_cont, pdu->rim_cont, pdu->rim_cont_len); - break; - default: - LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) cannot parse unknown RIM container.\n", nsei); - return 0; - } - if (rc < 0) { - LOGP(DLBSSGP, LOGL_DEBUG, "BSSGP RIM (NSEI=%u) unable to parse RIM container.\n", nsei); - return 0; - } - pdu->decoded_present = true; - - return 0; -} - -/* Encode a given rim-pdu struct into a message buffer */ -struct msgb *bssgp_encode_rim_pdu(const struct bssgp_ran_information_pdu *pdu) -{ - struct msgb *msg = bssgp_msgb_alloc(); - struct bssgp_normal_hdr *bgph; - uint8_t rim_ri_buf[BSSGP_RIM_ROUTING_INFO_MAXLEN]; - uint8_t *rim_cont_buf; - int rc; - - if (!msg) - return NULL; - bgph = (struct bssgp_normal_hdr *)msgb_put(msg, sizeof(*bgph)); - - /* Set PDU type based on RIM container type */ - switch (pdu->rim_cont_iei) { - case BSSGP_IE_RI_REQ_RIM_CONTAINER: - bgph->pdu_type = BSSGP_PDUT_RAN_INFO_REQ; - break; - case BSSGP_IE_RI_RIM_CONTAINER: - bgph->pdu_type = BSSGP_PDUT_RAN_INFO; - break; - case BSSGP_IE_RI_APP_ERROR_RIM_CONT: - bgph->pdu_type = BSSGP_PDUT_RAN_INFO_APP_ERROR; - break; - case BSSGP_IE_RI_ACK_RIM_CONTAINER: - bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ACK; - break; - case BSSGP_IE_RI_ERROR_RIM_COINTAINER: - bgph->pdu_type = BSSGP_PDUT_RAN_INFO_ERROR; - break; - default: - /* The caller must correctly specify the container type! */ - OSMO_ASSERT(false); - } - - /* Put RIM routing information */ - rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_dest); - if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN) - goto error; - msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf); - rc = bssgp_create_rim_ri(rim_ri_buf, &pdu->routing_info_src); - if (rc < 0 || rc > BSSGP_RIM_ROUTING_INFO_MAXLEN) - goto error; - msgb_tvlv_put(msg, BSSGP_IE_RIM_ROUTING_INFO, rc, rim_ri_buf); - - /* Put RIM container */ - if (pdu->decoded_present) { - rim_cont_buf = talloc_zero_size(msg, msg->data_len); - if (!rim_cont_buf) - goto error; - - switch (pdu->rim_cont_iei) { - case BSSGP_IE_RI_REQ_RIM_CONTAINER: - rc = bssgp_enc_ran_inf_req_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.req_rim_cont); - break; - case BSSGP_IE_RI_RIM_CONTAINER: - rc = bssgp_enc_ran_inf_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.rim_cont); - break; - case BSSGP_IE_RI_APP_ERROR_RIM_CONT: - rc = bssgp_enc_ran_inf_app_err_rim_cont(rim_cont_buf, msg->data_len, - &pdu->decoded.app_err_rim_cont); - break; - case BSSGP_IE_RI_ACK_RIM_CONTAINER: - rc = bssgp_enc_ran_inf_ack_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.ack_rim_cont); - break; - case BSSGP_IE_RI_ERROR_RIM_COINTAINER: - rc = bssgp_enc_ran_inf_err_rim_cont(rim_cont_buf, msg->data_len, &pdu->decoded.err_rim_cont); - break; - default: - /* The API user must set the iei properly! */ - OSMO_ASSERT(false); - } - if (rc < 0) - goto error; - - msgb_tvlv_put(msg, pdu->rim_cont_iei, rc, rim_cont_buf); - talloc_free(rim_cont_buf); - } else { - /* Make sure the RIM container is actually present. */ - OSMO_ASSERT(pdu->rim_cont_iei != 0 && pdu->rim_cont_len > 0 && pdu->rim_cont); - msgb_tvlv_put(msg, pdu->rim_cont_iei, pdu->rim_cont_len, pdu->rim_cont); - } - - return msg; -error: - talloc_free(rim_cont_buf); - msgb_free(msg); - return 0; -} -- cgit v1.2.3