diff options
Diffstat (limited to 'src/host')
-rw-r--r-- | src/host/layer23/src/common/apn.c | 3 | ||||
-rw-r--r-- | src/host/layer23/src/modem/sm.c | 81 |
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): |