diff options
Diffstat (limited to 'src/host/layer23/src/common/apn.c')
-rw-r--r-- | src/host/layer23/src/common/apn.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/host/layer23/src/common/apn.c b/src/host/layer23/src/common/apn.c new file mode 100644 index 00000000..cefa7641 --- /dev/null +++ b/src/host/layer23/src/common/apn.c @@ -0,0 +1,121 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdint.h> +#include <errno.h> +#include <string.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> + +#include <talloc.h> + +#include <osmocom/gprs/sm/sm.h> + +#include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/apn.h> +#include <osmocom/bb/common/ms.h> +#include <osmocom/bb/common/l23_app.h> + +struct osmobb_apn *apn_alloc(struct osmocom_ms *ms, const char *name) +{ + struct osmobb_apn *apn; + apn = talloc_zero(ms, struct osmobb_apn); + if (!apn) + return NULL; + + if (apn_fsm_ctx_init(&apn->fsm, apn) != 0) + goto ret_free; + + talloc_set_name(apn, "apn_%s", name); + apn->cfg.name = talloc_strdup(apn, name); + apn->cfg.shutdown = true; + apn->cfg.tx_gpdu_seq = true; + + apn->tun = osmo_tundev_alloc(apn, name); + if (!apn->tun) + goto ret_free_fsm; + osmo_tundev_set_priv_data(apn->tun, apn); + + apn->ms = ms; + /* FIXME: may want to configure or pick free one in the future: */ + apn->pdp.nsapi = 6; + apn->pdp.llc_sapi = OSMO_GPRS_SM_LLC_SAPI_SAPI3; + + /* QoS zeroed to 14 bytes is a valid QoS seen sent by some phones. Use + * that as default for now. */ + apn->pdp.qos_len = 14; + + llist_add_tail(&apn->list, &ms->gprs.apn_list); + return apn; + +ret_free_fsm: + apn_fsm_ctx_release(&apn->fsm); +ret_free: + talloc_free(apn); + return NULL; +} + +void apn_free(struct osmobb_apn *apn) +{ + apn_fsm_ctx_release(&apn->fsm); + llist_del(&apn->list); + osmo_tundev_free(apn->tun); + talloc_free(apn); +} + +int apn_start(struct osmobb_apn *apn) +{ + int rc; + + if (apn->started) + return 0; + + LOGPAPN(LOGL_INFO, apn, "Opening TUN device %s\n", apn->cfg.dev_name); + /* Set TUN library callback. Must have been configured by the app: */ + OSMO_ASSERT(l23_app_info.tun_data_ind_cb); + osmo_tundev_set_data_ind_cb(apn->tun, l23_app_info.tun_data_ind_cb); + osmo_tundev_set_dev_name(apn->tun, apn->cfg.dev_name); + osmo_tundev_set_netns_name(apn->tun, apn->cfg.dev_netns_name); + + rc = osmo_tundev_open(apn->tun); + if (rc < 0) { + LOGPAPN(LOGL_ERROR, apn, "Failed to configure tun device\n"); + return -1; + } + + LOGPAPN(LOGL_INFO, apn, "Opened TUN device %s\n", osmo_tundev_get_dev_name(apn->tun)); + + LOGPAPN(LOGL_NOTICE, apn, "Successfully started\n"); + apn->started = true; + return 0; +} + +int apn_stop(struct osmobb_apn *apn) +{ + LOGPAPN(LOGL_NOTICE, apn, "Stopping\n"); + + /* shutdown whatever old state might be left */ + if (apn->tun) { + /* release tun device */ + LOGPAPN(LOGL_INFO, apn, "Closing TUN device %s\n", + osmo_tundev_get_dev_name(apn->tun)); + osmo_tundev_close(apn->tun); + } + + apn->started = false; + return 0; +} |