pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32315 )
Change subject: sm: Parse PDP address in rx PDP Ctx Accept ......................................................................
sm: Parse PDP address in rx PDP Ctx Accept
Related: OS#5501 Change-Id: Ic41edc14445f0f5d4ef20bb30b53d66fb56435de --- M include/osmocom/gprs/sm/sm_pdu.h M include/osmocom/gprs/sm/sm_prim.h M src/sm/sm.c M src/sm/sm_pdu.c 4 files changed, 118 insertions(+), 8 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/sm/sm_pdu.h b/include/osmocom/gprs/sm/sm_pdu.h index 50e3ae9..d144f6e 100644 --- a/include/osmocom/gprs/sm/sm_pdu.h +++ b/include/osmocom/gprs/sm/sm_pdu.h @@ -2,8 +2,11 @@ #pragma once
#include <osmocom/core/msgb.h> +#include <osmocom/core/socket.h> #include <osmocom/gsm/tlv.h>
+#include <osmocom/gprs/sm/sm.h> + struct gprs_gmm_entity;
#define GPRS_SM_ALLOC_SIZE 2048 @@ -15,3 +18,8 @@
int gprs_sm_build_act_pdp_ctx_req(struct gprs_sm_entity *sme, struct msgb *msg); +int gprs_sm_pdp_addr_dec(const struct gprs_sm_pdp_addr *pdp_addr, + uint16_t pdp_addr_len, + enum osmo_gprs_sm_pdp_addr_ietf_type *pdp_addr_ietf_type, + struct osmo_sockaddr *osa4, + struct osmo_sockaddr *osa6); diff --git a/include/osmocom/gprs/sm/sm_prim.h b/include/osmocom/gprs/sm/sm_prim.h index 575ea80..4f16ae4 100644 --- a/include/osmocom/gprs/sm/sm_prim.h +++ b/include/osmocom/gprs/sm/sm_prim.h @@ -79,7 +79,9 @@ uint8_t pco_len; union { struct { - struct osmo_sockaddr pdp_addr; + enum osmo_gprs_sm_pdp_addr_ietf_type pdp_addr_ietf_type; + struct osmo_sockaddr pdp_addr_v4; + struct osmo_sockaddr pdp_addr_v6; uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN]; uint8_t qos_len; } acc; diff --git a/src/sm/sm.c b/src/sm/sm.c index b3d65da..d760ae6 100644 --- a/src/sm/sm.c +++ b/src/sm/sm.c @@ -208,8 +208,13 @@ sm_prim_tx->smreg.ms_id = sme->ms->ms_id; sm_prim_tx->smreg.pdp_act_cnf.accepted = (cause != 0); sm_prim_tx->smreg.pdp_act_cnf.nsapi = sme->nsapi; - if (!sm_prim_tx->smreg.pdp_act_cnf.accepted) + if (sm_prim_tx->smreg.pdp_act_cnf.accepted) { + sm_prim_tx->smreg.pdp_act_cnf.acc.pdp_addr_ietf_type = sme->pdp_addr_ietf_type; + memcpy(&sm_prim_tx->smreg.pdp_act_cnf.acc.pdp_addr_v4, &sme->pdp_addr_v4, sizeof(sme->pdp_addr_v4)); + memcpy(&sm_prim_tx->smreg.pdp_act_cnf.acc.pdp_addr_v6, &sme->pdp_addr_v6, sizeof(sme->pdp_addr_v6)); + } else { sm_prim_tx->smreg.pdp_act_cnf.rej.cause = cause; + }
rc = gprs_sm_prim_call_up_cb(sm_prim_tx); return rc; @@ -289,16 +294,28 @@
radio_prio = *ofs++;
- rc = gprs_sm_tlv_parse(&tp, ofs, len - (ofs - (uint8_t *)gh)); - if (rc < 0) { - LOGSME(sme, LOGL_ERROR, "Rx SM Activate PDP Context Accept: failed to parse TLVs %d\n", rc); - goto rejected; - } - (void)llc_sapi; (void)qos; (void)radio_prio;
+ if (len > ofs - (uint8_t *)gh) { + rc = gprs_sm_tlv_parse(&tp, ofs, len - (ofs - (uint8_t *)gh)); + if (rc < 0) { + LOGSME(sme, LOGL_ERROR, "Rx SM Activate PDP Context Accept: failed to parse TLVs %d\n", rc); + goto rejected; + } + + if (TLVP_PRESENT(&tp, GSM48_IE_GSM_PDP_ADDR)) { + rc = gprs_sm_pdp_addr_dec( + (const struct gprs_sm_pdp_addr *)TLVP_VAL(&tp, GSM48_IE_GSM_PDP_ADDR), + TLVP_LEN(&tp, GSM48_IE_GSM_PDP_ADDR), + &sme->pdp_addr_ietf_type, + &sme->pdp_addr_v4, &sme->pdp_addr_v6); + if (rc < 0) + goto rejected; + } + } + rc = osmo_fsm_inst_dispatch(sme->ms_fsm.fi, GPRS_SM_MS_EV_RX_ACT_PDP_CTX_ACC, NULL); if (rc < 0) goto rejected; diff --git a/src/sm/sm_pdu.c b/src/sm/sm_pdu.c index 3498a9c..e866a33 100644 --- a/src/sm/sm_pdu.c +++ b/src/sm/sm_pdu.c @@ -24,6 +24,7 @@ #include <osmocom/core/msgb.h> #include <osmocom/core/bitvec.h> #include <osmocom/core/endian.h> +#include <osmocom/core/socket.h> #include <osmocom/gsm/tlv.h> #include <osmocom/gsm/protocol/gsm_04_08.h> #include <osmocom/gsm/protocol/gsm_04_08_gprs.h> @@ -80,6 +81,78 @@ } }
+int gprs_sm_pdp_addr_dec(const struct gprs_sm_pdp_addr *pdp_addr, + uint16_t pdp_addr_len, + enum osmo_gprs_sm_pdp_addr_ietf_type *pdp_addr_ietf_type, + struct osmo_sockaddr *osa4, + struct osmo_sockaddr *osa6) +{ + + OSMO_ASSERT(pdp_addr); + OSMO_ASSERT(pdp_addr_ietf_type); + OSMO_ASSERT(osa4); + OSMO_ASSERT(osa6); + + memset(osa4, 0, sizeof(*osa4)); + memset(osa6, 0, sizeof(*osa6)); + osa4->u.sa.sa_family = AF_UNSPEC; + osa6->u.sa.sa_family = AF_UNSPEC; + + switch (pdp_addr->organization) { + case GPRS_SM_PDP_ADDR_ORG_IETF: + break; + case GPRS_SM_PDP_ADDR_ORG_ETSI: + default: + LOGSM(LOGL_INFO, "Unsupported PDP address organization %u\n", pdp_addr->organization); + return -EINVAL; + } + + pdp_addr_len -= 2; + switch (pdp_addr->type) { + case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4: + if (pdp_addr_len == sizeof(pdp_addr->addr)) { + osa4->u.sa.sa_family = AF_INET; + osa4->u.sin.sin_addr.s_addr = pdp_addr->addr; + } else if (pdp_addr_len != 0) { + LOGSM(LOGL_INFO, "Wrong IPv4 PDP address length %u\n", pdp_addr_len); + return -EINVAL; + } + break; + case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV6: + if (pdp_addr_len == sizeof(pdp_addr->addr6)) { + osa6->u.sa.sa_family = AF_INET6; + memcpy(osa6->u.sin6.sin6_addr.s6_addr, pdp_addr->addr6, sizeof(pdp_addr->addr6)); + } else if (pdp_addr_len != 0) { + LOGSM(LOGL_INFO, "Wrong IPv6 PDP address length %u\n", pdp_addr_len); + return -EINVAL; + } + break; + case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4V6: + if (pdp_addr_len == sizeof(pdp_addr->addr)) { + osa4->u.sa.sa_family = AF_INET; + osa4->u.sin.sin_addr.s_addr = pdp_addr->both.addr; + } else if (pdp_addr_len == sizeof(pdp_addr->both.addr6)) { + osa6->u.sa.sa_family = AF_INET6; + memcpy(osa6->u.sin6.sin6_addr.s6_addr, pdp_addr->both.addr6, sizeof(pdp_addr->both.addr6)); + } else if (pdp_addr_len == sizeof(pdp_addr->both)) { + osa4->u.sa.sa_family = AF_INET; + osa4->u.sin.sin_addr.s_addr = pdp_addr->both.addr; + osa6->u.sa.sa_family = AF_INET6; + memcpy(osa6->u.sin6.sin6_addr.s6_addr, pdp_addr->both.addr6, sizeof(pdp_addr->both.addr6)); + } else if (pdp_addr_len != 0) { + LOGSM(LOGL_INFO, "Wrong IPv4v6 PDP address length %u\n", pdp_addr_len); + return -EINVAL; + } + break; + default: + LOGSM(LOGL_INFO, "No IPv4 or IPv6\n"); + return -EINVAL; + } + *pdp_addr_ietf_type = pdp_addr->type; + + return 0; +} + /* Chapter 9.4.1: Attach request */ int gprs_sm_build_act_pdp_ctx_req(struct gprs_sm_entity *sme, struct msgb *msg)