Split gprs_sgsn.{c,h} -> {auth,mmctx,sgsn}.{c,h}
Some level of split already existed, like sgsn_auth.c, but headers were
entangled together.
Let's clearly separate application centric code (sgsn.c/h), auth related
code (auth.c/h) and mmctx related code (mmctx.c/h).
Change-Id: I048a082851c1275c959649942904205b02acce2a
diff --git a/include/osmocom/sgsn/mmctx.h b/include/osmocom/sgsn/mmctx.h
new file mode 100644
index 0000000..dd78124
--- /dev/null
+++ b/include/osmocom/sgsn/mmctx.h
@@ -0,0 +1,289 @@
+#pragma once
+
+#include <stdint.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/timer.h>
+
+#include <osmocom/gsm/gsm48.h>
+
+#include <osmocom/crypt/gprs_cipher.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+#include <osmocom/crypt/auth.h>
+
+#include <osmocom/sgsn/apn.h>
+#include <osmocom/sgsn/auth.h>
+#include <osmocom/sgsn/gprs_subscriber.h>
+
+#define GSM_EXTENSION_LENGTH 15
+
+struct gprs_llc_lle;
+struct ctrl_handle;
+struct gprs_subscr;
+struct sgsn_ggsn_ctx;
+struct sgsn_pdp_ctx;
+
+enum gsm48_gsm_cause;
+
+enum gprs_mm_ctr {
+ GMM_CTR_PKTS_SIG_IN,
+ GMM_CTR_PKTS_SIG_OUT,
+ GMM_CTR_PKTS_UDATA_IN,
+ GMM_CTR_PKTS_UDATA_OUT,
+ GMM_CTR_BYTES_UDATA_IN,
+ GMM_CTR_BYTES_UDATA_OUT,
+ GMM_CTR_PDP_CTX_ACT,
+ GMM_CTR_SUSPEND,
+ GMM_CTR_PAGING_PS,
+ GMM_CTR_PAGING_CS,
+ GMM_CTR_RA_UPDATE,
+};
+
+enum gprs_t3350_mode {
+ GMM_T3350_MODE_NONE,
+ GMM_T3350_MODE_ATT,
+ GMM_T3350_MODE_RAU,
+ GMM_T3350_MODE_PTMSI_REALL,
+};
+
+enum sgsn_ggsn_lookup_state {
+ SGSN_GGSN_2DIGIT,
+ SGSN_GGSN_3DIGIT,
+};
+
+struct sgsn_ggsn_lookup {
+ int state;
+
+ struct sgsn_mm_ctx *mmctx;
+
+ /* APN string */
+ char apn_str[GSM_APN_LENGTH];
+
+ /* the original data */
+ struct msgb *orig_msg;
+ struct tlv_parsed tp;
+
+ /* for dealing with re-transmissions */
+ uint8_t nsapi;
+ uint8_t sapi;
+ uint8_t ti;
+};
+
+enum sgsn_ran_type {
+ /* GPRS/EDGE via Gb */
+ MM_CTX_T_GERAN_Gb,
+ /* UMTS via Iu */
+ MM_CTX_T_UTRAN_Iu,
+#if 0
+ /* GPRS/EDGE via Iu, not supported */
+ MM_CTX_T_GERAN_Iu,
+#endif
+};
+extern const struct value_string sgsn_ran_type_names[];
+
+struct service_info {
+ uint8_t type;
+ uint16_t pdp_status;
+};
+
+struct ranap_ue_conn_ctx;
+
+/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
+/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
+struct sgsn_mm_ctx {
+ struct llist_head list;
+
+ enum sgsn_ran_type ran_type;
+
+ char imsi[GSM23003_IMSI_MAX_DIGITS+1];
+ struct osmo_fsm_inst *gmm_fsm;
+ uint32_t p_tmsi;
+ uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
+ uint32_t p_tmsi_sig;
+ char imei[GSM23003_IMEISV_NUM_DIGITS+1];
+ /* Opt: Software Version Numbber / TS 23.195 */
+ char msisdn[GSM_EXTENSION_LENGTH];
+ struct gprs_ra_id ra;
+ struct {
+ uint16_t cell_id; /* Gb only */
+ uint32_t cell_id_age; /* Gb only */
+ uint8_t radio_prio_sms;
+
+ /* Additional bits not present in the GSM TS */
+ uint16_t nsei;
+ uint16_t bvci;
+ struct gprs_llc_llme *llme;
+ uint32_t tlli;
+ uint32_t tlli_new;
+
+ /* TS 23.060 6.1.1 Mobility Management States (A/Gb mode) */
+ struct osmo_fsm_inst *mm_state_fsm;
+ } gb;
+ struct {
+ int new_key;
+ uint16_t sac; /* Iu: Service Area Code */
+ uint32_t sac_age; /* Iu: Service Area Code age */
+ /* CSG ID */
+ /* CSG Membership */
+ /* Access Mode */
+ /* Seelected CN Operator ID (TS 23.251) */
+ /* CSG Subscription Data */
+ /* LIPA Allowed */
+ /* Voice Support Match Indicator */
+ struct ranap_ue_conn_ctx *ue_ctx;
+ struct service_info service;
+ /* TS 23.060 6.1.2 Mobility Management States (Iu mode) */
+ struct osmo_fsm_inst *mm_state_fsm;
+ } iu;
+ struct {
+ struct osmo_fsm_inst *fsm;
+
+ /* when a second attach req arrives while in this procedure,
+ * the fsm needs to compare it against old to decide what to do */
+ struct msgb *attach_req;
+ uint32_t id_type;
+ unsigned int auth_reattempt; /* tracking UMTS resync auth attempts */
+ } gmm_att_req;
+ /* VLR number */
+ uint32_t new_sgsn_addr;
+ /* Authentication Triplet */
+ struct gsm_auth_tuple auth_triplet;
+ /* Kc */
+ /* Iu: CK, IK, KSI */
+ /* CKSN */
+ enum gprs_ciph_algo ciph_algo;
+ uint8_t ue_cipher_mask;
+ /* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
+ uint8_t ac_ref_nr_used;
+
+ struct {
+ uint8_t len;
+ uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
+ } ms_radio_access_capa;
+ /* Supported Codecs (SRVCC) */
+ struct {
+ uint8_t len;
+ uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
+ } ms_network_capa;
+ /* UE Netowrk Capability (E-UTRAN) */
+ uint16_t drx_parms;
+ /* Active Time value for PSM */
+ int mnrg; /* MS reported to HLR? */
+ int ngaf; /* MS reported to MSC/VLR? */
+ int ppf; /* paging for GPRS + non-GPRS? */
+ /* Subscribed Charging Characteristics */
+ /* Trace Reference */
+ /* Trace Type */
+ /* Trigger ID */
+ /* OMC Identity */
+ /* SMS Parameters */
+ int recovery;
+ /* Access Restriction */
+ /* GPRS CSI (CAMEL) */
+ /* MG-CSI (CAMEL) */
+ /* Subscribed UE-AMBR */
+ /* UE-AMBR */
+ /* APN Subscribed */
+
+ struct llist_head pdp_list;
+
+ struct rate_ctr_group *ctrg;
+ struct osmo_timer_list timer;
+ unsigned int T; /* Txxxx number */
+ unsigned int num_T_exp; /* number of consecutive T expirations */
+
+ enum gprs_t3350_mode t3350_mode;
+ uint8_t t3370_id_type;
+ uint8_t pending_req; /* the request's message type */
+ /* TODO: There isn't much semantic difference between t3350_mode
+ * (refers to the timer) and pending_req (refers to the procedure),
+ * where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
+ * whether one of them can be dropped. */
+
+ enum sgsn_auth_state auth_state;
+ enum osmo_sub_auth_type sec_ctx;
+
+ /* the string representation of the current hlr */
+ char hlr[GSM_EXTENSION_LENGTH];
+
+ /* the current GGSN look-up operation */
+ struct sgsn_ggsn_lookup *ggsn_lookup;
+
+ struct gprs_subscr *subscr;
+};
+
+static inline bool sgsn_mm_ctx_is_authenticated(struct sgsn_mm_ctx *ctx)
+{
+ switch (ctx->sec_ctx) {
+ case OSMO_AUTH_TYPE_GSM:
+ case OSMO_AUTH_TYPE_UMTS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+#define LOGMMCTXP(level, mm, fmt, args...) \
+ LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
+ (mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
+
+#ifdef BUILD_IU
+#define LOGIUP(ue, level, fmt, args...) \
+ LOGP(DMM, level, "UE(0x%x){%s} " fmt, ue->conn_id, osmo_rai_name(&(ue)->ra_id), ## args)
+#else
+#define LOGIUP(ue, level, fmt, args...) \
+ LOGP(DMM, level, "UE(%p){NOTSUPPORTED} " fmt, ue, ## args)
+#endif
+
+#define LOGGBP(llme, category, level, fmt, args...) \
+ LOGP(category, level, "LLME(%08x/%08x){%s} " fmt, (llme)->old_tlli, \
+ (llme)->tlli, get_value_string_or_null(gprs_llc_llme_state_names, (llme)->state), ## args);
+
+#define LOGGBIUP(llme, msg, level, fmt, args...) \
+ do { \
+ struct ranap_ue_conn_ctx * _ue; \
+ if (llme) { \
+ LOGGBP(llme, DMM, level, fmt, ## args); \
+ } else if ((msg) && (_ue = MSG_IU_UE_CTX(msg))) { \
+ LOGIUP(_ue, level, fmt, ## args); \
+ } else { OSMO_ASSERT(0); } \
+ } while (0)
+
+/* look-up a SGSN MM context based on TLLI + RAI */
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
+
+/* look-up by matching TLLI and P-TMSI (think twice before using this) */
+struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+
+/* Allocate a new SGSN MM context */
+struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
+ const struct gprs_ra_id *raid);
+struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
+
+void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
+
+struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
+ struct tlv_parsed *tp,
+ enum gsm48_gsm_cause *gsm_cause,
+ char *apn_str);
+
+/* look up PDP context by MM context and NSAPI */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
+ uint8_t nsapi);
+/* look up PDP context by MM context and transaction ID */
+struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
+ uint8_t tid);
+
+extern struct llist_head sgsn_mm_ctxts;
+
+uint32_t sgsn_alloc_ptmsi(void);
+
+/* Called on subscriber data updates */
+void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);