This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
dexter gerrit-no-reply at lists.osmocom.orgdexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/21862 ) Change subject: bssgp_rim: add encoder/decoder for NACC related RIM containers ...................................................................... bssgp_rim: add encoder/decoder for NACC related RIM containers BSSGP RIM uses a number of nested containers to signal generic RIM application specific payload information. Lets add the container structurs required for NACC. Change-Id: Ibbc7fd67658e3040c12abb5706fe9d1f31894352 Related: SYS#5103 --- M include/Makefile.am A include/osmocom/gprs/gprs_bssgp_rim.h M src/gb/Makefile.am A src/gb/gprs_bssgp_rim.c M src/gb/libosmogb.map M tests/Makefile.am A tests/gb/gprs_bssgp_rim_test.c A tests/gb/gprs_bssgp_rim_test.ok M tests/testsuite.at 9 files changed, 1,362 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/62/21862/1 diff --git a/include/Makefile.am b/include/Makefile.am index 842b872..2e3237d 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -68,6 +68,7 @@ osmocom/gprs/gprs_bssgp.h \ osmocom/gprs/gprs_bssgp2.h \ osmocom/gprs/gprs_bssgp_bss.h \ + osmocom/gprs/gprs_bssgp_rim.h \ osmocom/gprs/gprs_msgb.h \ osmocom/gprs/gprs_ns.h \ osmocom/gprs/gprs_ns_frgre.h \ diff --git a/include/osmocom/gprs/gprs_bssgp_rim.h b/include/osmocom/gprs/gprs_bssgp_rim.h new file mode 100644 index 0000000..c801c29 --- /dev/null +++ b/include/osmocom/gprs/gprs_bssgp_rim.h @@ -0,0 +1,129 @@ +#pragma once + +#include <osmocom/gprs/protocol/gsm_08_18.h> + +/* 3GPP TS 48.018, table 11.3.62a.1.b: RAN-INFORMATION-REQUEST RIM Container Contents */ +struct bssgp_ran_inf_req_rim_cont { + uint8_t app_id; + uint32_t seq_num; + struct bssgp_rim_pdu_ind pdu_ind; + uint8_t prot_ver; + + /* Pointer to nested containers */ + const uint8_t *app_cont; + size_t app_cont_len; + const uint8_t *son_trans_app_id; + size_t son_trans_app_id_len; +}; + +int bssgp_dec_ran_inf_req_rim_cont(struct bssgp_ran_inf_req_rim_cont *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_req_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_req_rim_cont *cont); + +/* 3GPP TS 48.018, table 11.3.62a.2.b: RAN-INFORMATION RIM Container Contents */ +struct bssgp_ran_inf_rim_cont { + uint8_t app_id; + uint32_t seq_num; + struct bssgp_rim_pdu_ind pdu_ind; + uint8_t prot_ver; + + /* Pointer to nested containers */ + const uint8_t *app_cont; + size_t app_cont_len; + const uint8_t *app_err_cont; + size_t app_err_cont_len; + const uint8_t *son_trans_app_id; + size_t son_trans_app_id_len; +}; + +int bssgp_dec_ran_inf_rim_cont(struct bssgp_ran_inf_rim_cont *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_rim_cont *cont); + +/* 3GPP TS 48.018, table 11.3.62a.3.b: RAN-INFORMATION-ACK RIM Container Contents */ +struct bssgp_ran_inf_ack_rim_cont { + uint8_t app_id; + uint32_t seq_num; + uint8_t prot_ver; + + /* Pointer to nested containers */ + const uint8_t *son_trans_app_id; + size_t son_trans_app_id_len; +}; + +int bssgp_dec_ran_inf_ack_rim_cont(struct bssgp_ran_inf_ack_rim_cont *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_ack_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_ack_rim_cont *cont); + +/* 3GPP TS 48.018, table 11.3.62a.4.b: RAN-INFORMATION-ERROR RIM Container Contents */ +struct bssgp_ran_inf_err_rim_cont { + uint8_t app_id; + uint8_t cause; + uint8_t prot_ver; + + /* Pointer to nested containers */ + const uint8_t *err_pdu; + size_t err_pdu_len; + const uint8_t *son_trans_app_id; + size_t son_trans_app_id_len; +}; + +int bssgp_dec_ran_inf_err_rim_cont(struct bssgp_ran_inf_err_rim_cont *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_err_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_err_rim_cont *cont); + +/* 3GPP TS 48.018, table 11.3.62a.5.b: RAN-INFORMATION-APPLICATION-ERROR RIM Container Contents */ +struct bssgp_ran_inf_app_err_rim_cont { + uint8_t app_id; + uint32_t seq_num; + struct bssgp_rim_pdu_ind pdu_ind; + uint8_t prot_ver; + + /* Pointer to nested containers */ + const uint8_t *app_err_cont; + size_t app_err_cont_len; +}; + +int bssgp_dec_ran_inf_app_err_rim_cont(struct bssgp_ran_inf_app_err_rim_cont *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_app_err_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_app_err_rim_cont *cont); + +/* 3GPP TS 48.018, table 11.3.63.1.1: RAN-INFORMATION-REQUEST Application Container coding for NACC */ +struct bssgp_ran_inf_req_app_cont_nacc { + struct { + struct gprs_ra_id raid; + uint16_t cid; + } reprt_cell; +}; + +int bssgp_dec_ran_inf_req_app_cont_nacc(struct bssgp_ran_inf_req_app_cont_nacc *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_req_app_cont_nacc(uint8_t *buf, size_t len, const struct bssgp_ran_inf_req_app_cont_nacc *cont); + +/* 3GPP TS 48.018, table 11.3.63.2.1.a: RAN-INFORMATION Application Container coding for NACC */ +struct bssgp_ran_inf_app_cont_nacc { + struct { + struct gprs_ra_id raid; + uint16_t cid; + } reprt_cell; + bool type_psi; + uint8_t num_si; + const uint8_t *si[127]; +}; + +int bssgp_dec_ran_inf_app_cont_nacc(struct bssgp_ran_inf_app_cont_nacc *cont, const uint8_t *buf, size_t len); +int bssgp_enc_ran_inf_app_cont_nacc(uint8_t *buf, size_t len, const struct bssgp_ran_inf_app_cont_nacc *cont); + +/* 3GPP TS 48.018, table 11.3.64.1.b, NACC Cause coding */ +enum bssgp_nacc_cause { + BSSGP_NACC_CAUSE_UNSPEC, + BSSGP_NACC_CAUSE_SYNTAX_ERR, + BSSGP_NACC_CAUSE_RPRT_CELL_MISSMTCH, + BSSGP_NACC_CAUSE_SIPSI_TYPE_ERR, + BSSGP_NACC_CAUSE_SIPSI_LEN_ERR, + BSSGP_NACC_CAUSE_SIPSI_SET_ERR, +}; + +/* 3GPP TS 48.018, table 11.3.64.1.a, Application Error Container coding for NACC */ +struct bssgp_app_err_cont_nacc { + enum bssgp_nacc_cause nacc_cause; + const uint8_t *err_app_cont; + size_t err_app_cont_len; +}; + +int bssgp_dec_app_err_cont_nacc(struct bssgp_app_err_cont_nacc *cont, const uint8_t *buf, size_t len); +int bssgp_enc_app_err_cont_nacc(uint8_t *buf, size_t len, const struct bssgp_app_err_cont_nacc *cont); diff --git a/src/gb/Makefile.am b/src/gb/Makefile.am index c829c29..93e4f0e 100644 --- a/src/gb/Makefile.am +++ b/src/gb/Makefile.am @@ -22,7 +22,7 @@ $(top_builddir)/src/gsm/libosmogsm.la libosmogb_la_SOURCES = gprs_ns.c gprs_ns_frgre.c gprs_ns_vty.c gprs_ns_sns.c \ - gprs_bssgp.c gprs_bssgp_util.c gprs_bssgp_vty.c \ + gprs_bssgp.c gprs_bssgp_util.c gprs_bssgp_vty.c gprs_bssgp_rim.c \ gprs_bssgp_bss.c \ gprs_ns2.c gprs_ns2_udp.c gprs_ns2_frgre.c gprs_ns2_fr.c gprs_ns2_vc_fsm.c gprs_ns2_sns.c \ gprs_ns2_message.c gprs_ns2_vty.c gprs_ns2_vty2.c \ diff --git a/src/gb/gprs_bssgp_rim.c b/src/gb/gprs_bssgp_rim.c new file mode 100644 index 0000000..f6aeb1d --- /dev/null +++ b/src/gb/gprs_bssgp_rim.c @@ -0,0 +1,509 @@ +/*! \file gprs_bssgp.c + * GPRS BSSGP RIM protocol implementation as per 3GPP TS 48.018. */ +/* + * (C) 2020 by sysmocom - s.f.m.c. GmbH + * Author: Philipp Maier <pmaier at sysmocom.de> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <errno.h> +#include <osmocom/gprs/gprs_bssgp.h> +#include <osmocom/gprs/gprs_bssgp_rim.h> + +/* See also 3GPP TS 48.018 table 11.3.62a.1.b, table 11.3.62a.2.b, and table 11.3.62a.5.b. Those container + * types share common IEs. */ +#define DEC_RIM_CONT_COMMON \ + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_APP_IDENTITY)) \ + cont->app_id = TLVP_VAL(&tp, BSSGP_IE_RIM_APP_IDENTITY)[0]; \ + else \ + return -EINVAL; \ + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_SEQ_NR)) \ + cont->seq_num = tlvp_val32be(&tp, BSSGP_IE_RIM_SEQ_NR); \ + else \ + return -EINVAL; \ + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_PDU_INDICATIONS)) \ + memcpy(&cont->pdu_ind, TLVP_VAL(&tp, BSSGP_IE_RIM_PDU_INDICATIONS), sizeof(cont->pdu_ind)); \ + else \ + return -EINVAL; \ + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_PROTOCOL_VERSION)) \ + cont->prot_ver = TLVP_VAL(&tp, BSSGP_IE_RIM_PROTOCOL_VERSION)[0]; \ + else \ + cont->prot_ver = 1; + +/* (requires max. 15 octets of memory, see also comment above) */ +#define ENC_RIM_CONT_COMMON \ + uint32_t seq_num = osmo_htonl(cont->seq_num); \ + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_APP_IDENTITY, 1, &cont->app_id); \ + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_SEQ_NR, 4, (uint8_t*)&seq_num); \ + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_PDU_INDICATIONS, sizeof(cont->pdu_ind), (uint8_t*)&cont->pdu_ind); \ + if (cont->prot_ver > 0) \ + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_PROTOCOL_VERSION, 1, &cont->prot_ver); \ + +/*! Decode a RAN Information Request RIM Container (3GPP TS 48.018, table 11.3.62a.1.b). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_req_rim_cont(struct bssgp_ran_inf_req_rim_cont *cont, const uint8_t *buf, size_t len) +{ + int rc; + struct tlv_parsed tp; + + memset(cont, 0, sizeof(*cont)); + + rc = tlv_parse(&tp, &tvlv_att_def, buf, len, 0, 0); + if (rc < 0) + return -EINVAL; + + DEC_RIM_CONT_COMMON if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_REQ_APP_CONTAINER)) { + cont->app_cont = TLVP_VAL(&tp, BSSGP_IE_RIM_REQ_APP_CONTAINER); + cont->app_cont_len = TLVP_LEN(&tp, BSSGP_IE_RIM_REQ_APP_CONTAINER); + } else { + cont->app_cont = NULL; + cont->app_cont_len = 0; + } + + if (TLVP_PRESENT(&tp, BSSGP_IE_SON_TRANSFER_APP_ID)) { + cont->son_trans_app_id = TLVP_VAL(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + cont->son_trans_app_id_len = TLVP_LEN(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + } else { + cont->son_trans_app_id = NULL; + cont->son_trans_app_id_len = 0; + } + + return 0; +} + +/*! Encode a RAN Information Request RIM Container (3GPP TS 48.018, table 11.3.62a.1.b). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_req_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_req_rim_cont *cont) +{ + uint8_t *buf_ptr = buf; + + if (len < 15 + cont->app_cont_len + cont->son_trans_app_id_len) + return -EINVAL; + + ENC_RIM_CONT_COMMON; + + if (cont->app_cont && cont->app_cont_len > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_REQ_APP_CONTAINER, cont->app_cont_len, cont->app_cont); + + if (cont->son_trans_app_id && cont->son_trans_app_id_len > 0) + buf_ptr = + tvlv_put(buf_ptr, BSSGP_IE_SON_TRANSFER_APP_ID, cont->son_trans_app_id_len, cont->son_trans_app_id); + + return (int)(buf_ptr - buf); +} + +/*! Decode a RAN Information RIM Container (3GPP TS 48.018, table 11.3.62a.2.b). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_rim_cont(struct bssgp_ran_inf_rim_cont *cont, const uint8_t *buf, size_t len) +{ + int rc; + struct tlv_parsed tp; + + memset(cont, 0, sizeof(*cont)); + + rc = tlv_parse(&tp, &tvlv_att_def, buf, len, 0, 0); + if (rc < 0) + return -EINVAL; + + DEC_RIM_CONT_COMMON if (TLVP_PRESENT(&tp, BSSGP_IE_RAN_INFO_APP_CONTAINER)) { + cont->app_cont = TLVP_VAL(&tp, BSSGP_IE_RAN_INFO_APP_CONTAINER); + cont->app_cont_len = TLVP_LEN(&tp, BSSGP_IE_RAN_INFO_APP_CONTAINER); + } else { + cont->app_cont = NULL; + cont->app_cont_len = 0; + } + + if (TLVP_PRESENT(&tp, BSSGP_IE_APP_ERROR_CONTAINER)) { + cont->app_err_cont = TLVP_VAL(&tp, BSSGP_IE_APP_ERROR_CONTAINER); + cont->app_err_cont_len = TLVP_LEN(&tp, BSSGP_IE_APP_ERROR_CONTAINER); + cont->app_cont = NULL; + cont->app_cont_len = 0; + } else { + cont->app_err_cont = NULL; + cont->app_err_cont_len = 0; + } + + if (TLVP_PRESENT(&tp, BSSGP_IE_SON_TRANSFER_APP_ID)) { + cont->son_trans_app_id = TLVP_VAL(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + cont->son_trans_app_id_len = TLVP_LEN(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + } else { + cont->son_trans_app_id = NULL; + cont->son_trans_app_id_len = 0; + } + + return 0; +} + +/*! Encode a RAN Information RIM Container (3GPP TS 48.018, table 11.3.62a.2.b). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_rim_cont *cont) +{ + uint8_t *buf_ptr = buf; + + if (len < 15 + cont->app_err_cont_len + cont->app_cont_len + cont->son_trans_app_id_len) + return -EINVAL; + + ENC_RIM_CONT_COMMON; + + if (cont->app_err_cont && cont->app_err_cont_len > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_REQ_APP_CONTAINER, cont->app_err_cont_len, cont->app_err_cont); + else if (cont->app_cont && cont->app_cont_len > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_REQ_APP_CONTAINER, cont->app_cont_len, cont->app_cont); + + if (cont->son_trans_app_id && cont->son_trans_app_id_len > 0) + buf_ptr = + tvlv_put(buf_ptr, BSSGP_IE_SON_TRANSFER_APP_ID, cont->son_trans_app_id_len, cont->son_trans_app_id); + + return (int)(buf_ptr - buf); +} + +/*! Decode a RAN Information ACK RIM Container (3GPP TS 48.018, table 11.3.62a.3.b). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_ack_rim_cont(struct bssgp_ran_inf_ack_rim_cont *cont, const uint8_t *buf, size_t len) +{ + int rc; + struct tlv_parsed tp; + + memset(cont, 0, sizeof(*cont)); + + rc = tlv_parse(&tp, &tvlv_att_def, buf, len, 0, 0); + if (rc < 0) + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_APP_IDENTITY)) + cont->app_id = TLVP_VAL(&tp, BSSGP_IE_RIM_APP_IDENTITY)[0]; + else + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_SEQ_NR)) + cont->seq_num = tlvp_val32be(&tp, BSSGP_IE_RIM_SEQ_NR); + else + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_PROTOCOL_VERSION)) + cont->prot_ver = TLVP_VAL(&tp, BSSGP_IE_RIM_PROTOCOL_VERSION)[0]; + else + cont->prot_ver = 1; + + if (TLVP_PRESENT(&tp, BSSGP_IE_SON_TRANSFER_APP_ID)) { + cont->son_trans_app_id = TLVP_VAL(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + cont->son_trans_app_id_len = TLVP_LEN(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + } else { + cont->son_trans_app_id = NULL; + cont->son_trans_app_id_len = 0; + } + + return 0; +} + +/*! Encode a RAN Information ACK RIM Container (3GPP TS 48.018, table 11.3.62a.3.b). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_ack_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_ack_rim_cont *cont) +{ + uint8_t *buf_ptr = buf; + uint32_t seq_num = osmo_htonl(cont->seq_num); + + if (len < 13 + cont->son_trans_app_id_len) + return -EINVAL; + + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_APP_IDENTITY, 1, &cont->app_id); + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_SEQ_NR, 4, (uint8_t *) & seq_num); + + if (cont->prot_ver > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_PROTOCOL_VERSION, 1, &cont->prot_ver); + + if (cont->son_trans_app_id && cont->son_trans_app_id_len > 0) + buf_ptr = + tvlv_put(buf_ptr, BSSGP_IE_SON_TRANSFER_APP_ID, cont->son_trans_app_id_len, cont->son_trans_app_id); + + return (int)(buf_ptr - buf); +} + +/*! Decode a RAN Information Error RIM Container (3GPP TS 48.018, table 11.3.62a.4.b). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_err_rim_cont(struct bssgp_ran_inf_err_rim_cont *cont, const uint8_t *buf, size_t len) +{ + int rc; + struct tlv_parsed tp; + + memset(cont, 0, sizeof(*cont)); + + rc = tlv_parse(&tp, &tvlv_att_def, buf, len, 0, 0); + if (rc < 0) + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_APP_IDENTITY)) + cont->app_id = TLVP_VAL(&tp, BSSGP_IE_RIM_APP_IDENTITY)[0]; + else + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_CAUSE)) + cont->cause = TLVP_VAL(&tp, BSSGP_IE_CAUSE)[0]; + else + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_RIM_PROTOCOL_VERSION)) + cont->prot_ver = TLVP_VAL(&tp, BSSGP_IE_RIM_PROTOCOL_VERSION)[0]; + else + cont->prot_ver = 1; + + if (TLVP_PRESENT(&tp, BSSGP_IE_PDU_IN_ERROR)) { + cont->err_pdu = TLVP_VAL(&tp, BSSGP_IE_PDU_IN_ERROR); + cont->err_pdu_len = TLVP_LEN(&tp, BSSGP_IE_PDU_IN_ERROR); + } else + return -EINVAL; + + if (TLVP_PRESENT(&tp, BSSGP_IE_SON_TRANSFER_APP_ID)) { + cont->son_trans_app_id = TLVP_VAL(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + cont->son_trans_app_id_len = TLVP_LEN(&tp, BSSGP_IE_SON_TRANSFER_APP_ID); + } else { + cont->son_trans_app_id = NULL; + cont->son_trans_app_id_len = 0; + } + + return 0; +} + +/*! Encode a RAN Information Error RIM Container (3GPP TS 48.018, table 11.3.62a.4.b). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_err_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_err_rim_cont *cont) +{ + uint8_t *buf_ptr = buf; + + if (len < 9 + cont->err_pdu_len + cont->son_trans_app_id_len) + return -EINVAL; + + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_APP_IDENTITY, 1, &cont->app_id); + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_CAUSE, 1, &cont->cause); + + if (cont->prot_ver > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_RIM_PROTOCOL_VERSION, 1, &cont->prot_ver); + + if (cont->err_pdu && cont->err_pdu_len > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_PDU_IN_ERROR, cont->err_pdu_len, cont->err_pdu); + else + return -EINVAL; + + if (cont->son_trans_app_id && cont->son_trans_app_id_len > 0) + buf_ptr = + tvlv_put(buf_ptr, BSSGP_IE_SON_TRANSFER_APP_ID, cont->son_trans_app_id_len, cont->son_trans_app_id); + + return (int)(buf_ptr - buf); +} + +/*! Decode a RAN Information Application Error RIM Container (3GPP TS 48.018, table 11.3.62a.5.b). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_app_err_rim_cont(struct bssgp_ran_inf_app_err_rim_cont *cont, const uint8_t *buf, size_t len) +{ + int rc; + struct tlv_parsed tp; + + memset(cont, 0, sizeof(*cont)); + + rc = tlv_parse(&tp, &tvlv_att_def, buf, len, 0, 0); + if (rc < 0) + return -EINVAL; + + DEC_RIM_CONT_COMMON if (TLVP_PRESENT(&tp, BSSGP_IE_APP_ERROR_CONTAINER)) { + cont->app_err_cont = TLVP_VAL(&tp, BSSGP_IE_APP_ERROR_CONTAINER); + cont->app_err_cont_len = TLVP_LEN(&tp, BSSGP_IE_APP_ERROR_CONTAINER); + } else + return -EINVAL; + + return 0; +} + +/*! Encode a RAN Information Application Error RIM Container (3GPP TS 48.018, table 11.3.62a.5.b). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_app_err_rim_cont(uint8_t *buf, size_t len, const struct bssgp_ran_inf_app_err_rim_cont *cont) +{ + uint8_t *buf_ptr = buf; + + if (len < 15 + cont->app_err_cont_len) + return -EINVAL; + + ENC_RIM_CONT_COMMON; + + if (cont->app_err_cont && cont->app_err_cont_len > 0) + buf_ptr = tvlv_put(buf_ptr, BSSGP_IE_APP_ERROR_CONTAINER, cont->app_err_cont_len, cont->app_err_cont); + else + return -EINVAL; + + return (int)(buf_ptr - buf); + + return 0; +} + +/*! Decode a RAN Information Request Application Container for NACC (3GPP TS 48.018, section 11.3.63.1.1). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_req_app_cont_nacc(struct bssgp_ran_inf_req_app_cont_nacc *cont, const uint8_t *buf, size_t len) +{ + if (len < 8) + return -EINVAL; + cont->reprt_cell.cid = bssgp_parse_cell_id(&cont->reprt_cell.raid, buf); + return 0; +} + +/*! Encode a RAN Information Request Application Container for NACC (3GPP TS 48.018, section 11.3.63.1.1). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_req_app_cont_nacc(uint8_t *buf, size_t len, const struct bssgp_ran_inf_req_app_cont_nacc *cont) +{ + int rc; + + if (len < 10) + return -EINVAL; + + rc = bssgp_create_cell_id(buf, &cont->reprt_cell.raid, cont->reprt_cell.cid); + if (rc < 0) + return -EINVAL; + return rc; +} + +/*! Decode a RAN Information Application Container (3GPP TS 48.018, section 11.3.63.2.1). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_ran_inf_app_cont_nacc(struct bssgp_ran_inf_app_cont_nacc *cont, const uint8_t *buf, size_t len) +{ + unsigned int i; + + if (len < 9) + return -EINVAL; + + cont->reprt_cell.cid = bssgp_parse_cell_id(&cont->reprt_cell.raid, buf); + + buf += 8; + + cont->type_psi = buf[0] & 1; + cont->num_si = buf[0] >> 1; + + if (cont->type_psi && (len - 8) / 22 != cont->num_si) + return -EINVAL; + else if ((len - 8) / 21 != cont->num_si) + return -EINVAL; + + buf++; + + for (i = 0; i < cont->num_si; i++) { + cont->si[i] = buf; + if (cont->type_psi) + buf += 22; + else + buf += 21; + } + + return 0; +} + +/*! Encode a RAN Information Application Container (3GPP TS 48.018, section 11.3.63.2.1). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_ran_inf_app_cont_nacc(uint8_t *buf, size_t len, const struct bssgp_ran_inf_app_cont_nacc *cont) +{ + uint8_t *buf_ptr = buf; + int rc; + unsigned int silen; + unsigned int i; + + if (cont->type_psi) + silen = 22; + else + silen = 21; + + if (len < 11 + silen * cont->num_si) + return -EINVAL; + + rc = bssgp_create_cell_id(buf_ptr, &cont->reprt_cell.raid, cont->reprt_cell.cid); + if (rc < 0) + return -EINVAL; + buf_ptr += rc; + + buf_ptr[0] = 0x00; + if (cont->type_psi) + buf_ptr[0] |= 0x01; + buf_ptr[0] |= (cont->num_si << 1); + buf_ptr++; + + for (i = 0; i < cont->num_si; i++) { + memcpy(buf_ptr, cont->si[i], silen); + buf_ptr += silen; + } + + return (int)(buf_ptr - buf); +} + +/*! Decode a Application Error Container for NACC (3GPP TS 48.018, section 11.3.64.1). + * \param[out] user provided memory for decoded data struct. + * \param[in] buf user provided memory with the encoded value data of the IE. + * \returns 0 on success, -EINVAL on error. */ +int bssgp_dec_app_err_cont_nacc(struct bssgp_app_err_cont_nacc *cont, const uint8_t *buf, size_t len) +{ + if (len < 1) + return -EINVAL; + + cont->nacc_cause = buf[0]; + buf++; + cont->err_app_cont = buf; + cont->err_app_cont_len = len - 1; + + return 0; +} + +/*! Encode Application Error Container for NACC (3GPP TS 48.018, section 11.3.64.1). + * \param[out] buf user provided memory for the generated value part of the IE. + * \param[in] cont user provided input data struct. + * \returns length of encoded octets, -EINVAL on error. */ +int bssgp_enc_app_err_cont_nacc(uint8_t *buf, size_t len, const struct bssgp_app_err_cont_nacc *cont) +{ + uint8_t *buf_ptr = buf; + + buf_ptr[0] = cont->nacc_cause; + buf_ptr++; + + memcpy(buf_ptr, cont->err_app_cont, cont->err_app_cont_len); + buf_ptr += cont->err_app_cont_len; + + return (int)(buf_ptr - buf); +} diff --git a/src/gb/libosmogb.map b/src/gb/libosmogb.map index 5c029b0..b012184 100644 --- a/src/gb/libosmogb.map +++ b/src/gb/libosmogb.map @@ -3,7 +3,23 @@ bssgp_cause_str; bssgp_create_cell_id; bssgp_create_rim_ri; +bssgp_dec_app_err_cont_nacc; +bssgp_dec_ran_inf_ack_rim_cont; +bssgp_dec_ran_inf_err_rim_cont; +bssgp_dec_ran_inf_req_app_cont_nacc; +bssgp_dec_ran_inf_req_rim_cont; +bssgp_dec_ran_inf_app_cont_nacc; +bssgp_dec_ran_inf_app_err_rim_cont; +bssgp_dec_ran_inf_rim_cont; bssgp_pdu_str; +bssgp_enc_app_err_cont_nacc; +bssgp_enc_ran_inf_ack_rim_cont; +bssgp_enc_ran_inf_err_rim_cont; +bssgp_enc_ran_inf_req_app_cont_nacc; +bssgp_enc_ran_inf_req_rim_cont; +bssgp_enc_ran_inf_app_cont_nacc; +bssgp_enc_ran_inf_app_err_rim_cont; +bssgp_enc_ran_inf_rim_cont; bssgp_fc_in; bssgp_fc_init; bssgp_fc_ms_init; diff --git a/tests/Makefile.am b/tests/Makefile.am index cb683f7..8cd7695 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -74,7 +74,7 @@ endif if ENABLE_GB -check_PROGRAMS += gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_ns_test fr/fr_test +check_PROGRAMS += gb/bssgp_fc_test gb/gprs_bssgp_test gb/gprs_bssgp_rim_test gb/gprs_ns_test fr/fr_test endif utils_utils_test_SOURCES = utils/utils_test.c @@ -175,6 +175,10 @@ $(top_builddir)/src/gsm/libosmogsm.la \ $(top_builddir)/src/gb/libosmogb.la +gb_gprs_bssgp_rim_test_SOURCES = gb/gprs_bssgp_rim_test.c +gb_gprs_bssgp_rim_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \ + $(top_builddir)/src/gb/libosmogb.la + gb_gprs_ns_test_SOURCES = gb/gprs_ns_test.c gb_gprs_ns_test_LDADD = $(LDADD) $(top_builddir)/src/gb/libosmogb.la $(LIBRARY_DLSYM) \ $(top_builddir)/src/vty/libosmovty.la \ diff --git a/tests/gb/gprs_bssgp_rim_test.c b/tests/gb/gprs_bssgp_rim_test.c new file mode 100644 index 0000000..99073a2 --- /dev/null +++ b/tests/gb/gprs_bssgp_rim_test.c @@ -0,0 +1,538 @@ +/* Test routines for the BSSGP implementation in libosmogb + * + * (C) 2020 by sysmocom - s.f.m.c. GmbH + * Author: Philipp Maier <pmaier at sysmocom.de> + * + * Skeleton based on bssgp_fc_test.c + * (C) 2012 by Harald Welte <laforge at gnumonks.org> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include <osmocom/core/application.h> +#include <osmocom/core/utils.h> +#include <osmocom/gprs/gprs_bssgp.h> +#include <osmocom/gprs/gprs_ns.h> +#include <osmocom/gprs/gprs_bssgp_rim.h> + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> + +void dump_bssgp_ran_inf_req_rim_cont(struct bssgp_ran_inf_req_rim_cont *rim_cont) +{ + printf("bssgp_ran_inf_req_rim_cont:\n"); + printf(" app_id = %02x\n", rim_cont->app_id); + printf(" seq_num = %08x\n", rim_cont->seq_num); + printf(" pdu_ind.ack_requested = %u\n", rim_cont->pdu_ind.ack_requested); + printf(" pdu_ind.pdu_type_ext = %u\n", rim_cont->pdu_ind.pdu_type_ext); + printf(" prot_ver = %u\n", rim_cont->prot_ver); + if (rim_cont->app_cont) { + printf(" app_cont: %s\n", osmo_hexdump_nospc(rim_cont->app_cont, rim_cont->app_cont_len)); + printf(" app_cont_len: %lu\n", rim_cont->app_cont_len); + } + if (rim_cont->son_trans_app_id) { + printf(" son_trans_app_id: %s\n", + osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len)); + printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len); + } +} + +static void test_bssgp_dec_ran_inf_req_rim_cont() +{ + int rc; + struct bssgp_ran_inf_req_rim_cont rim_cont_dec; + uint8_t testvec[] = + { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x4d, 0x88, + 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_req_rim_cont(&rim_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_req_rim_cont(&rim_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_ran_inf_req_rim_cont() +{ + int rc; + struct bssgp_ran_inf_req_rim_cont rim_cont; + uint8_t app_cont[] = { 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 }; + uint8_t result[256]; + printf("----- %s START\n", __func__); + + rim_cont.app_id = 1; + rim_cont.seq_num = 1; + rim_cont.pdu_ind.ack_requested = 0; + rim_cont.pdu_ind.pdu_type_ext = 1; + rim_cont.prot_ver = 1; + rim_cont.app_cont = app_cont; + rim_cont.app_cont_len = 8; + rim_cont.son_trans_app_id = NULL; + rim_cont.son_trans_app_id_len = 0; + dump_bssgp_ran_inf_req_rim_cont(&rim_cont); + + rc = bssgp_enc_ran_inf_req_rim_cont(result, sizeof(result), &rim_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_ran_inf_rim_cont(struct bssgp_ran_inf_rim_cont *rim_cont) +{ + printf("bssgp_ran_inf_rim_cont:\n"); + printf(" app_id = %02x\n", rim_cont->app_id); + printf(" seq_num = %08x\n", rim_cont->seq_num); + printf(" pdu_ind.ack_requested = %u\n", rim_cont->pdu_ind.ack_requested); + printf(" pdu_ind.pdu_type_ext = %u\n", rim_cont->pdu_ind.pdu_type_ext); + printf(" prot_ver = %u\n", rim_cont->prot_ver); + if (rim_cont->app_cont) { + printf(" app_cont: %s\n", osmo_hexdump_nospc(rim_cont->app_cont, rim_cont->app_cont_len)); + printf(" app_cont_len: %lu\n", rim_cont->app_cont_len); + } + if (rim_cont->app_err_cont) { + printf(" app_err_cont: %s\n", osmo_hexdump_nospc(rim_cont->app_err_cont, rim_cont->app_err_cont_len)); + printf(" app_err_cont_len: %lu\n", rim_cont->app_err_cont_len); + } + if (rim_cont->son_trans_app_id) { + printf(" son_trans_app_id: %s\n", + osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len)); + printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len); + } +} + +static void test_bssgp_dec_ran_inf_rim_cont() +{ + int rc; + struct bssgp_ran_inf_rim_cont rim_cont_dec; + uint8_t testvec[] = + { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x02, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x4e, 0xc8, + 0x62, 0xf2, 0x24, 0x33, 0x4f, 0x00, 0x51, 0xe0, 0x06, 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x2b, 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10, 0x23, 0x6e, + 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00, 0x3c, 0x0b, 0x2b, 0x2b, 0x00, 0x90, 0x00, 0x18, 0x5a, 0x6f, + 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_rim_cont(&rim_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_rim_cont(&rim_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_ran_inf_req_rim_cont() +{ + int rc; + struct bssgp_ran_inf_rim_cont rim_cont; + uint8_t app_cont[] = + { 0x62, 0xf2, 0x24, 0x33, 0x4f, 0x00, 0x51, 0xe0, 0x06, 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x2b, 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10, + 0x23, 0x6e, 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00, 0x3c, 0x0b, 0x2b, 0x2b, 0x00, 0x90, 0x00, 0x18, + 0x5a, 0x6f, 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; + + uint8_t result[256]; + printf("----- %s START\n", __func__); + + rim_cont.app_id = 1; + rim_cont.seq_num = 1; + rim_cont.pdu_ind.ack_requested = 0; + rim_cont.pdu_ind.pdu_type_ext = 1; + rim_cont.prot_ver = 1; + rim_cont.app_cont = app_cont; + rim_cont.app_cont_len = sizeof(app_cont); + rim_cont.app_err_cont = NULL; + rim_cont.app_err_cont_len = 0; + rim_cont.son_trans_app_id = NULL; + rim_cont.son_trans_app_id_len = 0; + dump_bssgp_ran_inf_rim_cont(&rim_cont); + + rc = bssgp_enc_ran_inf_rim_cont(result, sizeof(result), &rim_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_ran_inf_ack_rim_cont(struct bssgp_ran_inf_ack_rim_cont *rim_cont) +{ + printf("bssgp_ran_inf_ack_rim_cont:\n"); + printf(" app_id = %02x\n", rim_cont->app_id); + printf(" seq_num = %08x\n", rim_cont->seq_num); + printf(" prot_ver = %u\n", rim_cont->prot_ver); + if (rim_cont->son_trans_app_id) { + printf(" son_trans_app_id: %s\n", + osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len)); + printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len); + } +} + +static void test_bssgp_dec_ran_inf_ack_rim_cont() +{ + int rc; + struct bssgp_ran_inf_ack_rim_cont rim_cont_dec; + uint8_t testvec[] = { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x55, 0x81, 0x01 }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_ack_rim_cont(&rim_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_ack_rim_cont(&rim_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_ran_inf_ack_rim_cont() +{ + int rc; + struct bssgp_ran_inf_ack_rim_cont rim_cont; + uint8_t result[256]; + printf("----- %s START\n", __func__); + + rim_cont.app_id = 1; + rim_cont.seq_num = 1; + rim_cont.prot_ver = 1; + rim_cont.son_trans_app_id = NULL; + rim_cont.son_trans_app_id_len = 0; + dump_bssgp_ran_inf_ack_rim_cont(&rim_cont); + + rc = bssgp_enc_ran_inf_ack_rim_cont(result, sizeof(result), &rim_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_ran_inf_err_rim_cont(struct bssgp_ran_inf_err_rim_cont *rim_cont) +{ + printf("bssgp_ran_inf_err_rim_cont:\n"); + printf(" app_id = %02x\n", rim_cont->app_id); + printf(" cause = %02x\n", rim_cont->cause); + printf(" prot_ver = %u\n", rim_cont->prot_ver); + if (rim_cont->err_pdu) { + printf(" err_pdu: %s\n", osmo_hexdump_nospc(rim_cont->err_pdu, rim_cont->err_pdu_len)); + printf(" err_pdu_len: %lu\n", rim_cont->err_pdu_len); + } + if (rim_cont->son_trans_app_id) { + printf(" son_trans_app_id: %s\n", + osmo_hexdump_nospc(rim_cont->son_trans_app_id, rim_cont->son_trans_app_id_len)); + printf(" son_trans_app_id_len: %lu\n", rim_cont->son_trans_app_id_len); + } +} + +static void test_bssgp_dec_ran_inf_err_rim_cont() +{ + int rc; + struct bssgp_ran_inf_err_rim_cont rim_cont_dec; + uint8_t testvec[] = + { 0x4b, 0x81, 0x17, 0x07, 0x81, 0x2b, 0x55, 0x81, 0x01, 0x15, 0x85, 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_err_rim_cont(&rim_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_err_rim_cont(&rim_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_ran_inf_err_rim_cont() +{ + int rc; + struct bssgp_ran_inf_err_rim_cont rim_cont; + uint8_t err_pdu[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + uint8_t result[256]; + printf("----- %s START\n", __func__); + + rim_cont.app_id = 23; + rim_cont.cause = 0x2b; + rim_cont.prot_ver = 1; + rim_cont.err_pdu = err_pdu; + rim_cont.err_pdu_len = sizeof(err_pdu); + rim_cont.son_trans_app_id = NULL; + rim_cont.son_trans_app_id_len = 0; + dump_bssgp_ran_inf_err_rim_cont(&rim_cont); + + rc = bssgp_enc_ran_inf_err_rim_cont(result, sizeof(result), &rim_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_ran_inf_app_err_rim_cont(struct bssgp_ran_inf_app_err_rim_cont *rim_cont) +{ + printf("bssgp_ran_inf_app_err_rim_cont:\n"); + printf(" app_id = %02x\n", rim_cont->app_id); + printf(" seq_num = %08x\n", rim_cont->seq_num); + printf(" pdu_ind.ack_requested = %u\n", rim_cont->pdu_ind.ack_requested); + printf(" pdu_ind.pdu_type_ext = %u\n", rim_cont->pdu_ind.pdu_type_ext); + printf(" prot_ver = %u\n", rim_cont->prot_ver); + if (rim_cont->app_err_cont) { + printf(" app_err_cont: %s\n", osmo_hexdump_nospc(rim_cont->app_err_cont, rim_cont->app_err_cont_len)); + printf(" app_err_cont_len: %lu\n", rim_cont->app_err_cont_len); + } +} + +static void test_bssgp_dec_ran_inf_app_err_rim_cont() +{ + int rc; + struct bssgp_ran_inf_app_err_rim_cont rim_cont_dec; + uint8_t testvec[] = + { 0x4b, 0x81, 0x01, 0x4c, 0x84, 0x00, 0x00, 0x00, 0x01, 0x4f, 0x81, 0x02, 0x55, 0x81, 0x01, 0x56, 0x85, + 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_app_err_rim_cont(&rim_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_app_err_rim_cont(&rim_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_ran_inf_app_err_rim_cont() +{ + int rc; + struct bssgp_ran_inf_app_err_rim_cont rim_cont; + uint8_t app_err_cont[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + uint8_t result[256]; + printf("----- %s START\n", __func__); + rim_cont.app_id = 1; + rim_cont.seq_num = 1; + rim_cont.pdu_ind.ack_requested = 0; + rim_cont.pdu_ind.pdu_type_ext = 1; + rim_cont.prot_ver = 1; + rim_cont.app_err_cont = app_err_cont; + rim_cont.app_err_cont_len = sizeof(app_err_cont); + dump_bssgp_ran_inf_app_err_rim_cont(&rim_cont); + + rc = bssgp_enc_ran_inf_app_err_rim_cont(result, sizeof(result), &rim_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_ran_inf_req_app_cont_nacc(struct bssgp_ran_inf_req_app_cont_nacc *app_cont) +{ + printf("bssgp_ran_inf_req_app_cont_nacc:\n"); + printf(" reprt_cell.raid.mcc = %u\n", app_cont->reprt_cell.raid.mcc); + printf(" reprt_cell.raid.mnc = %u\n", app_cont->reprt_cell.raid.mnc); + printf(" reprt_cell.raid.mnc_3_digits = %u\n", app_cont->reprt_cell.raid.mnc_3_digits); + printf(" reprt_cell.raid.lac = %u\n", app_cont->reprt_cell.raid.lac); + printf(" reprt_cell.raid.rac = %u\n", app_cont->reprt_cell.raid.rac); + printf(" reprt_cell.cid = %04x\n", app_cont->reprt_cell.cid); +} + +static void test_bssgp_dec_ran_inf_req_app_cont_nacc() +{ + int rc; + struct bssgp_ran_inf_req_app_cont_nacc app_cont_dec; + uint8_t testvec[] = { 0x62, 0xf2, 0x24, 0x33, 0x90, 0x00, 0x51, 0xe1 }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_req_app_cont_nacc(&app_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_req_app_cont_nacc(&app_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_ran_inf_req_app_cont_nacc() +{ + int rc; + struct bssgp_ran_inf_req_app_cont_nacc app_cont; + uint8_t result[256]; + printf("----- %s START\n", __func__); + + app_cont.reprt_cell.raid.mcc = 262; + app_cont.reprt_cell.raid.mnc = 42; + app_cont.reprt_cell.raid.mnc_3_digits = 0; + app_cont.reprt_cell.raid.lac = 13200; + app_cont.reprt_cell.raid.rac = 0; + app_cont.reprt_cell.cid = 0x51e1; + dump_bssgp_ran_inf_req_app_cont_nacc(&app_cont); + + rc = bssgp_enc_ran_inf_req_app_cont_nacc(result, sizeof(result), &app_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_ran_inf_app_cont_nacc(struct bssgp_ran_inf_app_cont_nacc *app_cont) +{ + unsigned int i; + unsigned int silen; + printf("bssgp_ran_inf_app_cont_nacc:\n"); + printf(" reprt_cell.raid.mcc = %u\n", app_cont->reprt_cell.raid.mcc); + printf(" reprt_cell.raid.mnc = %u\n", app_cont->reprt_cell.raid.mnc); + printf(" reprt_cell.raid.mnc_3_digits = %u\n", app_cont->reprt_cell.raid.mnc_3_digits); + printf(" reprt_cell.raid.lac = %u\n", app_cont->reprt_cell.raid.lac); + printf(" reprt_cell.raid.rac = %u\n", app_cont->reprt_cell.raid.rac); + printf(" reprt_cell.cid = %04x\n", app_cont->reprt_cell.cid); + printf(" type_psi = %u\n", app_cont->type_psi); + printf(" num_si = %u\n", app_cont->num_si); + + if (app_cont->type_psi) + silen = 22; + else + silen = 21; + + for (i = 0; i < app_cont->num_si; i++) + printf(" si[%u] = %s\n", i, osmo_hexdump_nospc(app_cont->si[i], silen)); +} + +static void test_bssgp_dec_ran_inf_app_cont_nacc() +{ + int rc; + struct bssgp_ran_inf_app_cont_nacc app_cont_dec; + uint8_t testvec[] = + { 0x62, 0xf2, 0x24, 0x33, 0x4f, 0x00, 0x51, 0xe0, 0x06, 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x00, 0x00, 0x2b, 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10, + 0x23, 0x6e, 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00, 0x3c, 0x0b, 0x2b, 0x2b, 0x00, 0x90, 0x00, 0x18, + 0x5a, 0x6f, 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_ran_inf_app_cont_nacc(&app_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_ran_inf_app_cont_nacc(&app_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_ran_inf_app_cont_nacc() +{ + int rc; + struct bssgp_ran_inf_app_cont_nacc app_cont; + + uint8_t si1[] = + { 0x19, 0x8f, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x79, 0x00, 0x00, 0x2b }; + uint8_t si3[] = + { 0x1b, 0x75, 0x30, 0x00, 0xf1, 0x10, 0x23, 0x6e, 0xc9, 0x03, 0x3c, 0x27, 0x47, 0x40, 0x79, 0x00, 0x00, + 0x3c, 0x0b, 0x2b, 0x2b }; + uint8_t si13[] = + { 0x00, 0x90, 0x00, 0x18, 0x5a, 0x6f, 0xc9, 0xe0, 0x84, 0x10, 0xab, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, + 0x2b, 0x2b, 0x2b, 0x2b }; + + uint8_t result[256]; + printf("----- %s START\n", __func__); + + app_cont.reprt_cell.raid.mcc = 262; + app_cont.reprt_cell.raid.mnc = 42; + app_cont.reprt_cell.raid.mnc_3_digits = 0; + app_cont.reprt_cell.raid.lac = 13135; + app_cont.reprt_cell.raid.rac = 0; + app_cont.reprt_cell.cid = 0x51e1; + app_cont.type_psi = false; + app_cont.num_si = 3; + app_cont.si[0] = si1; + app_cont.si[1] = si3; + app_cont.si[2] = si13; + dump_bssgp_ran_inf_app_cont_nacc(&app_cont); + + rc = bssgp_enc_ran_inf_app_cont_nacc(result, sizeof(result), &app_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +void dump_bssgp_app_err_cont_nacc(struct bssgp_app_err_cont_nacc *app_cont) +{ + printf("bssgp_app_err_cont_nacc:\n"); + printf(" macc_cause = %02x\n", app_cont->nacc_cause); + if (app_cont->err_app_cont) { + printf(" err_app_cont: %s\n", osmo_hexdump_nospc(app_cont->err_app_cont, app_cont->err_app_cont_len)); + printf(" err_app_cont_len: %lu\n", app_cont->err_app_cont_len); + } +} + +static void test_bssgp_dec_app_err_cont_nacc() +{ + int rc; + struct bssgp_app_err_cont_nacc app_cont_dec; + uint8_t testvec[] = { 0x01, 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + + printf("----- %s START\n", __func__); + + rc = bssgp_dec_app_err_cont_nacc(&app_cont_dec, testvec, sizeof(testvec)); + printf("rc=%d, ", rc); + if (rc == 0) + dump_bssgp_app_err_cont_nacc(&app_cont_dec); + + printf("----- %s END\n", __func__); +} + +static void test_bssgp_enc_app_err_cont_nacc() +{ + int rc; + struct bssgp_app_err_cont_nacc app_cont; + uint8_t err_app_cont[] = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee }; + uint8_t result[256]; + printf("----- %s START\n", __func__); + + app_cont.nacc_cause = BSSGP_NACC_CAUSE_SYNTAX_ERR; + app_cont.err_app_cont = err_app_cont; + app_cont.err_app_cont_len = sizeof(err_app_cont); + dump_bssgp_app_err_cont_nacc(&app_cont); + + rc = bssgp_enc_app_err_cont_nacc(result, sizeof(result), &app_cont); + printf("rc=%d, ", rc); + if (rc > 0) + printf("result=%s", osmo_hexdump_nospc(result, rc)); + printf("\n"); + printf("----- %s END\n", __func__); +} + +int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx) { return 0; } + +int main(int argc, char **argv) +{ + printf("===== BSSGP RIM test START\n"); + test_bssgp_dec_ran_inf_req_rim_cont(); + test_bssgp_enc_ran_inf_req_rim_cont(); + test_bssgp_dec_ran_inf_rim_cont(); + test_bssgp_ran_inf_req_rim_cont(); + test_bssgp_dec_ran_inf_ack_rim_cont(); + test_bssgp_enc_ran_inf_ack_rim_cont(); + test_bssgp_dec_ran_inf_err_rim_cont(); + test_bssgp_enc_ran_inf_err_rim_cont(); + test_bssgp_dec_ran_inf_app_err_rim_cont(); + test_bssgp_enc_ran_inf_app_err_rim_cont(); + test_bssgp_dec_ran_inf_req_app_cont_nacc(); + test_bssgp_enc_ran_inf_req_app_cont_nacc(); + test_bssgp_dec_ran_inf_app_cont_nacc(); + test_bssgp_enc_ran_inf_app_cont_nacc(); + test_bssgp_dec_app_err_cont_nacc(); + test_bssgp_enc_app_err_cont_nacc(); + printf("===== BSSGP RIM test END\n\n"); + + exit(EXIT_SUCCESS); +} diff --git a/tests/gb/gprs_bssgp_rim_test.ok b/tests/gb/gprs_bssgp_rim_test.ok new file mode 100644 index 0000000..92d3282 --- /dev/null +++ b/tests/gb/gprs_bssgp_rim_test.ok @@ -0,0 +1,157 @@ +===== BSSGP RIM test START +----- test_bssgp_dec_ran_inf_req_rim_cont START +rc=0, bssgp_ran_inf_req_rim_cont: + app_id = 01 + seq_num = 00000001 + pdu_ind.ack_requested = 0 + pdu_ind.pdu_type_ext = 1 + prot_ver = 1 + app_cont: 62f22433900051e1 + app_cont_len: 8 +----- test_bssgp_dec_ran_inf_req_rim_cont END +----- test_bssgp_enc_ran_inf_req_rim_cont START +bssgp_ran_inf_req_rim_cont: + app_id = 01 + seq_num = 00000001 + pdu_ind.ack_requested = 0 + pdu_ind.pdu_type_ext = 1 + prot_ver = 1 + app_cont: 62f22433900051e1 + app_cont_len: 8 +rc=25, result=4b81014c84000000014f81f25581014d8862f22433900051e1 +----- test_bssgp_enc_ran_inf_req_rim_cont END +----- test_bssgp_dec_ran_inf_rim_cont START +rc=0, bssgp_ran_inf_rim_cont: + app_id = 01 + seq_num = 00000002 + pdu_ind.ack_requested = 0 + pdu_ind.pdu_type_ext = 1 + prot_ver = 1 + app_cont: 62f224334f0051e006198fb100000000000000000000000000007900002b1b753000f110236ec9033c2747407900003c0b2b2b009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b + app_cont_len: 72 +----- test_bssgp_dec_ran_inf_rim_cont END +----- test_bssgp_ran_inf_req_rim_cont START +bssgp_ran_inf_rim_cont: + app_id = 01 + seq_num = 00000001 + pdu_ind.ack_requested = 0 + pdu_ind.pdu_type_ext = 1 + prot_ver = 1 + app_cont: 62f224334f0051e006198fb100000000000000000000000000007900002b1b753000f110236ec9033c2747407900003c0b2b2b009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b + app_cont_len: 72 +rc=89, result=4b81014c84000000014f81025581014dc862f224334f0051e006198fb100000000000000000000000000007900002b1b753000f110236ec9033c2747407900003c0b2b2b009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b +----- test_bssgp_ran_inf_req_rim_cont END +----- test_bssgp_dec_ran_inf_ack_rim_cont START +rc=0, bssgp_ran_inf_ack_rim_cont: + app_id = 01 + seq_num = 00000001 + prot_ver = 1 +----- test_bssgp_dec_ran_inf_ack_rim_cont END +----- test_bssgp_enc_ran_inf_ack_rim_cont START +bssgp_ran_inf_ack_rim_cont: + app_id = 01 + seq_num = 00000001 + prot_ver = 1 +rc=12, result=4b81014c8400000001558101 +----- test_bssgp_enc_ran_inf_ack_rim_cont END +----- test_bssgp_dec_ran_inf_err_rim_cont START +rc=0, bssgp_ran_inf_err_rim_cont: + app_id = 17 + cause = 2b + prot_ver = 1 + err_pdu: aabbccddee + err_pdu_len: 5 +----- test_bssgp_dec_ran_inf_err_rim_cont END +----- test_bssgp_enc_ran_inf_err_rim_cont START +bssgp_ran_inf_err_rim_cont: + app_id = 17 + cause = 2b + prot_ver = 1 + err_pdu: aabbccddee + err_pdu_len: 5 +rc=16, result=4b811707812b5581011585aabbccddee +----- test_bssgp_enc_ran_inf_err_rim_cont END +----- test_bssgp_dec_ran_inf_app_err_rim_cont START +rc=0, bssgp_ran_inf_app_err_rim_cont: + app_id = 01 + seq_num = 00000001 + pdu_ind.ack_requested = 0 + pdu_ind.pdu_type_ext = 1 + prot_ver = 1 + app_err_cont: aabbccddee + app_err_cont_len: 5 +----- test_bssgp_dec_ran_inf_app_err_rim_cont END +----- test_bssgp_enc_ran_inf_app_err_rim_cont START +bssgp_ran_inf_app_err_rim_cont: + app_id = 01 + seq_num = 00000001 + pdu_ind.ack_requested = 0 + pdu_ind.pdu_type_ext = 1 + prot_ver = 1 + app_err_cont: aabbccddee + app_err_cont_len: 5 +rc=22, result=4b81014c84000000014f81025581015685aabbccddee +----- test_bssgp_enc_ran_inf_app_err_rim_cont END +----- test_bssgp_dec_ran_inf_req_app_cont_nacc START +rc=0, bssgp_ran_inf_req_app_cont_nacc: + reprt_cell.raid.mcc = 262 + reprt_cell.raid.mnc = 42 + reprt_cell.raid.mnc_3_digits = 0 + reprt_cell.raid.lac = 13200 + reprt_cell.raid.rac = 0 + reprt_cell.cid = 51e1 +----- test_bssgp_dec_ran_inf_req_app_cont_nacc END +----- test_bssgp_enc_ran_inf_req_app_cont_nacc START +bssgp_ran_inf_req_app_cont_nacc: + reprt_cell.raid.mcc = 262 + reprt_cell.raid.mnc = 42 + reprt_cell.raid.mnc_3_digits = 0 + reprt_cell.raid.lac = 13200 + reprt_cell.raid.rac = 0 + reprt_cell.cid = 51e1 +rc=8, result=62f22433900051e1 +----- test_bssgp_enc_ran_inf_req_app_cont_nacc END +----- test_bssgp_dec_ran_inf_app_cont_nacc START +rc=0, bssgp_ran_inf_app_cont_nacc: + reprt_cell.raid.mcc = 262 + reprt_cell.raid.mnc = 42 + reprt_cell.raid.mnc_3_digits = 0 + reprt_cell.raid.lac = 13135 + reprt_cell.raid.rac = 0 + reprt_cell.cid = 51e0 + type_psi = 0 + num_si = 3 + si[0] = 198fb100000000000000000000000000007900002b + si[1] = 1b753000f110236ec9033c2747407900003c0b2b2b + si[2] = 009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b +----- test_bssgp_dec_ran_inf_app_cont_nacc END +----- test_bssgp_enc_ran_inf_app_cont_nacc START +bssgp_ran_inf_app_cont_nacc: + reprt_cell.raid.mcc = 262 + reprt_cell.raid.mnc = 42 + reprt_cell.raid.mnc_3_digits = 0 + reprt_cell.raid.lac = 13135 + reprt_cell.raid.rac = 0 + reprt_cell.cid = 51e1 + type_psi = 0 + num_si = 3 + si[0] = 198fb100000000000000000000000000007900002b + si[1] = 1b753000f110236ec9033c2747407900003c0b2b2b + si[2] = 009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b +rc=72, result=62f224334f0051e106198fb100000000000000000000000000007900002b1b753000f110236ec9033c2747407900003c0b2b2b009000185a6fc9e08410ab2b2b2b2b2b2b2b2b2b2b +----- test_bssgp_enc_ran_inf_app_cont_nacc END +----- test_bssgp_dec_app_err_cont_nacc START +rc=0, bssgp_app_err_cont_nacc: + macc_cause = 01 + err_app_cont: aabbccddee + err_app_cont_len: 5 +----- test_bssgp_dec_app_err_cont_nacc END +----- test_bssgp_enc_app_err_cont_nacc START +bssgp_app_err_cont_nacc: + macc_cause = 01 + err_app_cont: aabbccddee + err_app_cont_len: 5 +rc=6, result=01aabbccddee +----- test_bssgp_enc_app_err_cont_nacc END +===== BSSGP RIM test END + diff --git a/tests/testsuite.at b/tests/testsuite.at index 43f515a..9a5e866 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -215,6 +215,12 @@ AT_CHECK([$abs_top_builddir/tests/gb/gprs_bssgp_test], [0], [expout], [ignore]) AT_CLEANUP +AT_SETUP([gprs-bssgp-rim]) +AT_KEYWORDS([gprs-bssgp-rim]) +cat $abs_srcdir/gb/gprs_bssgp_rim_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/gb/gprs_bssgp_rim_test], [0], [expout], [ignore]) +AT_CLEANUP + AT_SETUP([gprs-ns]) AT_KEYWORDS([gprs-ns]) cat $abs_srcdir/gb/gprs_ns_test.ok > expout -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/21862 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: Ibbc7fd67658e3040c12abb5706fe9d1f31894352 Gerrit-Change-Number: 21862 Gerrit-PatchSet: 1 Gerrit-Owner: dexter <pmaier at sysmocom.de> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201223/145e34e8/attachment.htm>