pespin has uploaded this change for review.
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(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-gprs refs/changes/15/32315/1
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)
To view, visit change 32315. To unsubscribe, or for help writing mail filters, visit settings.