aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2021-06-23 19:46:07 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2021-06-25 17:20:50 +0200
commit1989a190664ca1d4169c80336b2ecc00426c84f1 (patch)
tree14fdad45c6362dc36f741579e8deba9d36c2578b
parent8c29236d353f75e97661b68003c6e70b67f5b7e3 (diff)
Support proto IPAC_PROTO_EXT_PCU BSC<->PCU
-rw-r--r--src/osmobts_sock.c14
-rw-r--r--src/pcu_l1_if.cpp48
-rw-r--r--src/pcu_l1_if.h5
-rw-r--r--tests/app_info/AppInfoTest.cpp10
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");
}