summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2023-04-24 14:08:02 +0200
committerpespin <pespin@sysmocom.de>2023-04-25 22:16:26 +0000
commit0683b9033f40f6f46bcb8ae1cbba8887d3012755 (patch)
tree2261516a42277b40d8289d30978b981808138e31 /src/host/layer23/src
parent651426fee4e847d0d22d5b4845c3ead139a0b574 (diff)
layer23: modem: Set on tun the IP address received during PDP Ctx Act Accept
Diffstat (limited to 'src/host/layer23/src')
-rw-r--r--src/host/layer23/src/common/apn.c3
-rw-r--r--src/host/layer23/src/modem/sm.c81
2 files changed, 76 insertions, 8 deletions
diff --git a/src/host/layer23/src/common/apn.c b/src/host/layer23/src/common/apn.c
index 62aa0ff5..636246a9 100644
--- a/src/host/layer23/src/common/apn.c
+++ b/src/host/layer23/src/common/apn.c
@@ -81,9 +81,6 @@ int apn_start(struct osmobb_apn *apn)
LOGPAPN(LOGL_INFO, apn, "Opened TUN device %s\n", osmo_tundev_get_dev_name(apn->tun));
- /* TODO: set IP addresses on the tun device once we receive them from GGSN. See
- osmo-ggsn.git's apn_start() */
-
LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n");
apn->started = true;
return 0;
diff --git a/src/host/layer23/src/modem/sm.c b/src/host/layer23/src/modem/sm.c
index 67fdc49d..01d5a42d 100644
--- a/src/host/layer23/src/modem/sm.c
+++ b/src/host/layer23/src/modem/sm.c
@@ -46,20 +46,91 @@
#include <osmocom/bb/common/ms.h>
#include <osmocom/bb/modem/sm.h>
+
+static int modem_sm_handle_pdp_act_cnf(struct osmocom_ms *ms, struct osmo_gprs_sm_prim *sm_prim)
+{
+ const char *pdu_name = osmo_gprs_sm_prim_name(sm_prim);
+ struct osmobb_apn *apn = llist_first_entry_or_null(&ms->gprs.apn_list, struct osmobb_apn, list);
+ struct osmo_netdev *netdev;
+ char buf_addr[INET6_ADDRSTRLEN];
+ char buf_addr2[INET6_ADDRSTRLEN];
+ int rc;
+
+ if (!apn) {
+ LOGP(DSM, LOGL_ERROR, "Rx %s but have no APN!\n", pdu_name);
+ return -ENOENT;
+ }
+ if (apn->cfg.shutdown) {
+ LOGPAPN(LOGL_ERROR, apn, "Rx %s but APN is administratively shutdown!\n", pdu_name);
+ return -ENOENT;
+ }
+
+ if (!sm_prim->smreg.pdp_act_cnf.accepted) {
+ LOGPAPN(LOGL_ERROR, apn, "Rx %s: Activate PDP failed! cause '%s'\n", pdu_name,
+ get_value_string(gsm48_gsm_cause_names, sm_prim->smreg.pdp_act_cnf.rej.cause));
+ /* TODO: maybe retry ? */
+ return 0;
+ }
+
+ netdev = osmo_tundev_get_netdev(apn->tun);
+ switch (sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_ietf_type) {
+ case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4:
+ LOGPAPN(LOGL_INFO, apn, "Rx %s: IPv4=%s\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v4.u.sa, buf_addr));
+ rc = osmo_netdev_add_addr(netdev, &sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v4, 30);
+ if (rc < 0) {
+ LOGPAPN(LOGL_ERROR, apn, "Rx %s: Failed setting IPv4=%s\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v4.u.sa, buf_addr));
+ return rc;
+ }
+ break;
+ case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV6:
+ LOGPAPN(LOGL_INFO, apn, "Rx %s: IPv6=%s [FIXME: IPv6 not yet supported!]\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v6.u.sa, buf_addr));
+ rc = osmo_netdev_add_addr(netdev, &sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v6, 64);
+ if (rc < 0) {
+ LOGPAPN(LOGL_ERROR, apn, "Rx %s: Failed setting IPv6=%s\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v6.u.sa, buf_addr));
+ return rc;
+ }
+ break;
+ case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4V6:
+ LOGPAPN(LOGL_INFO, apn, "Rx %s: IPv4=%s IPv6=%s [FIXME: IPv6 not yet supported!]\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v4.u.sa, buf_addr),
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v6.u.sa, buf_addr2));
+ rc = osmo_netdev_add_addr(netdev, &sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v4, 30);
+ if (rc < 0) {
+ LOGPAPN(LOGL_ERROR, apn, "Rx %s: Failed setting IPv4=%s\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v4.u.sa, buf_addr));
+ return rc;
+ }
+ rc = osmo_netdev_add_addr(netdev, &sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v6, 64);
+ if (rc < 0) {
+ LOGPAPN(LOGL_ERROR, apn, "Rx %s: Failed setting IPv6=%s\n", pdu_name,
+ osmo_sockaddr_ntop(&sm_prim->smreg.pdp_act_cnf.acc.pdp_addr_v6.u.sa, buf_addr));
+ return rc;
+ }
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+ /* TODO: Handle PCO */
+ /* TODO: Handle QoS */
+ return rc;
+}
+
static int modem_sm_prim_up_cb(struct osmo_gprs_sm_prim *sm_prim, void *user_data)
{
const char *pdu_name = osmo_gprs_sm_prim_name(sm_prim);
+ struct osmocom_ms *ms = user_data;
int rc = 0;
switch (sm_prim->oph.sap) {
case OSMO_GPRS_SM_SAP_SMREG:
switch (OSMO_PRIM_HDR(&sm_prim->oph)) {
case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_CONFIRM):
- if (sm_prim->smreg.pdp_act_cnf.accepted)
- LOGP(DSM, LOGL_INFO, "%s(): Rx %s (TODO: set IP address in tun device)\n", __func__, pdu_name);
- else
- LOGP(DSM, LOGL_INFO, "%s(): Rx %s: Activate PDP failed! cause '%s'\n", __func__, pdu_name,
- get_value_string(gsm48_gsm_cause_names, sm_prim->smreg.pdp_act_cnf.rej.cause));
+ modem_sm_handle_pdp_act_cnf(ms, sm_prim);
break;
case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_INDICATION):
case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, PRIM_OP_CONFIRM):