From 1989a190664ca1d4169c80336b2ecc00426c84f1 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 23 Jun 2021 19:46:07 +0200 Subject: [PATCH] Support proto IPAC_PROTO_EXT_PCU BSC<->PCU Related: SYS#5303 Change-Id: I633db291107883c2e370a9b56606d562a990b714 --- src/osmobts_sock.c | 14 +++++++--- src/pcu_l1_if.cpp | 48 +++++++++++++++++++++++++++++++--- src/pcu_l1_if.h | 5 +++- tests/app_info/AppInfoTest.cpp | 10 +++---- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/osmobts_sock.c b/src/osmobts_sock.c index 4e1171fc..5c6415fb 100644 --- a/src/osmobts_sock.c +++ b/src/osmobts_sock.c @@ -133,10 +133,12 @@ static void pcu_sock_close(int lost) static int pcu_sock_read(struct osmo_fd *bfd) { - struct gsm_pcu_if pcu_prim; + const size_t max_len = sizeof(struct gsm_pcu_if) + 1000; + uint8_t *buf = alloca(max_len); + struct gsm_pcu_if *pcu_prim = (struct gsm_pcu_if *)buf; int rc; - rc = recv(bfd->fd, &pcu_prim, sizeof(pcu_prim), 0); + rc = recv(bfd->fd, buf, max_len, 0); if (rc < 0 && errno == EAGAIN) return 0; /* Try again later */ if (rc <= 0) { @@ -144,7 +146,13 @@ static int pcu_sock_read(struct osmo_fd *bfd) return -EIO; } - return pcu_rx(pcu_prim.msg_type, &pcu_prim); + if (rc < PCUIF_HDR_SIZE) { + LOGP(DL1IF, LOGL_ERROR, "Received %d bytes on PCU Socket, but primitive " + "hdr size is %zu, discarding\n", rc, PCUIF_HDR_SIZE); + return -EINVAL; + } + + return pcu_rx(pcu_prim, rc); } static int pcu_sock_write(struct osmo_fd *bfd) diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index b35c9906..2373f60c 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -951,9 +951,32 @@ static int pcu_rx_app_info_req(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_ap return 0; } -int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim) +static int pcu_rx_container(struct gprs_rlcmac_bts *bts, struct gsm_pcu_if_container *container) +{ + int rc; + + switch (container->msg_type) { + default: + LOGP(DL1IF, LOGL_NOTICE, "(bts=%d) Rx unexpected msg type (%u) inside container!\n", + bts->nr, container->msg_type); + rc = -1; + } + return rc; +} + +#define CHECK_IF_MSG_SIZE(prim_len, prim_msg) \ + do { \ + size_t _len = PCUIF_HDR_SIZE + sizeof(prim_msg); \ + if (prim_len < _len) { \ + LOGP(DL1IF, LOGL_ERROR, "Received %zu bytes on PCU Socket, but primitive %s " \ + "size is %zu, discarding\n", prim_len, #prim_msg, _len); \ + return -EINVAL; \ + } \ + } while(0); +int pcu_rx(struct gsm_pcu_if *pcu_prim, size_t pcu_prim_length) { int rc = 0; + size_t exp_len; struct gprs_rlcmac_bts *bts = gprs_pcu_get_bts_by_nr(the_pcu, pcu_prim->bts_nr); if (!bts) { LOGP(DL1IF, LOGL_NOTICE, "Received message for new BTS%d\n", pcu_prim->bts_nr); @@ -964,40 +987,59 @@ int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim) } } - switch (msg_type) { + switch (pcu_prim->msg_type) { case PCU_IF_MSG_DATA_IND: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.data_ind); rc = pcu_rx_data_ind(bts, &pcu_prim->u.data_ind); break; case PCU_IF_MSG_DATA_CNF: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.data_cnf); rc = pcu_rx_data_cnf(bts, &pcu_prim->u.data_cnf); break; case PCU_IF_MSG_RTS_REQ: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.rts_req); rc = pcu_rx_rts_req(bts, &pcu_prim->u.rts_req); break; case PCU_IF_MSG_RACH_IND: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.rach_ind); rc = pcu_rx_rach_ind(bts, &pcu_prim->u.rach_ind); break; case PCU_IF_MSG_INFO_IND: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.info_ind); rc = pcu_rx_info_ind(bts, &pcu_prim->u.info_ind); break; case PCU_IF_MSG_TIME_IND: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.time_ind); rc = pcu_rx_time_ind(bts, &pcu_prim->u.time_ind); break; case PCU_IF_MSG_PAG_REQ: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.pag_req); rc = pcu_rx_pag_req(bts, &pcu_prim->u.pag_req); break; case PCU_IF_MSG_SUSP_REQ: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.susp_req); rc = pcu_rx_susp_req(bts, &pcu_prim->u.susp_req); break; case PCU_IF_MSG_APP_INFO_REQ: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.app_info_req); rc = pcu_rx_app_info_req(bts, &pcu_prim->u.app_info_req); break; case PCU_IF_MSG_INTERF_IND: /* TODO: handle interference reports */ break; + case PCU_IF_MSG_CONTAINER: + CHECK_IF_MSG_SIZE(pcu_prim_length, pcu_prim->u.container); + /* ^ check if we can access container fields, v check with container data length */ + exp_len = PCUIF_HDR_SIZE + sizeof(pcu_prim->u.container) + osmo_load16be(&pcu_prim->u.container.length); + if (pcu_prim_length < exp_len) { + LOGP(DL1IF, LOGL_ERROR, "Received %zu bytes on PCU Socket, but primitive container size" \ + "is %zu, discarding\n", pcu_prim_length, exp_len); + } + rc = pcu_rx_container(bts, &pcu_prim->u.container); + break; default: LOGP(DL1IF, LOGL_ERROR, "Received unknown PCU msg type %d\n", - msg_type); + pcu_prim->msg_type); rc = -EINVAL; } diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h index 246444ca..2a4f0ead 100644 --- a/src/pcu_l1_if.h +++ b/src/pcu_l1_if.h @@ -160,7 +160,7 @@ extern "C" { #endif struct gprs_rlcmac_bts; -int pcu_rx(uint8_t msg_type, struct gsm_pcu_if *pcu_prim); +int pcu_rx(struct gsm_pcu_if *pcu_prim, size_t pcu_prim_length); int pcu_l1if_open(void); void pcu_l1if_close(void); int pcu_sock_send(struct msgb *msg); @@ -178,6 +178,9 @@ int pcu_rx_data_ind_pdtch(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_pdch * void pcu_rx_block_time(struct gprs_rlcmac_bts *bts, uint16_t arfcn, uint32_t fn, uint8_t ts_no); uint16_t imsi2paging_group(const char* imsi); + +#define PCUIF_HDR_SIZE ( sizeof(struct gsm_pcu_if) - sizeof(((struct gsm_pcu_if *)0)->u) ) + #ifdef __cplusplus } #endif diff --git a/tests/app_info/AppInfoTest.cpp b/tests/app_info/AppInfoTest.cpp index e89680b6..d3a047e2 100644 --- a/tests/app_info/AppInfoTest.cpp +++ b/tests/app_info/AppInfoTest.cpp @@ -72,7 +72,7 @@ void test_pcu_rx_no_subscr_with_active_tbf() struct gsm_pcu_if pcu_prim = {PCU_IF_MSG_APP_INFO_REQ, }; fprintf(stderr, "--- %s ---\n", __func__); - pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim); + pcu_rx(&pcu_prim, sizeof(struct gsm_pcu_if)); fprintf(stderr, "\n"); } @@ -106,7 +106,7 @@ void test_sched_app_info_ok(const struct gsm_pcu_if_app_info_req *req) fprintf(stderr, "--- %s ---\n", __func__); pcu_prim.u.app_info_req = *req; - pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim); + pcu_rx(&pcu_prim, sizeof(struct gsm_pcu_if)); msg = sched_app_info(tbf1); assert(msg); @@ -126,7 +126,7 @@ void test_sched_app_info_missing_app_info_in_bts(const struct gsm_pcu_if_app_inf fprintf(stderr, "--- %s ---\n", __func__); pcu_prim.u.app_info_req = *req; - pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim); + pcu_rx(&pcu_prim, sizeof(struct gsm_pcu_if)); msgb_free(bts->app_info); bts->app_info = NULL; @@ -142,8 +142,8 @@ void test_pcu_rx_overwrite_app_info(const struct gsm_pcu_if_app_info_req *req) fprintf(stderr, "--- %s ---\n", __func__); pcu_prim.u.app_info_req = *req; - pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim); - pcu_rx(PCU_IF_MSG_APP_INFO_REQ, &pcu_prim); + pcu_rx(&pcu_prim, sizeof(struct gsm_pcu_if)); + pcu_rx(&pcu_prim, sizeof(struct gsm_pcu_if)); fprintf(stderr, "\n"); }