blob: 1026474a1e5ee67ad2fd5fc7fea5d4d079fd058d [file] [log] [blame]
Harald Welte75bb8202010-03-14 15:45:01 +08001/* GSM Mobile Radio Interface Layer 3 messages on the A-bis interface
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
3
Harald Weltebdeaf5f2015-08-16 17:11:32 +02004/* (C) 2009-2015 by Harald Welte <laforge@gnumonks.org>
Harald Welte7e01d8e2010-05-31 20:23:38 +02005 * (C) 2010 by On-Waves
Harald Welte75bb8202010-03-14 15:45:01 +08006 *
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Harald Welte75bb8202010-03-14 15:45:01 +080012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Harald Welte75bb8202010-03-14 15:45:01 +080018 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Harald Welte75bb8202010-03-14 15:45:01 +080021 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Harald Welted85d9a92010-05-02 11:26:34 +020027#include <stdint.h>
Harald Welte75bb8202010-03-14 15:45:01 +080028#include <errno.h>
Max4bc28212016-07-06 11:59:18 +020029#include <stdbool.h>
Harald Welte75bb8202010-03-14 15:45:01 +080030#include <netinet/in.h>
Harald Welte2aea7492010-05-02 23:11:50 +020031#include <arpa/inet.h>
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +080032#include <netdb.h>
Harald Welte75bb8202010-03-14 15:45:01 +080033
Max9943d7a2016-07-05 15:19:12 +020034#include <openssl/rand.h>
35
Daniel Willmann945f6082016-05-21 17:35:57 +020036#include "bscconfig.h"
37
Harald Welte75bb8202010-03-14 15:45:01 +080038#include <openbsc/db.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010039#include <osmocom/core/msgb.h>
Harald Welte8b1713a2011-03-23 18:26:56 +010040#include <osmocom/gsm/tlv.h>
41#include <osmocom/gsm/gsm_utils.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010042#include <osmocom/core/signal.h>
43#include <osmocom/core/talloc.h>
44#include <osmocom/core/rate_ctr.h>
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +010045#include <osmocom/core/utils.h>
Daniel Willmannc3eb6a32016-05-21 00:31:12 +020046#include <osmocom/crypt/auth.h>
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +080047#include <osmocom/gsm/apn.h>
Harald Welte35ade5e2016-04-20 17:11:43 +020048#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Weltee4cc19a2010-05-02 12:57:45 +020049
Harald Weltecfb6b282012-06-16 14:59:56 +080050#include <osmocom/gprs/gprs_bssgp.h>
51
Daniel Willmann945f6082016-05-21 17:35:57 +020052#ifdef BUILD_IU
53#include <osmocom/ranap/ranap_ies_defs.h>
Daniel Willmanne0181a22016-05-21 00:35:41 +020054#include <osmocom/ranap/ranap_msg_factory.h>
Daniel Willmann945f6082016-05-21 17:35:57 +020055#endif
56
Harald Welte75bb8202010-03-14 15:45:01 +080057#include <openbsc/debug.h>
58#include <openbsc/gsm_data.h>
Harald Welte75bb8202010-03-14 15:45:01 +080059#include <openbsc/gsm_subscriber.h>
60#include <openbsc/gsm_04_08.h>
Harald Welte75bb8202010-03-14 15:45:01 +080061#include <openbsc/paging.h>
Harald Welte75bb8202010-03-14 15:45:01 +080062#include <openbsc/transaction.h>
63#include <openbsc/gprs_llc.h>
64#include <openbsc/gprs_sgsn.h>
Harald Welte29d838e2010-05-18 10:35:06 +020065#include <openbsc/gprs_gmm.h>
Jacob Erlbeck1063ae02015-01-23 11:44:39 +010066#include <openbsc/gprs_utils.h>
Harald Weltec1f6bfe2010-05-17 22:58:03 +020067#include <openbsc/sgsn.h>
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +020068#include <openbsc/signal.h>
Daniel Willmann945f6082016-05-21 17:35:57 +020069#include <openbsc/iu.h>
Daniel Willmann945f6082016-05-21 17:35:57 +020070
Harald Welte29d838e2010-05-18 10:35:06 +020071#include <pdp.h>
72
Harald Welte7e01d8e2010-05-31 20:23:38 +020073#define PTMSI_ALLOC
74
Harald Weltec1f6bfe2010-05-17 22:58:03 +020075extern struct sgsn_instance *sgsn;
Harald Welte75bb8202010-03-14 15:45:01 +080076
Harald Welted9610722010-06-09 10:28:29 +020077static const struct tlv_definition gsm48_gmm_att_tlvdef = {
78 .def = {
Harald Welte45fcf682010-07-03 11:09:06 +020079 [GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 },
Harald Welted9610722010-06-09 10:28:29 +020080 [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
81 [GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
Harald Welte45fcf682010-07-03 11:09:06 +020082 [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 },
83 [GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_FIXED, 16 },
84 [GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_FIXED, 4 },
Harald Welted9610722010-06-09 10:28:29 +020085 [GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
Harald Welte45fcf682010-07-03 11:09:06 +020086 [GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 },
Harald Welted9610722010-06-09 10:28:29 +020087 [GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
88 [GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
89 [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 },
90 [GSM48_IE_GMM_GMM_MBMS_CTX_ST] = { TLV_TYPE_TLV, 0 },
91 },
92};
93
94static const struct tlv_definition gsm48_sm_att_tlvdef = {
95 .def = {
96 [GSM48_IE_GSM_APN] = { TLV_TYPE_TLV, 0 },
97 [GSM48_IE_GSM_PROTO_CONF_OPT] = { TLV_TYPE_TLV, 0 },
98 [GSM48_IE_GSM_PDP_ADDR] = { TLV_TYPE_TLV, 0 },
99 [GSM48_IE_GSM_AA_TMR] = { TLV_TYPE_TV, 1 },
100 [GSM48_IE_GSM_NAME_FULL] = { TLV_TYPE_TLV, 0 },
101 [GSM48_IE_GSM_NAME_SHORT] = { TLV_TYPE_TLV, 0 },
Harald Welte45fcf682010-07-03 11:09:06 +0200102 [GSM48_IE_GSM_TIMEZONE] = { TLV_TYPE_FIXED, 1 },
103 [GSM48_IE_GSM_UTC_AND_TZ] = { TLV_TYPE_FIXED, 7 },
Harald Welted9610722010-06-09 10:28:29 +0200104 [GSM48_IE_GSM_LSA_ID] = { TLV_TYPE_TLV, 0 },
105 },
106};
107
Alexander Couzens41d17802017-01-31 18:13:15 +0100108static const struct value_string gprs_pmm_state_names[] = {
109 { PMM_DETACHED, "PMM DETACH" },
110 { PMM_CONNECTED, "PMM CONNECTED" },
111 { PMM_IDLE, "PMM IDLE" },
112 { MM_IDLE, "MM IDLE" },
113 { MM_READY, "MM READY" },
114 { MM_STANDBY, "MM STANDBY" },
115};
116
Jacob Erlbeckac336982014-12-02 09:47:26 +0100117static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx);
118
Daniel Willmann3d224b62016-05-11 12:43:47 +0200119static void mmctx_change_gtpu_endpoints_to_sgsn(struct sgsn_mm_ctx *mm_ctx)
120{
121 struct sgsn_pdp_ctx *pdp;
122 llist_for_each_entry(pdp, &mm_ctx->pdp_list, list) {
123 sgsn_pdp_upd_gtp_u(pdp,
124 &sgsn->cfg.gtp_listenaddr.sin_addr,
125 sizeof(sgsn->cfg.gtp_listenaddr.sin_addr));
126 }
127}
128
Daniel Willmanne9861832016-05-11 12:42:54 +0200129void mmctx_set_pmm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state)
130{
Alexander Couzens5e33f442017-01-31 15:34:26 +0100131 if (ctx->ran_type != MM_CTX_T_UTRAN_Iu)
132 return;
133
Daniel Willmanne9861832016-05-11 12:42:54 +0200134 if (ctx->pmm_state == state)
135 return;
136
Alexander Couzens41d17802017-01-31 18:13:15 +0100137 LOGMMCTXP(LOGL_INFO, ctx, "Changing PMM state from %s to %s\n",
138 get_value_string(gprs_pmm_state_names, ctx->pmm_state),
139 get_value_string(gprs_pmm_state_names, state));
Daniel Willmanne9861832016-05-11 12:42:54 +0200140
Alexander Couzens5e33f442017-01-31 15:34:26 +0100141 switch (state) {
142 case PMM_IDLE:
143 /* TODO: start RA Upd timer */
144 mmctx_change_gtpu_endpoints_to_sgsn(ctx);
145 break;
146 case PMM_CONNECTED:
147 break;
148 default:
149 break;
Daniel Willmanne9861832016-05-11 12:42:54 +0200150 }
151
152 ctx->pmm_state = state;
153}
154
Alexander Couzens5e33f442017-01-31 15:34:26 +0100155void mmctx_set_mm_state(struct sgsn_mm_ctx *ctx, enum gprs_pmm_state state)
156{
157 if (ctx->ran_type != MM_CTX_T_GERAN_Gb)
158 return;
159
160 if (ctx->pmm_state == state)
161 return;
162
Alexander Couzens41d17802017-01-31 18:13:15 +0100163 LOGMMCTXP(LOGL_INFO, ctx, "Changing MM state from %s to %s\n",
164 get_value_string(gprs_pmm_state_names, ctx->pmm_state),
165 get_value_string(gprs_pmm_state_names, state));
Alexander Couzens5e33f442017-01-31 15:34:26 +0100166
167 ctx->pmm_state = state;
168}
169
Daniel Willmann945f6082016-05-21 17:35:57 +0200170#ifdef BUILD_IU
171int sgsn_ranap_rab_ass_resp(struct sgsn_mm_ctx *ctx, RANAP_RAB_SetupOrModifiedItemIEs_t *setup_ies);
172int sgsn_ranap_iu_event(struct ue_conn_ctx *ctx, enum iu_event_type type, void *data)
173{
174 struct sgsn_mm_ctx *mm;
175 int rc = -1;
176
177 mm = sgsn_mm_ctx_by_ue_ctx(ctx);
178 if (!mm) {
179 LOGP(DRANAP, LOGL_NOTICE, "Cannot find mm ctx for IU event %i!\n", type);
180 return rc;
181 }
182
183 switch (type) {
184 case IU_EVENT_RAB_ASSIGN:
185 rc = sgsn_ranap_rab_ass_resp(mm, (RANAP_RAB_SetupOrModifiedItemIEs_t *)data);
186 break;
187 case IU_EVENT_IU_RELEASE:
188 /* fall thru */
189 case IU_EVENT_LINK_INVALIDATED:
190 /* Clean up ue_conn_ctx here */
191 LOGMMCTXP(LOGL_INFO, mm, "IU release for imsi %s\n", mm->imsi);
Daniel Willmann7d62c882016-05-21 00:01:21 +0200192 if (mm->pmm_state == PMM_CONNECTED)
Daniel Willmanne9861832016-05-11 12:42:54 +0200193 mmctx_set_pmm_state(mm, PMM_IDLE);
Daniel Willmann945f6082016-05-21 17:35:57 +0200194 rc = 0;
195 break;
196 case IU_EVENT_SECURITY_MODE_COMPLETE:
197 /* Continue authentication here */
198 mm->iu.ue_ctx->integrity_active = 1;
199 rc = gsm48_gmm_authorize(mm);
200 break;
201 default:
202 LOGP(DRANAP, LOGL_NOTICE, "Unknown event received: %i\n", type);
203 rc = -1;
204 break;
205 }
206 return rc;
207}
208#endif
209
210
Harald Welte8f77f192010-05-17 00:44:57 +0200211/* Our implementation, should be kept in SGSN */
Harald Welte75bb8202010-03-14 15:45:01 +0800212
Harald Welte7e01d8e2010-05-31 20:23:38 +0200213static void mmctx_timer_cb(void *_mm);
214
215static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T,
216 unsigned int seconds)
217{
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200218 if (osmo_timer_pending(&mm->timer))
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200219 LOGMMCTXP(LOGL_ERROR, mm, "Starting MM timer %u while old "
Harald Welte7e01d8e2010-05-31 20:23:38 +0200220 "timer %u pending\n", T, mm->T);
221 mm->T = T;
222 mm->num_T_exp = 0;
223
224 /* FIXME: we should do this only once ? */
225 mm->timer.data = mm;
226 mm->timer.cb = &mmctx_timer_cb;
227
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200228 osmo_timer_schedule(&mm->timer, seconds, 0);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200229}
230
231static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
232{
233 if (mm->T != T)
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200234 LOGMMCTXP(LOGL_ERROR, mm, "Stopping MM timer %u but "
Harald Welte7e01d8e2010-05-31 20:23:38 +0200235 "%u is running\n", T, mm->T);
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200236 osmo_timer_del(&mm->timer);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200237}
238
Jacob Erlbecke6140d02015-01-23 11:33:51 +0100239time_t gprs_max_time_to_idle(void)
240{
Harald Welte9b57a3d2015-08-15 19:08:21 +0200241 return sgsn->cfg.timers.T3314 + (sgsn->cfg.timers.T3312 + 4 * 60);
Jacob Erlbecke6140d02015-01-23 11:33:51 +0100242}
243
Neels Hofmeyr2a7ce0f2016-08-11 19:12:54 +0200244/* Send a message through the underlying layer.
245 * For param encryptable, see 3GPP TS 24.008 § 4.7.1.2 and
246 * gsm48_hdr_gmm_cipherable(). Pass false for not cipherable messages. */
Harald Welte8a035af2010-05-18 10:57:45 +0200247static int gsm48_gmm_sendmsg(struct msgb *msg, int command,
Max4bc28212016-07-06 11:59:18 +0200248 struct sgsn_mm_ctx *mm, bool encryptable)
Harald Welte75bb8202010-03-14 15:45:01 +0800249{
Daniel Willmann63dddc72016-05-21 17:36:18 +0200250 if (mm) {
Harald Welte8a035af2010-05-18 10:57:45 +0200251 rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_SIG_OUT]);
Daniel Willmann63dddc72016-05-21 17:36:18 +0200252#ifdef BUILD_IU
253 if (mm->ran_type == MM_CTX_T_UTRAN_Iu)
254 return iu_tx(msg, GPRS_SAPI_GMM);
255#endif
256 }
257
258#ifdef BUILD_IU
259 /* In Iu mode, msg->dst contains the ue_conn_ctx pointer, in Gb mode
260 * dst is empty. */
261 /* FIXME: have a more explicit indicator for Iu messages */
262 if (msg->dst)
263 return iu_tx(msg, GPRS_SAPI_GMM);
264#endif
Harald Welte8a035af2010-05-18 10:57:45 +0200265
Harald Welte2351f1f2010-05-02 11:54:55 +0200266 /* caller needs to provide TLLI, BVCI and NSEI */
Max4bc28212016-07-06 11:59:18 +0200267 return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm, encryptable);
Harald Welte75bb8202010-03-14 15:45:01 +0800268}
269
Harald Welte2351f1f2010-05-02 11:54:55 +0200270/* copy identifiers from old message to new message, this
271 * is required so lower layers can route it correctly */
272static void gmm_copy_id(struct msgb *msg, const struct msgb *old)
273{
274 msgb_tlli(msg) = msgb_tlli(old);
275 msgb_bvci(msg) = msgb_bvci(old);
276 msgb_nsei(msg) = msgb_nsei(old);
Daniel Willmann499d3ce2016-05-21 00:11:39 +0200277 msg->dst = old->dst;
Harald Welte2351f1f2010-05-02 11:54:55 +0200278}
279
Harald Welte29d838e2010-05-18 10:35:06 +0200280/* Store BVCI/NSEI in MM context */
281static void msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg)
282{
Harald Weltec28dc2f2015-12-25 19:12:21 +0100283 mm->gb.bvci = msgb_bvci(msg);
284 mm->gb.nsei = msgb_nsei(msg);
Daniel Willmann499d3ce2016-05-21 00:11:39 +0200285 /* In case a Iu connection is reconnected we need to update the ue ctx */
286 mm->iu.ue_ctx = msg->dst;
Harald Welte29d838e2010-05-18 10:35:06 +0200287}
288
289/* Store BVCI/NSEI in MM context */
290static void mmctx2msgid(struct msgb *msg, const struct sgsn_mm_ctx *mm)
291{
Harald Weltec28dc2f2015-12-25 19:12:21 +0100292 msgb_tlli(msg) = mm->gb.tlli;
293 msgb_bvci(msg) = mm->gb.bvci;
294 msgb_nsei(msg) = mm->gb.nsei;
Daniel Willmann499d3ce2016-05-21 00:11:39 +0200295 msg->dst = mm->iu.ue_ctx;
Harald Welte29d838e2010-05-18 10:35:06 +0200296}
297
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200298static void mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx, const char *log_text)
299{
Jacob Erlbeck70c177a2015-01-26 14:43:07 +0100300 LOGMMCTXP(LOGL_INFO, ctx, "Cleaning MM context due to %s\n", log_text);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200301
302 /* Mark MM state as deregistered */
Alexander Couzens5e33f442017-01-31 15:34:26 +0100303 ctx->gmm_state = GMM_DEREGISTERED;
Daniel Willmanne9861832016-05-11 12:42:54 +0200304 mmctx_set_pmm_state(ctx, PMM_DETACHED);
Alexander Couzens5e33f442017-01-31 15:34:26 +0100305 mmctx_set_pmm_state(ctx, MM_IDLE);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200306
Jacob Erlbeck70c177a2015-01-26 14:43:07 +0100307 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200308}
309
Harald Welte263edd12010-06-09 10:51:23 +0200310/* Chapter 9.4.18 */
311static int _tx_status(struct msgb *msg, uint8_t cause,
312 struct sgsn_mm_ctx *mmctx, int sm)
313{
314 struct gsm48_hdr *gh;
315
316 /* MMCTX might be NULL! */
317
318 DEBUGP(DMM, "<- GPRS MM STATUS (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +0100319 get_value_string(gsm48_gmm_cause_names, cause));
Harald Welte263edd12010-06-09 10:51:23 +0200320
321 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
322 if (sm) {
323 gh->proto_discr = GSM48_PDISC_SM_GPRS;
324 gh->msg_type = GSM48_MT_GSM_STATUS;
325 } else {
326 gh->proto_discr = GSM48_PDISC_MM_GPRS;
327 gh->msg_type = GSM48_MT_GMM_STATUS;
328 }
329 gh->data[0] = cause;
330
Max4bc28212016-07-06 11:59:18 +0200331 return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
Harald Welte263edd12010-06-09 10:51:23 +0200332}
Jacob Erlbeckce61bb72014-10-29 22:57:30 +0100333
Harald Welte263edd12010-06-09 10:51:23 +0200334static int gsm48_tx_gmm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
335{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100336 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 GMM STATUS");
Harald Welte263edd12010-06-09 10:51:23 +0200337
338 mmctx2msgid(msg, mmctx);
339 return _tx_status(msg, cause, mmctx, 0);
Harald Welte263edd12010-06-09 10:51:23 +0200340}
Jacob Erlbeckce61bb72014-10-29 22:57:30 +0100341
Harald Welte263edd12010-06-09 10:51:23 +0200342static int gsm48_tx_sm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
343{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100344 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SM STATUS");
Harald Welte263edd12010-06-09 10:51:23 +0200345
346 mmctx2msgid(msg, mmctx);
347 return _tx_status(msg, cause, mmctx, 1);
Harald Welte263edd12010-06-09 10:51:23 +0200348}
349
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200350static int _tx_detach_req(struct msgb *msg, uint8_t detach_type, uint8_t cause,
351 struct sgsn_mm_ctx *mmctx)
352{
353 struct gsm48_hdr *gh;
354
355 /* MMCTX might be NULL! */
356
357 DEBUGP(DMM, "<- GPRS MM DETACH REQ (type: %s, cause: %s)\n",
358 get_value_string(gprs_det_t_mt_strs, detach_type),
Jacob Erlbeck9346dad2015-01-05 17:30:02 +0100359 get_value_string(gsm48_gmm_cause_names, cause));
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200360
361 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
362
363 gh->proto_discr = GSM48_PDISC_MM_GPRS;
364 gh->msg_type = GSM48_MT_GMM_DETACH_REQ;
365 gh->data[0] = detach_type & 0x07;
366
367 msgb_tv_put(msg, GSM48_IE_GMM_CAUSE, cause);
368
Max4bc28212016-07-06 11:59:18 +0200369 return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200370}
371
372static int gsm48_tx_gmm_detach_req(struct sgsn_mm_ctx *mmctx,
373 uint8_t detach_type, uint8_t cause)
374{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100375 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET REQ");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200376
377 mmctx2msgid(msg, mmctx);
378 return _tx_detach_req(msg, detach_type, cause, mmctx);
379}
380
381static int gsm48_tx_gmm_detach_req_oldmsg(struct msgb *oldmsg,
382 uint8_t detach_type, uint8_t cause)
383{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100384 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET OLD");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200385
386 gmm_copy_id(msg, oldmsg);
387 return _tx_detach_req(msg, detach_type, cause, NULL);
388}
Harald Welte263edd12010-06-09 10:51:23 +0200389
Harald Welte242d1722010-05-03 10:54:35 +0200390static struct gsm48_qos default_qos = {
391 .delay_class = 4, /* best effort */
392 .reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT,
393 .peak_tput = GSM48_QOS_PEAK_TPUT_32000bps,
394 .preced_class = GSM48_QOS_PC_NORMAL,
395 .mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT,
396 .traf_class = GSM48_QOS_TC_INTERACTIVE,
397 .deliv_order = GSM48_QOS_DO_UNORDERED,
398 .deliv_err_sdu = GSM48_QOS_ERRSDU_YES,
399 .max_sdu_size = GSM48_QOS_MAXSDU_1520,
400 .max_bitrate_up = GSM48_QOS_MBRATE_63k,
401 .max_bitrate_down = GSM48_QOS_MBRATE_63k,
402 .resid_ber = GSM48_QOS_RBER_5e_2,
403 .sdu_err_ratio = GSM48_QOS_SERR_1e_2,
404 .handling_prio = 3,
405 .xfer_delay = 0x10, /* 200ms */
406 .guar_bitrate_up = GSM48_QOS_MBRATE_0k,
407 .guar_bitrate_down = GSM48_QOS_MBRATE_0k,
408 .sig_ind = 0, /* not optimised for signalling */
409 .max_bitrate_down_ext = 0, /* use octet 9 */
410 .guar_bitrate_down_ext = 0, /* use octet 13 */
411};
412
Harald Welte75bb8202010-03-14 15:45:01 +0800413/* Chapter 9.4.2: Attach accept */
Harald Welte64df8ed2010-05-18 17:04:55 +0200414static int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
Harald Welte75bb8202010-03-14 15:45:01 +0800415{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100416 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT ACK");
Harald Welte75bb8202010-03-14 15:45:01 +0800417 struct gsm48_hdr *gh;
418 struct gsm48_attach_ack *aa;
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +0200419 uint8_t *mid;
420#if 0
421 uint8_t *ptsig;
422#endif
Harald Welte75bb8202010-03-14 15:45:01 +0800423
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200424 LOGMMCTXP(LOGL_INFO, mm, "<- GPRS ATTACH ACCEPT (new P-TMSI=0x%08x)\n", mm->p_tmsi);
Alexander Couzens32fdba02016-07-05 09:52:52 +0200425 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_ACKED]);
Harald Welte75bb8202010-03-14 15:45:01 +0800426
Harald Welte64df8ed2010-05-18 17:04:55 +0200427 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +0800428
429 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
430 gh->proto_discr = GSM48_PDISC_MM_GPRS;
431 gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
432
433 aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
434 aa->force_stby = 0; /* not indicated */
435 aa->att_result = 1; /* GPRS only */
Harald Welte9b57a3d2015-08-15 19:08:21 +0200436 aa->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
Harald Welte75bb8202010-03-14 15:45:01 +0800437 aa->radio_prio = 4; /* lowest */
Harald Welte64df8ed2010-05-18 17:04:55 +0200438 gsm48_construct_ra(aa->ra_id.digits, &mm->ra);
Harald Welte75bb8202010-03-14 15:45:01 +0800439
Harald Welteebe8a6d2010-05-18 19:58:38 +0200440#if 0
Harald Welte64df8ed2010-05-18 17:04:55 +0200441 /* Optional: P-TMSI signature */
442 msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
443 ptsig = msgb_put(msg, 3);
444 ptsig[0] = mm->p_tmsi_sig >> 16;
445 ptsig[1] = mm->p_tmsi_sig >> 8;
446 ptsig[2] = mm->p_tmsi_sig & 0xff;
447
Harald Welte7e01d8e2010-05-31 20:23:38 +0200448#endif
Jacob Erlbeck1063ae02015-01-23 11:44:39 +0100449 /* Optional: Negotiated Ready timer value
450 * (fixed 44s, default value, GSM 04.08, table 11.4a) to safely limit
451 * the inactivity time READY->STANDBY.
452 */
453 msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
Harald Welte9b57a3d2015-08-15 19:08:21 +0200454 gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
Harald Welte64df8ed2010-05-18 17:04:55 +0200455
Harald Welte7e01d8e2010-05-31 20:23:38 +0200456#ifdef PTMSI_ALLOC
Harald Welte64df8ed2010-05-18 17:04:55 +0200457 /* Optional: Allocated P-TMSI */
Harald Welte64df8ed2010-05-18 17:04:55 +0200458 mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
459 gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
Harald Welteebe8a6d2010-05-18 19:58:38 +0200460 mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
461#endif
Harald Welte7e01d8e2010-05-31 20:23:38 +0200462
Harald Welte64df8ed2010-05-18 17:04:55 +0200463 /* Optional: MS-identity (combined attach) */
464 /* Optional: GMM cause (partial attach result for combined attach) */
465
Max4bc28212016-07-06 11:59:18 +0200466 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte75bb8202010-03-14 15:45:01 +0800467}
468
469/* Chapter 9.4.5: Attach reject */
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200470static int _tx_gmm_att_rej(struct msgb *msg, uint8_t gmm_cause,
471 const struct sgsn_mm_ctx *mm)
Harald Welte75bb8202010-03-14 15:45:01 +0800472{
Harald Welte75bb8202010-03-14 15:45:01 +0800473 struct gsm48_hdr *gh;
474
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200475 LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS ATTACH REJECT: %s\n",
476 get_value_string(gsm48_gmm_cause_names, gmm_cause));
Alexander Couzens32fdba02016-07-05 09:52:52 +0200477 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_REJECTED]);
Harald Welte75bb8202010-03-14 15:45:01 +0800478
Harald Welte75bb8202010-03-14 15:45:01 +0800479 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
480 gh->proto_discr = GSM48_PDISC_MM_GPRS;
481 gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
482 gh->data[0] = gmm_cause;
483
Max4bc28212016-07-06 11:59:18 +0200484 return gsm48_gmm_sendmsg(msg, 0, NULL, false);
Harald Welte75bb8202010-03-14 15:45:01 +0800485}
Harald Welte64df8ed2010-05-18 17:04:55 +0200486static int gsm48_tx_gmm_att_rej_oldmsg(const struct msgb *old_msg,
487 uint8_t gmm_cause)
488{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100489 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT REJ OLD");
Harald Welte64df8ed2010-05-18 17:04:55 +0200490 gmm_copy_id(msg, old_msg);
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200491 return _tx_gmm_att_rej(msg, gmm_cause, NULL);
Harald Welte64df8ed2010-05-18 17:04:55 +0200492}
493static int gsm48_tx_gmm_att_rej(struct sgsn_mm_ctx *mm,
494 uint8_t gmm_cause)
495{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100496 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT REJ");
Harald Welte64df8ed2010-05-18 17:04:55 +0200497 mmctx2msgid(msg, mm);
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200498 return _tx_gmm_att_rej(msg, gmm_cause, mm);
Harald Welte64df8ed2010-05-18 17:04:55 +0200499}
Harald Welte75bb8202010-03-14 15:45:01 +0800500
Harald Welte8f77f192010-05-17 00:44:57 +0200501/* Chapter 9.4.6.2 Detach accept */
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200502static int _tx_detach_ack(struct msgb *msg, uint8_t force_stby,
503 struct sgsn_mm_ctx *mm)
Harald Welte8f77f192010-05-17 00:44:57 +0200504{
Harald Welte8f77f192010-05-17 00:44:57 +0200505 struct gsm48_hdr *gh;
506
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200507 /* MMCTX might be NULL! */
Harald Welte8f77f192010-05-17 00:44:57 +0200508
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200509 DEBUGP(DMM, "<- GPRS MM DETACH ACC (force-standby: %d)\n", force_stby);
Alexander Couzens32fdba02016-07-05 09:52:52 +0200510 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_DETACH_ACKED]);
Harald Welte64df8ed2010-05-18 17:04:55 +0200511
Harald Welte8f77f192010-05-17 00:44:57 +0200512 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
513 gh->proto_discr = GSM48_PDISC_MM_GPRS;
514 gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
515 gh->data[0] = force_stby;
516
Max4bc28212016-07-06 11:59:18 +0200517 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte8f77f192010-05-17 00:44:57 +0200518}
519
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200520static int gsm48_tx_gmm_det_ack(struct sgsn_mm_ctx *mm, uint8_t force_stby)
521{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100522 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACK");
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200523
524 mmctx2msgid(msg, mm);
525 return _tx_detach_ack(msg, force_stby, mm);
526}
527
528static int gsm48_tx_gmm_det_ack_oldmsg(struct msgb *oldmsg, uint8_t force_stby)
529{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100530 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACK OLD");
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200531
532 gmm_copy_id(msg, oldmsg);
533 return _tx_detach_ack(msg, force_stby, NULL);
534}
535
Harald Welte75bb8202010-03-14 15:45:01 +0800536/* Transmit Chapter 9.4.12 Identity Request */
Harald Welte64df8ed2010-05-18 17:04:55 +0200537static int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type)
Harald Welte75bb8202010-03-14 15:45:01 +0800538{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100539 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ID REQ");
Harald Welte75bb8202010-03-14 15:45:01 +0800540 struct gsm48_hdr *gh;
541
Harald Welte7e3e9332015-08-16 18:07:48 +0200542 LOGMMCTXP(LOGL_DEBUG, mm, "<- GPRS IDENTITY REQUEST: mi_type=%s\n",
543 gsm48_mi_type_name(id_type));
Harald Welte75bb8202010-03-14 15:45:01 +0800544
Harald Welte64df8ed2010-05-18 17:04:55 +0200545 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +0800546
547 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
548 gh->proto_discr = GSM48_PDISC_MM_GPRS;
549 gh->msg_type = GSM48_MT_GMM_ID_REQ;
550 /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
551 gh->data[0] = id_type & 0xf;
552
Max4bc28212016-07-06 11:59:18 +0200553 return gsm48_gmm_sendmsg(msg, 1, mm, false);
Harald Welte75bb8202010-03-14 15:45:01 +0800554}
555
Max6d999582016-07-06 15:57:01 +0200556/* 3GPP TS 24.008 Section 9.4.9: Authentication and Ciphering Request */
Max9943d7a2016-07-05 15:19:12 +0200557static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rnd,
Max6d999582016-07-06 15:57:01 +0200558 uint8_t key_seq, bool force_standby)
Harald Welte45fcf682010-07-03 11:09:06 +0200559{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100560 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REQ");
Harald Welte45fcf682010-07-03 11:09:06 +0200561 struct gsm48_hdr *gh;
562 struct gsm48_auth_ciph_req *acreq;
Max9943d7a2016-07-05 15:19:12 +0200563 uint8_t *m_rand, *m_cksn, rbyte;
Harald Welte45fcf682010-07-03 11:09:06 +0200564
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200565 LOGMMCTXP(LOGL_INFO, mm, "<- GPRS AUTH AND CIPHERING REQ (rand = %s)\n",
Max9943d7a2016-07-05 15:19:12 +0200566 osmo_hexdump(rnd, 16));
Harald Welte45fcf682010-07-03 11:09:06 +0200567
568 mmctx2msgid(msg, mm);
569
570 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
571 gh->proto_discr = GSM48_PDISC_MM_GPRS;
572 gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REQ;
573
574 acreq = (struct gsm48_auth_ciph_req *) msgb_put(msg, sizeof(*acreq));
Max6d999582016-07-06 15:57:01 +0200575 acreq->ciph_alg = mm->ciph_algo & 0xf;
576 /* § 10.5.5.10: */
Harald Welte45fcf682010-07-03 11:09:06 +0200577 acreq->imeisv_req = 0x1;
Max6d999582016-07-06 15:57:01 +0200578 /* § 10.5.5.7: */
579 acreq->force_stby = force_standby;
Max9943d7a2016-07-05 15:19:12 +0200580 /* 3GPP TS 24.008 § 10.5.5.19: */
581 if (RAND_bytes(&rbyte, 1) != 1) {
582 LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed for A&C ref, falling "
583 "back to rand()\n");
584 acreq->ac_ref_nr = rand();
585 } else
586 acreq->ac_ref_nr = rbyte;
587 mm->ac_ref_nr_used = acreq->ac_ref_nr;
Harald Welte45fcf682010-07-03 11:09:06 +0200588
589 /* Only if authentication is requested we need to set RAND + CKSN */
Max9943d7a2016-07-05 15:19:12 +0200590 if (rnd) {
Harald Welte45fcf682010-07-03 11:09:06 +0200591 m_rand = msgb_put(msg, 16+1);
592 m_rand[0] = GSM48_IE_GMM_AUTH_RAND;
Max9943d7a2016-07-05 15:19:12 +0200593 memcpy(m_rand + 1, rnd, 16);
Max6d999582016-07-06 15:57:01 +0200594 /* § 10.5.1.2: */
Jacob Erlbeck79dcaa42014-12-01 10:36:17 +0100595 m_cksn = msgb_put(msg, 1);
596 m_cksn[0] = (GSM48_IE_GMM_CIPH_CKSN << 4) | (key_seq & 0x07);
Harald Welte45fcf682010-07-03 11:09:06 +0200597 }
Max6d999582016-07-06 15:57:01 +0200598 /* FIXME: add AUTN for 3g auth according to 3GPP TS 24.008 § 10.5.3.1.1 */
Harald Welte45fcf682010-07-03 11:09:06 +0200599 /* FIXME: make sure we don't send any other messages to the MS */
600
Max4bc28212016-07-06 11:59:18 +0200601 return gsm48_gmm_sendmsg(msg, 1, mm, false);
Harald Welte45fcf682010-07-03 11:09:06 +0200602}
603
604/* Section 9.4.11: Authentication and Ciphering Reject */
605static int gsm48_tx_gmm_auth_ciph_rej(struct sgsn_mm_ctx *mm)
606{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100607 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REJ");
Harald Welte45fcf682010-07-03 11:09:06 +0200608 struct gsm48_hdr *gh;
609
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200610 LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS AUTH AND CIPH REJECT\n");
Harald Welte45fcf682010-07-03 11:09:06 +0200611
612 mmctx2msgid(msg, mm);
613
614 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
615 gh->proto_discr = GSM48_PDISC_MM_GPRS;
616 gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REJ;
617
Max4bc28212016-07-06 11:59:18 +0200618 return gsm48_gmm_sendmsg(msg, 0, mm, false);
Harald Welte45fcf682010-07-03 11:09:06 +0200619}
620
621/* Section 9.4.10: Authentication and Ciphering Response */
622static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
623 struct msgb *msg)
624{
625 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
626 struct gsm48_auth_ciph_resp *acr = (struct gsm48_auth_ciph_resp *)gh->data;
627 struct tlv_parsed tp;
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100628 struct gsm_auth_tuple *at;
629 int rc;
630
631 LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS AUTH AND CIPH RESPONSE\n");
632
633 if (ctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
634 LOGMMCTXP(LOGL_NOTICE, ctx,
635 "Unexpected Auth & Ciph Response (ignored)\n");
636 return 0;
637 }
Harald Welte45fcf682010-07-03 11:09:06 +0200638
Max9943d7a2016-07-05 15:19:12 +0200639 if (acr->ac_ref_nr != ctx->ac_ref_nr_used) {
640 LOGMMCTXP(LOGL_NOTICE, ctx, "Reference mismatch for Auth & Ciph"
641 " Response: %u received, %u expected\n",
642 acr->ac_ref_nr, ctx->ac_ref_nr_used);
643 return 0;
644 }
645
Jacob Erlbeck4d127672014-12-01 12:33:33 +0100646 /* Stop T3360 */
647 mmctx_timer_stop(ctx, 3360);
Harald Welte45fcf682010-07-03 11:09:06 +0200648
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +0200649 tlv_parse(&tp, &gsm48_gmm_att_tlvdef, acr->data,
Harald Welte45fcf682010-07-03 11:09:06 +0200650 (msg->data + msg->len) - acr->data, 0, 0);
651
Harald Welte45fcf682010-07-03 11:09:06 +0200652 if (!TLVP_PRESENT(&tp, GSM48_IE_GMM_AUTH_SRES) ||
653 !TLVP_PRESENT(&tp, GSM48_IE_GMM_IMEISV)) {
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100654 /* TODO: missing mandatory IE, return STATUS or REJ? */
655 LOGMMCTXP(LOGL_ERROR, ctx, "Missing mandantory IE\n");
656 return -EINVAL;
Harald Welte45fcf682010-07-03 11:09:06 +0200657 }
658
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100659 /* Compare SRES with what we expected */
660 LOGMMCTXP(LOGL_DEBUG, ctx, "checking received auth info, SRES = %s\n",
661 osmo_hexdump(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES),
662 TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES)));
663
664 at = &ctx->auth_triplet;
665
Harald Welte34ef4c52016-04-20 13:13:19 +0200666 if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES) != sizeof(at->vec.sres) ||
667 memcmp(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), at->vec.sres,
668 sizeof(at->vec.sres)) != 0) {
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100669
Max2b521252017-01-13 19:18:52 +0100670 LOGMMCTXP(LOGL_NOTICE, ctx, "Received SRES doesn't match "
671 "expected RES %s\n", osmo_hexdump(at->vec.sres,
672 sizeof(at->vec.sres)));
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100673 rc = gsm48_tx_gmm_auth_ciph_rej(ctx);
674 mm_ctx_cleanup_free(ctx, "GPRS AUTH AND CIPH REJECT");
675 return rc;
676 }
677
678 ctx->is_authenticated = 1;
679
Daniel Willmann522fee82016-05-21 00:16:55 +0200680 if (ctx->ran_type == MM_CTX_T_UTRAN_Iu)
681 ctx->iu.new_key = 1;
682
Harald Welte45fcf682010-07-03 11:09:06 +0200683 /* FIXME: enable LLC cipheirng */
Jacob Erlbeckac336982014-12-02 09:47:26 +0100684
685 /* Check if we can let the mobile station enter */
686 return gsm48_gmm_authorize(ctx);
Harald Welte45fcf682010-07-03 11:09:06 +0200687}
688
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +0200689static void extract_subscr_msisdn(struct sgsn_mm_ctx *ctx)
690{
691 struct gsm_mncc_number called;
692 uint8_t msisdn[sizeof(ctx->subscr->sgsn_data->msisdn) + 1];
693
694 /* Convert MSISDN from encoded to string.. */
695 if (!ctx->subscr)
696 return;
697
698 if (ctx->subscr->sgsn_data->msisdn_len < 1)
699 return;
700
701 /* prepare the data for the decoder */
702 memset(&called, 0, sizeof(called));
703 msisdn[0] = ctx->subscr->sgsn_data->msisdn_len;
704 memcpy(&msisdn[1], ctx->subscr->sgsn_data->msisdn,
705 ctx->subscr->sgsn_data->msisdn_len);
706
707 /* decode the string now */
708 gsm48_decode_called(&called, msisdn);
709
710 /* Prepend a '+' for international numbers */
711 if (called.plan == 1 && called.type == 1) {
712 ctx->msisdn[0] = '+';
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +0100713 osmo_strlcpy(&ctx->msisdn[1], called.number,
714 sizeof(ctx->msisdn));
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +0200715 } else {
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +0100716 osmo_strlcpy(ctx->msisdn, called.number, sizeof(ctx->msisdn));
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +0200717 }
718}
719
Holger Hans Peter Freyther8b2b5fb2015-05-18 10:00:03 +0200720static void extract_subscr_hlr(struct sgsn_mm_ctx *ctx)
721{
722 struct gsm_mncc_number called;
723 uint8_t hlr_number[sizeof(ctx->subscr->sgsn_data->hlr) + 1];
724
725 if (!ctx->subscr)
726 return;
727
728 if (ctx->subscr->sgsn_data->hlr_len < 1)
729 return;
730
731 /* prepare the data for the decoder */
732 memset(&called, 0, sizeof(called));
733 hlr_number[0] = ctx->subscr->sgsn_data->hlr_len;
734 memcpy(&hlr_number[1], ctx->subscr->sgsn_data->hlr,
735 ctx->subscr->sgsn_data->hlr_len);
736
737 /* decode the string now */
738 gsm48_decode_called(&called, hlr_number);
739
740 if (called.plan != 1) {
741 LOGMMCTXP(LOGL_ERROR, ctx,
742 "Numbering plan(%d) not allowed\n",
743 called.plan);
744 return;
745 }
746
747 if (called.type != 1) {
748 LOGMMCTXP(LOGL_ERROR, ctx,
749 "Numbering type(%d) not allowed\n",
750 called.type);
751 return;
752 }
753
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +0100754 osmo_strlcpy(ctx->hlr, called.number, sizeof(ctx->hlr));
Holger Hans Peter Freyther8b2b5fb2015-05-18 10:00:03 +0200755}
756
Daniel Willmann65edec82016-05-21 00:15:29 +0200757#ifdef BUILD_IU
758/* Chapter 9.4.21: Service accept */
759static int gsm48_tx_gmm_service_ack(struct sgsn_mm_ctx *mm)
760{
761 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE ACK");
762 struct gsm48_hdr *gh;
763
764 LOGMMCTXP(LOGL_INFO, mm, "<- GPRS SERVICE ACCEPT (P-TMSI=0x%08x)\n", mm->p_tmsi);
765
766 mmctx2msgid(msg, mm);
767
768 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
769 gh->proto_discr = GSM48_PDISC_MM_GPRS;
770 gh->msg_type = GSM48_MT_GMM_SERVICE_ACK;
771
772 /* Optional: PDP context status */
773 /* Optional: MBMS context status */
774
775 return gsm48_gmm_sendmsg(msg, 0, mm, false);
776}
777#endif
778
779/* Chapter 9.4.22: Service reject */
780static int _tx_gmm_service_rej(struct msgb *msg, uint8_t gmm_cause,
781 const struct sgsn_mm_ctx *mm)
782{
783 struct gsm48_hdr *gh;
784
785 LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS SERVICE REJECT: %s\n",
786 get_value_string(gsm48_gmm_cause_names, gmm_cause));
787
788 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
789 gh->proto_discr = GSM48_PDISC_MM_GPRS;
790 gh->msg_type = GSM48_MT_GMM_SERVICE_REJ;
791 gh->data[0] = gmm_cause;
792
793 return gsm48_gmm_sendmsg(msg, 0, NULL, true);
794}
795static int gsm48_tx_gmm_service_rej_oldmsg(const struct msgb *old_msg,
796 uint8_t gmm_cause)
797{
798 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE REJ OLD");
799 gmm_copy_id(msg, old_msg);
800 return _tx_gmm_service_rej(msg, gmm_cause, NULL);
801}
802#if 0
803-- currently unused --
804static int gsm48_tx_gmm_service_rej(struct sgsn_mm_ctx *mm,
805 uint8_t gmm_cause)
806{
807 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERVICE REJ");
808 mmctx2msgid(msg, mm);
809 return _tx_gmm_service_rej(msg, gmm_cause, mm);
810}
811#endif
812
813static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm);
814
815#ifdef BUILD_IU
816void activate_pdp_rabs(struct sgsn_mm_ctx *ctx)
817{
818 /* Send RAB activation requests for all PDP contexts */
819 struct sgsn_pdp_ctx *pdp;
820 llist_for_each_entry(pdp, &ctx->pdp_list, list) {
821 iu_rab_act_ps(pdp->nsapi, pdp, 1);
822 }
823}
824#endif
825
Harald Welte75bb8202010-03-14 15:45:01 +0800826/* Check if we can already authorize a subscriber */
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100827static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
Harald Welte75bb8202010-03-14 15:45:01 +0800828{
Daniel Willmann522fee82016-05-21 00:16:55 +0200829#ifdef BUILD_IU
830 int rc;
831#endif
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +0200832#ifndef PTMSI_ALLOC
833 struct sgsn_signal_data sig_data;
834#endif
835
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100836 /* Request IMSI and IMEI from the MS if they are unknown */
Harald Welte7e01d8e2010-05-31 20:23:38 +0200837 if (!strlen(ctx->imei)) {
Harald Welte7e01d8e2010-05-31 20:23:38 +0200838 ctx->t3370_id_type = GSM_MI_TYPE_IMEI;
Harald Welte9b57a3d2015-08-15 19:08:21 +0200839 mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
Harald Welte64df8ed2010-05-18 17:04:55 +0200840 return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMEI);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200841 }
Harald Welte7e01d8e2010-05-31 20:23:38 +0200842 if (!strlen(ctx->imsi)) {
Harald Welte7e01d8e2010-05-31 20:23:38 +0200843 ctx->t3370_id_type = GSM_MI_TYPE_IMSI;
Harald Welte9b57a3d2015-08-15 19:08:21 +0200844 mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
Harald Welte64df8ed2010-05-18 17:04:55 +0200845 return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMSI);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200846 }
Harald Welte75bb8202010-03-14 15:45:01 +0800847
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100848 /* All information required for authentication is available */
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100849 ctx->t3370_id_type = GSM_MI_TYPE_NONE;
850
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200851 if (ctx->auth_state == SGSN_AUTH_UNKNOWN) {
852 /* Request authorization, this leads to a call to
Jacob Erlbeck802d78a2014-11-07 14:17:44 +0100853 * sgsn_auth_update which in turn calls
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200854 * gsm0408_gprs_access_granted or gsm0408_gprs_access_denied */
855
Jacob Erlbeckb2acd742014-11-13 10:48:39 +0100856 sgsn_auth_request(ctx);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200857 /* Note that gsm48_gmm_authorize can be called recursively via
858 * sgsn_auth_request iff ctx->auth_info changes to AUTH_ACCEPTED
859 */
860 return 0;
861 }
862
Jacob Erlbeckac336982014-12-02 09:47:26 +0100863 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && !ctx->is_authenticated) {
864 struct gsm_auth_tuple *at = &ctx->auth_triplet;
865
Harald Welte9b57a3d2015-08-15 19:08:21 +0200866 mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360);
Harald Welte34ef4c52016-04-20 13:13:19 +0200867 return gsm48_tx_gmm_auth_ciph_req(ctx, at->vec.rand,
Max6d999582016-07-06 15:57:01 +0200868 at->key_seq, false);
Jacob Erlbeckac336982014-12-02 09:47:26 +0100869 }
870
871 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && ctx->is_authenticated &&
872 ctx->auth_triplet.key_seq != GSM_KEY_SEQ_INVAL) {
873 /* Check again for authorization */
874 sgsn_auth_request(ctx);
875 return 0;
876 }
877
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200878 if (ctx->auth_state != SGSN_AUTH_ACCEPTED) {
879 LOGMMCTXP(LOGL_NOTICE, ctx,
880 "authorization is denied, aborting procedure\n");
881 return -EACCES;
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100882 }
883
884 /* The MS is authorized */
Daniel Willmann522fee82016-05-21 00:16:55 +0200885#ifdef BUILD_IU
886 if (ctx->ran_type == MM_CTX_T_UTRAN_Iu && !ctx->iu.ue_ctx->integrity_active) {
887 rc = iu_tx_sec_mode_cmd(ctx->iu.ue_ctx, &ctx->auth_triplet, 0, ctx->iu.new_key);
888 ctx->iu.new_key = 0;
889 return rc;
890 }
891#endif
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100892
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100893 switch (ctx->pending_req) {
894 case 0:
895 LOGMMCTXP(LOGL_INFO, ctx,
896 "no pending request, authorization completed\n");
897 break;
898 case GSM48_MT_GMM_ATTACH_REQ:
Daniel Willmann68ce9e32016-05-21 00:21:15 +0200899 ctx->pending_req = 0;
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +0200900
901 extract_subscr_msisdn(ctx);
Holger Hans Peter Freyther8b2b5fb2015-05-18 10:00:03 +0200902 extract_subscr_hlr(ctx);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100903#ifdef PTMSI_ALLOC
904 /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
Harald Welte9b57a3d2015-08-15 19:08:21 +0200905 mmctx_timer_start(ctx, 3350, sgsn->cfg.timers.T3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100906 ctx->t3350_mode = GMM_T3350_MODE_ATT;
Jacob Erlbeck67318ef2014-10-28 16:23:46 +0100907#else
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +0200908 memset(&sig_data, 0, sizeof(sig_data));
909 sig_data.mm = mmctx;
910 osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
Alexander Couzens5e33f442017-01-31 15:34:26 +0100911 ctx->gmm_state = GMM_REGISTERED_NORMAL;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100912#endif
913
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100914 return gsm48_tx_gmm_att_ack(ctx);
Daniel Willmann65edec82016-05-21 00:15:29 +0200915#ifdef BUILD_IU
916 case GSM48_MT_GMM_SERVICE_REQ:
Daniel Willmann65edec82016-05-21 00:15:29 +0200917 ctx->pending_req = 0;
Daniel Willmanne9861832016-05-11 12:42:54 +0200918 mmctx_set_pmm_state(ctx, PMM_CONNECTED);
Daniel Willmann65edec82016-05-21 00:15:29 +0200919 rc = gsm48_tx_gmm_service_ack(ctx);
920
Daniel Willmanne0181a22016-05-21 00:35:41 +0200921 if (ctx->iu.service.type != GPRS_SERVICE_T_SIGNALLING)
Daniel Willmann65edec82016-05-21 00:15:29 +0200922 activate_pdp_rabs(ctx);
Daniel Willmann65edec82016-05-21 00:15:29 +0200923
924 return rc;
925#endif
926 case GSM48_MT_GMM_RA_UPD_REQ:
927 ctx->pending_req = 0;
928 /* Send RA UPDATE ACCEPT */
929 return gsm48_tx_gmm_ra_upd_ack(ctx);
930
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100931 default:
932 LOGMMCTXP(LOGL_ERROR, ctx,
933 "only Attach Request is supported yet, "
934 "got request type %u\n", ctx->pending_req);
935 break;
936 }
937
Harald Welte75bb8202010-03-14 15:45:01 +0800938 return 0;
939}
940
Jacob Erlbeckac336982014-12-02 09:47:26 +0100941void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *ctx)
942{
943 ctx->is_authenticated = 0;
944
945 gsm48_gmm_authorize(ctx);
946}
947
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200948void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
949{
Alexander Couzens5e33f442017-01-31 15:34:26 +0100950 switch (ctx->gmm_state) {
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200951 case GMM_COMMON_PROC_INIT:
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200952 LOGMMCTXP(LOGL_NOTICE, ctx,
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200953 "Authorized, continuing procedure, IMSI=%s\n",
954 ctx->imsi);
955 /* Continue with the authorization */
956 gsm48_gmm_authorize(ctx);
957 break;
958 default:
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200959 LOGMMCTXP(LOGL_INFO, ctx,
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200960 "Authorized, ignored, IMSI=%s\n",
961 ctx->imsi);
962 }
963}
964
Jacob Erlbeck41010082015-01-05 17:51:17 +0100965void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200966{
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100967 if (gmm_cause == SGSN_ERROR_CAUSE_NONE)
Jacob Erlbeck41010082015-01-05 17:51:17 +0100968 gmm_cause = GMM_CAUSE_GPRS_NOTALLOWED;
969
Alexander Couzens5e33f442017-01-31 15:34:26 +0100970 switch (ctx->gmm_state) {
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200971 case GMM_COMMON_PROC_INIT:
Jacob Erlbeck41010082015-01-05 17:51:17 +0100972 LOGMMCTXP(LOGL_NOTICE, ctx,
973 "Not authorized, rejecting ATTACH REQUEST "
974 "with cause '%s' (%d)\n",
975 get_value_string(gsm48_gmm_cause_names, gmm_cause),
976 gmm_cause);
977 gsm48_tx_gmm_att_rej(ctx, gmm_cause);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200978 mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJECT");
979 break;
980 case GMM_REGISTERED_NORMAL:
981 case GMM_REGISTERED_SUSPENDED:
Jacob Erlbeck41010082015-01-05 17:51:17 +0100982 LOGMMCTXP(LOGL_NOTICE, ctx,
983 "Authorization lost, detaching "
984 "with cause '%s' (%d)\n",
985 get_value_string(gsm48_gmm_cause_names, gmm_cause),
986 gmm_cause);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200987 gsm48_tx_gmm_detach_req(
Jacob Erlbeck41010082015-01-05 17:51:17 +0100988 ctx, GPRS_DET_T_MT_REATT_NOTREQ, gmm_cause);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200989
990 mm_ctx_cleanup_free(ctx, "auth lost");
991 break;
992 default:
Jacob Erlbeck41010082015-01-05 17:51:17 +0100993 LOGMMCTXP(LOGL_INFO, ctx,
994 "Authorization lost, cause is '%s' (%d)\n",
995 get_value_string(gsm48_gmm_cause_names, gmm_cause),
996 gmm_cause);
997 mm_ctx_cleanup_free(ctx, "auth lost");
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200998 }
999}
1000
Jacob Erlbeck41010082015-01-05 17:51:17 +01001001void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *ctx, int gmm_cause)
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001002{
Jacob Erlbeckf96779f2015-01-19 11:10:04 +01001003 if (gmm_cause != SGSN_ERROR_CAUSE_NONE) {
Jacob Erlbeck41010082015-01-05 17:51:17 +01001004 LOGMMCTXP(LOGL_INFO, ctx,
1005 "Cancelled with cause '%s' (%d), deleting context\n",
1006 get_value_string(gsm48_gmm_cause_names, gmm_cause),
1007 gmm_cause);
1008 gsm0408_gprs_access_denied(ctx, gmm_cause);
1009 return;
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001010 }
Jacob Erlbeck41010082015-01-05 17:51:17 +01001011
1012 LOGMMCTXP(LOGL_INFO, ctx, "Cancelled, deleting context silently\n");
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +01001013 mm_ctx_cleanup_free(ctx, "access cancelled");
1014}
1015
Harald Welte75bb8202010-03-14 15:45:01 +08001016/* Parse Chapter 9.4.13 Identity Response */
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001017static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08001018{
Harald Weltecf3c4142010-04-30 16:33:12 +02001019 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welted85d9a92010-05-02 11:26:34 +02001020 uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
Harald Welte75bb8202010-03-14 15:45:01 +08001021 char mi_string[GSM48_MI_SIZE];
Harald Welte75bb8202010-03-14 15:45:01 +08001022
1023 gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte75bb8202010-03-14 15:45:01 +08001024 if (!ctx) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001025 DEBUGP(DMM, "from unknown TLLI 0x%08x?!? This should not happen\n", msgb_tlli(msg));
Harald Welte75bb8202010-03-14 15:45:01 +08001026 return -EINVAL;
1027 }
1028
Harald Welte7e3e9332015-08-16 18:07:48 +02001029 LOGMMCTXP(LOGL_DEBUG, ctx, "-> GMM IDENTITY RESPONSE: MI(%s)=%s\n",
1030 gsm48_mi_type_name(mi_type), mi_string);
Daniel Willmann09827d52014-09-23 18:48:44 +02001031
Jacob Erlbeck5233c0c2014-10-22 12:20:26 +02001032 if (ctx->t3370_id_type == GSM_MI_TYPE_NONE) {
1033 LOGMMCTXP(LOGL_NOTICE, ctx,
Harald Welte7e3e9332015-08-16 18:07:48 +02001034 "Got unexpected IDENTITY RESPONSE: MI(%s)=%s, "
Jacob Erlbeck5233c0c2014-10-22 12:20:26 +02001035 "ignoring message\n",
Harald Welte7e3e9332015-08-16 18:07:48 +02001036 gsm48_mi_type_name(mi_type), mi_string);
Jacob Erlbeck5233c0c2014-10-22 12:20:26 +02001037 return -EINVAL;
1038 }
1039
Harald Welte7e01d8e2010-05-31 20:23:38 +02001040 if (mi_type == ctx->t3370_id_type)
1041 mmctx_timer_stop(ctx, 3370);
1042
Harald Welte75bb8202010-03-14 15:45:01 +08001043 switch (mi_type) {
1044 case GSM_MI_TYPE_IMSI:
1045 /* we already have a mm context with current TLLI, but no
1046 * P-TMSI / IMSI yet. What we now need to do is to fill
1047 * this initial context with data from the HLR */
Harald Weltec6e196f2010-12-24 23:07:18 +01001048 if (strlen(ctx->imsi) == 0) {
1049 /* Check if we already have a MM context for this IMSI */
1050 struct sgsn_mm_ctx *ictx;
1051 ictx = sgsn_mm_ctx_by_imsi(mi_string);
1052 if (ictx) {
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +02001053 /* Handle it like in gsm48_rx_gmm_det_req,
1054 * except that no messages are sent to the BSS */
1055
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001056 LOGMMCTXP(LOGL_NOTICE, ctx, "Deleting old MM Context for same IMSI "
1057 "p_tmsi_old=0x%08x\n",
1058 ictx->p_tmsi);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +02001059
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +02001060 mm_ctx_cleanup_free(ictx, "GPRS IMSI re-use");
Harald Weltec6e196f2010-12-24 23:07:18 +01001061 }
1062 }
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001063 osmo_strlcpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
Harald Welte75bb8202010-03-14 15:45:01 +08001064 break;
1065 case GSM_MI_TYPE_IMEI:
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001066 osmo_strlcpy(ctx->imei, mi_string, sizeof(ctx->imei));
Harald Welte75bb8202010-03-14 15:45:01 +08001067 break;
1068 case GSM_MI_TYPE_IMEISV:
1069 break;
1070 }
1071
Harald Welte75bb8202010-03-14 15:45:01 +08001072 /* Check if we can let the mobile station enter */
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001073 return gsm48_gmm_authorize(ctx);
Harald Welte75bb8202010-03-14 15:45:01 +08001074}
1075
1076/* Section 9.4.1 Attach request */
Harald Welte75871c72010-06-01 11:53:01 +02001077static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
1078 struct gprs_llc_llme *llme)
Harald Welte75bb8202010-03-14 15:45:01 +08001079{
Harald Weltecf3c4142010-04-30 16:33:12 +02001080 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02001081 uint8_t *cur = gh->data, *msnc, *mi, *ms_ra_acc_cap;
Harald Weltecca80c92010-05-31 22:12:30 +02001082 uint8_t msnc_len, att_type, mi_len, mi_type, ms_ra_acc_cap_len;
Harald Welted85d9a92010-05-02 11:26:34 +02001083 uint16_t drx_par;
1084 uint32_t tmsi;
Harald Welte75bb8202010-03-14 15:45:01 +08001085 char mi_string[GSM48_MI_SIZE];
1086 struct gprs_ra_id ra_id;
Daniel Willmann63dddc72016-05-21 17:36:18 +02001087 uint16_t cid = 0;
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001088 enum gsm48_gmm_cause reject_cause;
1089 int rc;
Harald Welte75bb8202010-03-14 15:45:01 +08001090
Harald Weltebdeaf5f2015-08-16 17:11:32 +02001091 LOGMMCTXP(LOGL_INFO, ctx, "-> GMM ATTACH REQUEST ");
Alexander Couzens32fdba02016-07-05 09:52:52 +02001092 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_REQUEST]);
Harald Welte75bb8202010-03-14 15:45:01 +08001093
1094 /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
1095 * with a foreign TLLI (P-TMSI that was allocated to the MS before),
1096 * or with random TLLI. */
1097
Daniel Willmann63dddc72016-05-21 17:36:18 +02001098 /* In Iu mode, msg->dst contains the ue_conn_ctx pointer, in Gb mode
1099 * dst is empty. */
1100 /* FIXME: have a more explicit indicator for Iu messages */
1101 if (!msg->dst) {
1102 /* Gb mode */
1103 cid = bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
Neels Hofmeyr09156122016-11-26 13:37:55 +01001104 } else
1105 ra_id = ((struct ue_conn_ctx*)msg->dst)->ra_id;
Harald Welte75bb8202010-03-14 15:45:01 +08001106
1107 /* MS network capability 10.5.5.12 */
1108 msnc_len = *cur++;
1109 msnc = cur;
Alexander Chemeris6824c502013-07-03 10:12:23 +04001110 if (msnc_len > sizeof(ctx->ms_network_capa.buf))
Harald Welte75bb8202010-03-14 15:45:01 +08001111 goto err_inval;
1112 cur += msnc_len;
1113
Daniel Willmann4b4ecb92016-01-25 16:49:53 +01001114 /* TODO: In iu mode - handle follow-on request */
1115
Harald Welte75bb8202010-03-14 15:45:01 +08001116 /* aTTACH Type 10.5.5.2 */
Daniel Willmann4b4ecb92016-01-25 16:49:53 +01001117 att_type = *cur++ & 0x07;
Harald Welte75bb8202010-03-14 15:45:01 +08001118
1119 /* DRX parameter 10.5.5.6 */
Harald Weltecca80c92010-05-31 22:12:30 +02001120 drx_par = *cur++ << 8;
1121 drx_par |= *cur++;
Harald Welte75bb8202010-03-14 15:45:01 +08001122
1123 /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
1124 mi_len = *cur++;
1125 mi = cur;
1126 if (mi_len > 8)
1127 goto err_inval;
1128 mi_type = *mi & GSM_MI_TYPE_MASK;
1129 cur += mi_len;
1130
1131 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1132
Harald Welte8f77f192010-05-17 00:44:57 +02001133 DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
1134 get_value_string(gprs_att_t_strs, att_type));
Harald Welte75bb8202010-03-14 15:45:01 +08001135
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02001136 /* Old routing area identification 10.5.5.15. Skip it */
Harald Welte75bb8202010-03-14 15:45:01 +08001137 cur += 6;
1138
1139 /* MS Radio Access Capability 10.5.5.12a */
Harald Weltecca80c92010-05-31 22:12:30 +02001140 ms_ra_acc_cap_len = *cur++;
1141 ms_ra_acc_cap = cur;
Alexander Chemeris6824c502013-07-03 10:12:23 +04001142 if (ms_ra_acc_cap_len > sizeof(ctx->ms_radio_access_capa.buf))
Harald Welteabe06132010-07-03 21:20:06 +02001143 goto err_inval;
Harald Welte45ca5522011-07-27 23:35:38 +02001144 cur += ms_ra_acc_cap_len;
Harald Welte75bb8202010-03-14 15:45:01 +08001145
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001146 LOGPC(DMM, LOGL_INFO, "\n");
1147
Harald Welte75bb8202010-03-14 15:45:01 +08001148 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
1149
1150 switch (mi_type) {
1151 case GSM_MI_TYPE_IMSI:
1152 /* Try to find MM context based on IMSI */
Harald Welte75871c72010-06-01 11:53:01 +02001153 if (!ctx)
1154 ctx = sgsn_mm_ctx_by_imsi(mi_string);
Harald Welte75bb8202010-03-14 15:45:01 +08001155 if (!ctx) {
1156#if 0
1157 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
1158#else
Daniel Willmann63dddc72016-05-21 17:36:18 +02001159 if (msg->dst)
1160 ctx = sgsn_mm_ctx_alloc_iu(msg->dst);
1161 else
Alexander Couzens1c7869e2017-02-04 06:01:00 +01001162 ctx = sgsn_mm_ctx_alloc_gb(0, &ra_id);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001163 if (!ctx) {
1164 reject_cause = GMM_CAUSE_NET_FAIL;
1165 goto rejected;
1166 }
Neels Hofmeyr5644c2b2017-01-13 03:12:08 +01001167 osmo_strlcpy(ctx->imsi, mi_string, sizeof(ctx->imsi));
Harald Welte75bb8202010-03-14 15:45:01 +08001168#endif
1169 }
Harald Welte15487002015-12-25 22:23:27 +01001170 if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
1171 ctx->gb.tlli = msgb_tlli(msg);
1172 ctx->gb.llme = llme;
1173 }
Harald Welte5c23bfc2010-05-18 12:05:42 +02001174 msgid2mmctx(ctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001175 break;
1176 case GSM_MI_TYPE_TMSI:
Harald Welteebe8a6d2010-05-18 19:58:38 +02001177 memcpy(&tmsi, mi+1, 4);
1178 tmsi = ntohl(tmsi);
Harald Welte75bb8202010-03-14 15:45:01 +08001179 /* Try to find MM context based on P-TMSI */
Harald Welte75871c72010-06-01 11:53:01 +02001180 if (!ctx)
1181 ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
Harald Welte75bb8202010-03-14 15:45:01 +08001182 if (!ctx) {
Harald Weltec6e196f2010-12-24 23:07:18 +01001183 /* Allocate a context as most of our code expects one.
1184 * Context will not have an IMSI ultil ID RESP is received */
Daniel Willmann63dddc72016-05-21 17:36:18 +02001185 if (msg->dst)
1186 ctx = sgsn_mm_ctx_alloc_iu(msg->dst);
1187 else
Alexander Couzens1c7869e2017-02-04 06:01:00 +01001188 ctx = sgsn_mm_ctx_alloc_gb(msgb_tlli(msg), &ra_id);
Harald Welte75871c72010-06-01 11:53:01 +02001189 ctx->p_tmsi = tmsi;
Harald Welte75bb8202010-03-14 15:45:01 +08001190 }
Harald Welte15487002015-12-25 22:23:27 +01001191 if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
1192 ctx->gb.tlli = msgb_tlli(msg);
1193 ctx->gb.llme = llme;
1194 }
Harald Welte75871c72010-06-01 11:53:01 +02001195 msgid2mmctx(ctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001196 break;
1197 default:
Harald Weltebdeaf5f2015-08-16 17:11:32 +02001198 LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with "
Harald Welte7e3e9332015-08-16 18:07:48 +02001199 "MI type %s\n", gsm48_mi_type_name(mi_type));
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001200 reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
1201 goto rejected;
Harald Welte75bb8202010-03-14 15:45:01 +08001202 }
Harald Weltede34afa2010-05-02 12:56:57 +02001203 /* Update MM Context with currient RA and Cell ID */
1204 ctx->ra = ra_id;
Harald Welte15487002015-12-25 22:23:27 +01001205 if (ctx->ran_type == MM_CTX_T_GERAN_Gb)
1206 ctx->gb.cell_id = cid;
Daniel Willmannc3eb6a32016-05-21 00:31:12 +02001207 else if (ctx->ran_type == MM_CTX_T_UTRAN_Iu) {
1208 /* DEVELOPMENT HACK: Our current HLR does not support 3G
1209 * authentication tokens. A new HLR/VLR implementation is being
1210 * developed. Until it is ready and actual milenage
1211 * authentication is properly supported, we are hardcoding a
1212 * fixed Ki and use 2G auth. */
1213 unsigned char tmp_rand[16];
1214 /* Ki 000102030405060708090a0b0c0d0e0f */
1215 struct osmo_sub_auth_data auth = {
1216 .type = OSMO_AUTH_TYPE_GSM,
1217 .algo = OSMO_AUTH_ALG_COMP128v1,
1218 .u.gsm.ki = {
1219 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
1220 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
1221 0x0e, 0x0f
1222 },
1223 };
1224 /* XXX: Hack to make 3G auth work with special SIM card */
1225 ctx->auth_state = SGSN_AUTH_AUTHENTICATE;
1226
1227 RAND_bytes(tmp_rand, 16);
1228
1229 memset(&ctx->auth_triplet.vec, 0, sizeof(ctx->auth_triplet.vec));
1230 osmo_auth_gen_vec(&ctx->auth_triplet.vec, &auth, tmp_rand);
1231
1232 ctx->auth_triplet.key_seq = 0;
1233 }
1234
Harald Weltecca80c92010-05-31 22:12:30 +02001235 /* Update MM Context with other data */
1236 ctx->drx_parms = drx_par;
Alexander Chemeris6824c502013-07-03 10:12:23 +04001237 ctx->ms_radio_access_capa.len = ms_ra_acc_cap_len;
Harald Welte45ca5522011-07-27 23:35:38 +02001238 memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap,
1239 ctx->ms_radio_access_capa.len);
Harald Weltecca80c92010-05-31 22:12:30 +02001240 ctx->ms_network_capa.len = msnc_len;
1241 memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
Max6d999582016-07-06 15:57:01 +02001242 if (!gprs_ms_net_cap_gea_supported(ctx->ms_network_capa.buf, msnc_len,
1243 ctx->ciph_algo)) {
1244 reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
1245 LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with MI "
1246 "type %s because MS do not support required %s "
1247 "encryption\n", gsm48_mi_type_name(mi_type),
1248 get_value_string(gprs_cipher_names,ctx->ciph_algo));
1249 goto rejected;
1250 }
Harald Welte7e01d8e2010-05-31 20:23:38 +02001251#ifdef PTMSI_ALLOC
Harald Welte75871c72010-06-01 11:53:01 +02001252 /* Allocate a new P-TMSI (+ P-TMSI signature) and update TLLI */
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001253 /* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
Alexander Couzens5e33f442017-01-31 15:34:26 +01001254 if (ctx->gmm_state != GMM_COMMON_PROC_INIT) {
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001255 ctx->p_tmsi_old = ctx->p_tmsi;
1256 ctx->p_tmsi = sgsn_alloc_ptmsi();
1257 }
Alexander Couzens5e33f442017-01-31 15:34:26 +01001258 ctx->gmm_state = GMM_COMMON_PROC_INIT;
Harald Welteebe8a6d2010-05-18 19:58:38 +02001259#endif
Harald Welte75871c72010-06-01 11:53:01 +02001260
Harald Welte15487002015-12-25 22:23:27 +01001261 if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
1262 /* Even if there is no P-TMSI allocated, the MS will
1263 * switch from foreign TLLI to local TLLI */
1264 ctx->gb.tlli_new = gprs_tmsi2tlli(ctx->p_tmsi, TLLI_LOCAL);
1265
1266 /* Inform LLC layer about new TLLI but keep old active */
Maxeb64e3f2016-07-06 11:33:04 +02001267 if (ctx->is_authenticated)
1268 gprs_llme_copy_key(ctx, ctx->gb.llme);
1269
1270 gprs_llgmm_assign(ctx->gb.llme, ctx->gb.tlli, ctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001271 }
Harald Welte75bb8202010-03-14 15:45:01 +08001272
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001273 ctx->pending_req = GSM48_MT_GMM_ATTACH_REQ;
1274 return gsm48_gmm_authorize(ctx);
Harald Welte75bb8202010-03-14 15:45:01 +08001275
1276err_inval:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001277 LOGPC(DMM, LOGL_INFO, "\n");
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001278 reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
1279
1280rejected:
1281 /* Send ATTACH REJECT */
1282 LOGMMCTXP(LOGL_NOTICE, ctx,
1283 "Rejecting Attach Request with cause '%s' (%d)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01001284 get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001285 rc = gsm48_tx_gmm_att_rej_oldmsg(msg, reject_cause);
1286 if (ctx)
1287 mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJ");
1288 else
Maxa86f5c02016-06-28 17:39:20 +02001289 gprs_llgmm_unassign(llme);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001290
1291 return rc;
1292
Harald Welte75bb8202010-03-14 15:45:01 +08001293}
1294
Harald Welte8f77f192010-05-17 00:44:57 +02001295/* Section 4.7.4.1 / 9.4.5.2 MO Detach request */
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001296static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
Harald Welte8f77f192010-05-17 00:44:57 +02001297{
1298 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte8f77f192010-05-17 00:44:57 +02001299 uint8_t detach_type, power_off;
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001300 int rc = 0;
Harald Welte8f77f192010-05-17 00:44:57 +02001301
1302 detach_type = gh->data[0] & 0x7;
1303 power_off = gh->data[0] & 0x8;
1304
1305 /* FIXME: In 24.008 there is an optional P-TMSI and P-TMSI signature IE */
Alexander Couzens32fdba02016-07-05 09:52:52 +02001306 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_DETACH_REQUEST]);
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001307 LOGMMCTXP(LOGL_INFO, ctx, "-> GMM DETACH REQUEST TLLI=0x%08x type=%s %s\n",
Harald Welte8f77f192010-05-17 00:44:57 +02001308 msgb_tlli(msg), get_value_string(gprs_det_t_mo_strs, detach_type),
1309 power_off ? "Power-off" : "");
1310
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001311 /* Only send the Detach Accept (MO) if power off isn't indicated,
Jacob Erlbeck97ee3762014-10-21 09:52:05 +02001312 * see 04.08, 4.7.4.1.2/3 for details */
1313 if (!power_off) {
1314 /* force_stby = 0 */
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001315 if (ctx)
1316 rc = gsm48_tx_gmm_det_ack(ctx, 0);
1317 else
1318 rc = gsm48_tx_gmm_det_ack_oldmsg(msg, 0);
Jacob Erlbeck97ee3762014-10-21 09:52:05 +02001319 }
Harald Welte309b5932010-06-28 22:18:53 +02001320
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001321 if (ctx) {
1322 struct sgsn_signal_data sig_data;
1323 memset(&sig_data, 0, sizeof(sig_data));
1324 sig_data.mm = ctx;
1325 osmo_signal_dispatch(SS_SGSN, S_SGSN_DETACH, &sig_data);
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001326 mm_ctx_cleanup_free(ctx, "GPRS DETACH REQUEST");
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001327 }
Jacob Erlbeck12396bd2014-09-30 13:51:45 +02001328
Harald Welte309b5932010-06-28 22:18:53 +02001329 return rc;
Harald Welte8f77f192010-05-17 00:44:57 +02001330}
1331
Harald Welte75bb8202010-03-14 15:45:01 +08001332/* Chapter 9.4.15: Routing area update accept */
Harald Welte64df8ed2010-05-18 17:04:55 +02001333static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
Harald Welte75bb8202010-03-14 15:45:01 +08001334{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001335 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 UPD ACK");
Harald Welte75bb8202010-03-14 15:45:01 +08001336 struct gsm48_hdr *gh;
1337 struct gsm48_ra_upd_ack *rua;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001338 uint8_t *mid;
Harald Welte75bb8202010-03-14 15:45:01 +08001339
Alexander Couzens32fdba02016-07-05 09:52:52 +02001340 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_ACKED]);
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001341 LOGMMCTXP(LOGL_INFO, mm, "<- ROUTING AREA UPDATE ACCEPT\n");
Harald Welte75bb8202010-03-14 15:45:01 +08001342
Harald Welte64df8ed2010-05-18 17:04:55 +02001343 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +08001344
1345 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1346 gh->proto_discr = GSM48_PDISC_MM_GPRS;
1347 gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
1348
1349 rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
1350 rua->force_stby = 0; /* not indicated */
1351 rua->upd_result = 0; /* RA updated */
Harald Welte9b57a3d2015-08-15 19:08:21 +02001352 rua->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
Harald Welte2351f1f2010-05-02 11:54:55 +02001353
Harald Welte64df8ed2010-05-18 17:04:55 +02001354 gsm48_construct_ra(rua->ra_id.digits, &mm->ra);
Harald Welte75bb8202010-03-14 15:45:01 +08001355
Harald Welte7e01d8e2010-05-31 20:23:38 +02001356#if 0
1357 /* Optional: P-TMSI signature */
1358 msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
1359 ptsig = msgb_put(msg, 3);
1360 ptsig[0] = mm->p_tmsi_sig >> 16;
1361 ptsig[1] = mm->p_tmsi_sig >> 8;
1362 ptsig[2] = mm->p_tmsi_sig & 0xff;
1363#endif
1364
1365#ifdef PTMSI_ALLOC
1366 /* Optional: Allocated P-TMSI */
1367 mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
1368 gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
1369 mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
1370#endif
1371
Jacob Erlbeck1063ae02015-01-23 11:44:39 +01001372 /* Optional: Negotiated READY timer value */
1373 msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
Harald Welte9b57a3d2015-08-15 19:08:21 +02001374 gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
Jacob Erlbeck1063ae02015-01-23 11:44:39 +01001375
Harald Welte7e01d8e2010-05-31 20:23:38 +02001376 /* Option: MS ID, ... */
Max4bc28212016-07-06 11:59:18 +02001377 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte75bb8202010-03-14 15:45:01 +08001378}
1379
1380/* Chapter 9.4.17: Routing area update reject */
Harald Welted85d9a92010-05-02 11:26:34 +02001381static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
Harald Welte75bb8202010-03-14 15:45:01 +08001382{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001383 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 RA UPD REJ");
Harald Welte75bb8202010-03-14 15:45:01 +08001384 struct gsm48_hdr *gh;
1385
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001386 LOGP(DMM, LOGL_NOTICE, "<- ROUTING AREA UPDATE REJECT\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02001387 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_REJECT]);
Harald Welte75bb8202010-03-14 15:45:01 +08001388
Harald Welte2351f1f2010-05-02 11:54:55 +02001389 gmm_copy_id(msg, old_msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001390
1391 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
1392 gh->proto_discr = GSM48_PDISC_MM_GPRS;
1393 gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
1394 gh->data[0] = cause;
1395 gh->data[1] = 0; /* ? */
1396
1397 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
Max4bc28212016-07-06 11:59:18 +02001398 return gsm48_gmm_sendmsg(msg, 0, NULL, false);
Harald Welte75bb8202010-03-14 15:45:01 +08001399}
1400
Harald Welted9610722010-06-09 10:28:29 +02001401static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001402 const uint8_t *pdp_status)
Harald Welted9610722010-06-09 10:28:29 +02001403{
1404 struct sgsn_pdp_ctx *pdp, *pdp2;
1405 /* 24.008 4.7.5.1.3: If the PDP context status information element is
1406 * included in ROUTING AREA UPDATE REQUEST message, then the network
1407 * shall deactivate all those PDP contexts locally (without peer to
1408 * peer signalling between the MS and the network), which are not in SM
1409 * state PDP-INACTIVE on network side but are indicated by the MS as
1410 * being in state PDP-INACTIVE. */
1411
1412 llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
Harald Welte9e7093c2011-08-05 21:23:46 +02001413 if (pdp->nsapi < 8) {
1414 if (!(pdp_status[0] & (1 << pdp->nsapi))) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001415 LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for NSAPI=%u "
Harald Welte9e7093c2011-08-05 21:23:46 +02001416 "due to PDP CTX STATUS IE= 0x%02x%02x\n",
1417 pdp->nsapi, pdp_status[1], pdp_status[0]);
1418 sgsn_delete_pdp_ctx(pdp);
1419 }
1420 } else {
1421 if (!(pdp_status[1] & (1 << (pdp->nsapi - 8)))) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001422 LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for NSAPI=%u "
Harald Welte9e7093c2011-08-05 21:23:46 +02001423 "due to PDP CTX STATUS IE= 0x%02x%02x\n",
1424 pdp->nsapi, pdp_status[1], pdp_status[0]);
1425 sgsn_delete_pdp_ctx(pdp);
1426 }
Harald Welted9610722010-06-09 10:28:29 +02001427 }
1428 }
1429}
1430
Harald Welte75bb8202010-03-14 15:45:01 +08001431/* Chapter 9.4.14: Routing area update request */
Harald Welte75871c72010-06-01 11:53:01 +02001432static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
1433 struct gprs_llc_llme *llme)
Harald Welte75bb8202010-03-14 15:45:01 +08001434{
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001435#ifndef PTMSI_ALLOC
1436 struct sgsn_signal_data sig_data;
1437#endif
Harald Weltecf3c4142010-04-30 16:33:12 +02001438 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welted85d9a92010-05-02 11:26:34 +02001439 uint8_t *cur = gh->data;
Harald Welted9610722010-06-09 10:28:29 +02001440 uint8_t ms_ra_acc_cap_len;
Harald Welte75bb8202010-03-14 15:45:01 +08001441 struct gprs_ra_id old_ra_id;
Harald Welted9610722010-06-09 10:28:29 +02001442 struct tlv_parsed tp;
Harald Welted85d9a92010-05-02 11:26:34 +02001443 uint8_t upd_type;
Philipp Maier22f3e402017-01-25 12:19:08 +01001444 enum gsm48_gmm_cause reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001445 int rc;
Harald Welte75bb8202010-03-14 15:45:01 +08001446
Daniel Willmann4b4ecb92016-01-25 16:49:53 +01001447 /* TODO: In iu mode - handle follow-on request */
1448
Harald Welte75bb8202010-03-14 15:45:01 +08001449 /* Update Type 10.5.5.18 */
Daniel Willmann4b4ecb92016-01-25 16:49:53 +01001450 upd_type = *cur++ & 0x07;
Harald Welte75bb8202010-03-14 15:45:01 +08001451
Alexander Couzens32fdba02016-07-05 09:52:52 +02001452 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_REQUEST]);
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001453 LOGP(DMM, LOGL_INFO, "-> GMM RA UPDATE REQUEST type=\"%s\"\n",
Harald Welte8f77f192010-05-17 00:44:57 +02001454 get_value_string(gprs_upd_t_strs, upd_type));
Harald Welte75bb8202010-03-14 15:45:01 +08001455
1456 /* Old routing area identification 10.5.5.15 */
1457 gsm48_parse_ra(&old_ra_id, cur);
1458 cur += 6;
1459
1460 /* MS Radio Access Capability 10.5.5.12a */
Harald Welted9610722010-06-09 10:28:29 +02001461 ms_ra_acc_cap_len = *cur++;
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001462 if (ms_ra_acc_cap_len > 52) {
1463 reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
1464 goto rejected;
1465 }
Harald Welte45ca5522011-07-27 23:35:38 +02001466 cur += ms_ra_acc_cap_len;
Harald Welte75bb8202010-03-14 15:45:01 +08001467
1468 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
1469 * DRX parameter, MS network capability */
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02001470 tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur,
Harald Welted9610722010-06-09 10:28:29 +02001471 (msg->data + msg->len) - cur, 0, 0);
Harald Welte75bb8202010-03-14 15:45:01 +08001472
1473 switch (upd_type) {
1474 case GPRS_UPD_T_RA_LA:
1475 case GPRS_UPD_T_RA_LA_IMSI_ATT:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001476 LOGP(DMM, LOGL_NOTICE, "Update type %i unsupported in Mode III, is your SI13 corrupt?\n", upd_type);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001477 reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
1478 goto rejected;
Harald Welte75bb8202010-03-14 15:45:01 +08001479 case GPRS_UPD_T_RA:
1480 case GPRS_UPD_T_PERIODIC:
1481 break;
1482 }
1483
Jacob Erlbecke437e122016-01-04 18:43:36 +01001484 if (!mmctx) {
1485 /* BSSGP doesn't give us an mmctx */
1486
1487 /* TODO: Check if there is an MM CTX with old_ra_id and
1488 * the P-TMSI (if given, reguired for UMTS) or as last resort
1489 * if the TLLI matches foreign_tlli (P-TMSI). Note that this
1490 * is an optimization to avoid the RA reject (impl detached)
1491 * below, which will cause a new attach cycle. */
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001492 /* Look-up the MM context based on old RA-ID and TLLI */
Daniel Willmann63dddc72016-05-21 17:36:18 +02001493 /* In Iu mode, msg->dst contains the ue_conn_ctx pointer, in Gb
1494 * mode dst is empty. */
1495 /* FIXME: have a more explicit indicator for Iu messages */
1496 if (!msg->dst) {
1497 mmctx = sgsn_mm_ctx_by_tlli_and_ptmsi(msgb_tlli(msg), &old_ra_id);
1498 } else if (TLVP_PRESENT(&tp, GSM48_IE_GMM_ALLOC_PTMSI)) {
1499#ifdef BUILD_IU
1500 /* In Iu mode search only for ptmsi */
1501 char mi_string[GSM48_MI_SIZE];
1502 uint8_t mi_len = TLVP_LEN(&tp, GSM48_IE_GMM_ALLOC_PTMSI);
1503 uint8_t *mi = TLVP_VAL(&tp, GSM48_IE_GMM_ALLOC_PTMSI);
1504 uint8_t mi_type = *mi & GSM_MI_TYPE_MASK;
1505 uint32_t tmsi;
1506
1507 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1508
1509 if (mi_type == GSM_MI_TYPE_TMSI) {
1510 memcpy(&tmsi, mi+1, 4);
1511 tmsi = ntohl(tmsi);
1512 mmctx = sgsn_mm_ctx_by_ptmsi(tmsi);
1513 }
1514#else
1515 goto rejected;
1516#endif
1517 }
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001518 if (mmctx) {
1519 LOGMMCTXP(LOGL_INFO, mmctx,
1520 "Looked up by matching TLLI and P_TMSI. "
1521 "BSSGP TLLI: %08x, P-TMSI: %08x (%08x), "
1522 "TLLI: %08x (%08x), RA: %d-%d-%d-%d\n",
1523 msgb_tlli(msg),
1524 mmctx->p_tmsi, mmctx->p_tmsi_old,
Harald Weltec28dc2f2015-12-25 19:12:21 +01001525 mmctx->gb.tlli, mmctx->gb.tlli_new,
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001526 mmctx->ra.mcc, mmctx->ra.mnc,
1527 mmctx->ra.lac, mmctx->ra.rac);
Jacob Erlbecke437e122016-01-04 18:43:36 +01001528
Alexander Couzens5e33f442017-01-31 15:34:26 +01001529 mmctx->gmm_state = GMM_COMMON_PROC_INIT;
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001530 }
1531 } else if (!gprs_ra_id_equals(&mmctx->ra, &old_ra_id) ||
Alexander Couzens5e33f442017-01-31 15:34:26 +01001532 mmctx->gmm_state == GMM_DEREGISTERED)
Jacob Erlbecke437e122016-01-04 18:43:36 +01001533 {
1534 /* We cannot use the mmctx */
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001535 LOGMMCTXP(LOGL_INFO, mmctx,
1536 "The MM context cannot be used, RA: %d-%d-%d-%d\n",
1537 mmctx->ra.mcc, mmctx->ra.mnc,
1538 mmctx->ra.lac, mmctx->ra.rac);
1539 mmctx = NULL;
1540 }
Jacob Erlbecke437e122016-01-04 18:43:36 +01001541
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001542 if (!mmctx) {
Harald Welte95de4d52015-12-25 22:31:36 +01001543 if (llme) {
1544 /* send a XID reset to re-set all LLC sequence numbers
1545 * in the MS */
1546 LOGMMCTXP(LOGL_NOTICE, mmctx, "LLC XID RESET\n");
1547 gprs_llgmm_reset(llme);
1548 }
Harald Welte75bb8202010-03-14 15:45:01 +08001549 /* The MS has to perform GPRS attach */
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001550 /* Device is still IMSI attached for CS but initiate GPRS ATTACH,
1551 * see GSM 04.08, 4.7.5.1.4 and G.6 */
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001552 reject_cause = GMM_CAUSE_IMPL_DETACHED;
1553 goto rejected;
Harald Welte75bb8202010-03-14 15:45:01 +08001554 }
1555
Harald Welte66d062a2010-12-26 10:39:26 +01001556 /* Store new BVCI/NSEI in MM context (FIXME: delay until we ack?) */
1557 msgid2mmctx(mmctx, msg);
1558 /* Bump the statistics of received signalling msgs for this MM context */
1559 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
1560
Harald Weltede34afa2010-05-02 12:56:57 +02001561 /* Update the MM context with the new RA-ID */
Harald Welte15487002015-12-25 22:23:27 +01001562 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
Daniel Willmann711adc22016-05-20 22:36:23 +02001563 bssgp_parse_cell_id(&mmctx->ra, msgb_bcid(msg));
Harald Welte15487002015-12-25 22:23:27 +01001564 /* Update the MM context with the new (i.e. foreign) TLLI */
1565 mmctx->gb.tlli = msgb_tlli(msg);
1566 }
Harald Welte75bb8202010-03-14 15:45:01 +08001567 /* FIXME: Update the MM context with the MS radio acc capabilities */
1568 /* FIXME: Update the MM context with the MS network capabilities */
1569
Harald Welteeb471c92010-05-18 14:32:29 +02001570 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_RA_UPDATE]);
1571
Harald Welte7e01d8e2010-05-31 20:23:38 +02001572#ifdef PTMSI_ALLOC
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001573 /* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
Alexander Couzens5e33f442017-01-31 15:34:26 +01001574 if (mmctx->gmm_state != GMM_COMMON_PROC_INIT) {
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001575 mmctx->p_tmsi_old = mmctx->p_tmsi;
1576 mmctx->p_tmsi = sgsn_alloc_ptmsi();
1577 }
Harald Welte7e01d8e2010-05-31 20:23:38 +02001578 /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
1579 mmctx->t3350_mode = GMM_T3350_MODE_RAU;
Harald Welte9b57a3d2015-08-15 19:08:21 +02001580 mmctx_timer_start(mmctx, 3350, sgsn->cfg.timers.T3350);
Jacob Erlbeck67318ef2014-10-28 16:23:46 +01001581
Alexander Couzens5e33f442017-01-31 15:34:26 +01001582 mmctx->gmm_state = GMM_COMMON_PROC_INIT;
Jacob Erlbeck67318ef2014-10-28 16:23:46 +01001583#else
1584 /* Make sure we are NORMAL (i.e. not SUSPENDED anymore) */
Alexander Couzens5e33f442017-01-31 15:34:26 +01001585 mmctx->gmm_state = GMM_REGISTERED_NORMAL;
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001586
1587 memset(&sig_data, 0, sizeof(sig_data));
1588 sig_data.mm = mmctx;
1589 osmo_signal_dispatch(SS_SGSN, S_SGSN_UPDATE, &sig_data);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001590#endif
Harald Welte15487002015-12-25 22:23:27 +01001591 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1592 /* Even if there is no P-TMSI allocated, the MS will switch from
1593 * foreign TLLI to local TLLI */
1594 mmctx->gb.tlli_new = gprs_tmsi2tlli(mmctx->p_tmsi, TLLI_LOCAL);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001595
Harald Welte15487002015-12-25 22:23:27 +01001596 /* Inform LLC layer about new TLLI but keep old active */
1597 gprs_llgmm_assign(mmctx->gb.llme, mmctx->gb.tlli,
Maxeb64e3f2016-07-06 11:33:04 +02001598 mmctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001599 }
Harald Welte75871c72010-06-01 11:53:01 +02001600
Harald Welted9610722010-06-09 10:28:29 +02001601 /* Look at PDP Context Status IE and see if MS's view of
1602 * activated/deactivated NSAPIs agrees with our view */
1603 if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001604 const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
Harald Welted9610722010-06-09 10:28:29 +02001605 process_ms_ctx_status(mmctx, pdp_status);
1606 }
1607
Daniel Willmanne0181a22016-05-21 00:35:41 +02001608 /* Send RA UPDATE ACCEPT. In Iu, the RA upd request can be called from
1609 * a new Iu connection, so we might need to re-authenticate the
1610 * connection as well as turn on integrity protection. */
1611 mmctx->pending_req = GSM48_MT_GMM_RA_UPD_REQ;
1612 return gsm48_gmm_authorize(mmctx);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001613
1614rejected:
1615 /* Send RA UPDATE REJECT */
1616 LOGMMCTXP(LOGL_NOTICE, mmctx,
1617 "Rejecting RA Update Request with cause '%s' (%d)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01001618 get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001619 rc = gsm48_tx_gmm_ra_upd_rej(msg, reject_cause);
1620 if (mmctx)
1621 mm_ctx_cleanup_free(mmctx, "GPRS RA UPDATE REJ");
Harald Welte15487002015-12-25 22:23:27 +01001622 else {
Maxa86f5c02016-06-28 17:39:20 +02001623 if (llme)
1624 gprs_llgmm_unassign(llme);
Harald Welte15487002015-12-25 22:23:27 +01001625 }
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001626
1627 return rc;
Harald Welte75bb8202010-03-14 15:45:01 +08001628}
1629
Daniel Willmann65edec82016-05-21 00:15:29 +02001630/* 3GPP TS 24.008 Section 9.4.20 Service request.
1631 * In Iu, a UE in PMM-IDLE mode can use GSM48_MT_GMM_SERVICE_REQ to switch back
1632 * to PMM-CONNECTED mode. */
1633static int gsm48_rx_gmm_service_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
1634{
1635 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
1636 uint8_t *cur = gh->data, *mi;
1637 uint8_t ciph_seq_nr, service_type, mi_len, mi_type;
1638 uint32_t tmsi;
1639 struct tlv_parsed tp;
1640 char mi_string[GSM48_MI_SIZE];
1641 enum gsm48_gmm_cause reject_cause;
1642 int rc;
1643
1644 LOGMMCTXP(LOGL_INFO, ctx, "-> GMM SERVICE REQUEST ");
1645
1646 /* This message is only valid in Iu mode */
1647 if (!msg->dst) {
1648 LOGPC(DMM, LOGL_INFO, "Invalid if not in Iu mode\n");
1649 return -1;
1650 }
1651
1652 /* Skip Ciphering key sequence number 10.5.1.2 */
1653 ciph_seq_nr = *cur & 0x07;
1654
1655 /* Service type 10.5.5.20 */
1656 service_type = (*cur++ >> 4) & 0x07;
1657
1658 /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
1659 mi_len = *cur++;
1660 mi = cur;
1661 if (mi_len > 8)
1662 goto err_inval;
1663 mi_type = *mi & GSM_MI_TYPE_MASK;
1664 cur += mi_len;
1665
1666 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
1667
1668 DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
1669 get_value_string(gprs_service_t_strs, service_type));
1670
1671 LOGPC(DMM, LOGL_INFO, "\n");
1672
1673 /* Optional: PDP context status, MBMS context status, Uplink data status, Device properties */
1674 tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur, (msg->data + msg->len) - cur, 0, 0);
1675
1676 switch (mi_type) {
1677 case GSM_MI_TYPE_IMSI:
1678 /* Try to find MM context based on IMSI */
1679 if (!ctx)
1680 ctx = sgsn_mm_ctx_by_imsi(mi_string);
1681 if (!ctx) {
1682 /* FIXME: We need to have a context for service request? */
1683 reject_cause = GMM_CAUSE_NET_FAIL;
1684 goto rejected;
1685 }
1686 msgid2mmctx(ctx, msg);
1687 break;
1688 case GSM_MI_TYPE_TMSI:
1689 memcpy(&tmsi, mi+1, 4);
1690 tmsi = ntohl(tmsi);
1691 /* Try to find MM context based on P-TMSI */
1692 if (!ctx)
1693 ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
1694 if (!ctx) {
1695 /* FIXME: We need to have a context for service request? */
1696 reject_cause = GMM_CAUSE_NET_FAIL;
1697 goto rejected;
1698 }
1699 msgid2mmctx(ctx, msg);
1700 break;
1701 default:
1702 LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting SERVICE REQUEST with "
1703 "MI type %s\n", gsm48_mi_type_name(mi_type));
1704 reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
1705 goto rejected;
1706 }
1707
Alexander Couzens5e33f442017-01-31 15:34:26 +01001708 ctx->gmm_state = GMM_COMMON_PROC_INIT;
Daniel Willmann65edec82016-05-21 00:15:29 +02001709
1710 ctx->iu.service.type = service_type;
1711
1712 /* TODO: Handle those only in case of accept? */
1713 /* Look at PDP Context Status IE and see if MS's view of
1714 * activated/deactivated NSAPIs agrees with our view */
1715 if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
1716 const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
1717 process_ms_ctx_status(ctx, pdp_status);
1718 }
1719
1720
1721 ctx->pending_req = GSM48_MT_GMM_SERVICE_REQ;
1722 return gsm48_gmm_authorize(ctx);
1723
1724err_inval:
1725 LOGPC(DMM, LOGL_INFO, "\n");
1726 reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
1727
1728rejected:
1729 /* Send SERVICE REJECT */
1730 LOGMMCTXP(LOGL_NOTICE, ctx,
1731 "Rejecting Service Request with cause '%s' (%d)\n",
1732 get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
1733 rc = gsm48_tx_gmm_service_rej_oldmsg(msg, reject_cause);
1734
1735 return rc;
1736
1737}
1738
1739
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001740static int gsm48_rx_gmm_status(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08001741{
1742 struct gsm48_hdr *gh = msgb_l3(msg);
1743
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001744 LOGMMCTXP(LOGL_INFO, mmctx, "-> GPRS MM STATUS (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01001745 get_value_string(gsm48_gmm_cause_names, gh->data[0]));
Harald Welte75bb8202010-03-14 15:45:01 +08001746
1747 return 0;
1748}
1749
1750/* GPRS Mobility Management */
Harald Welte75871c72010-06-01 11:53:01 +02001751static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
Max4bc28212016-07-06 11:59:18 +02001752 struct gprs_llc_llme *llme, bool drop_cipherable)
Harald Welte75bb8202010-03-14 15:45:01 +08001753{
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001754 struct sgsn_signal_data sig_data;
Harald Weltecf3c4142010-04-30 16:33:12 +02001755 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001756 int rc;
1757
Harald Welte75871c72010-06-01 11:53:01 +02001758 /* MMCTX can be NULL when called */
Max4bc28212016-07-06 11:59:18 +02001759 if (drop_cipherable && gsm48_hdr_gmm_cipherable(gh)) {
1760 LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping cleartext GMM %s which "
1761 "is expected to be encrypted for TLLI 0x%08x\n",
1762 get_value_string(gprs_msgt_gmm_names, gh->msg_type),
1763 llme->tlli);
1764 return -EBADMSG;
1765 }
Harald Welte75871c72010-06-01 11:53:01 +02001766
Harald Welte95de4d52015-12-25 22:31:36 +01001767 if (llme && !mmctx &&
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001768 gh->msg_type != GSM48_MT_GMM_ATTACH_REQ &&
Harald Welte7e01d8e2010-05-31 20:23:38 +02001769 gh->msg_type != GSM48_MT_GMM_RA_UPD_REQ) {
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001770 LOGP(DMM, LOGL_NOTICE, "Cannot handle GMM for unknown MM CTX\n");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001771 /* 4.7.10 */
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001772 if (gh->msg_type == GSM48_MT_GMM_STATUS) {
1773 /* TLLI unassignment */
Maxa86f5c02016-06-28 17:39:20 +02001774 gprs_llgmm_unassign(llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001775 return 0;
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001776 }
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001777
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001778 /* Don't reply or establish a LLME on DETACH_ACK */
Maxa86f5c02016-06-28 17:39:20 +02001779 if (gh->msg_type == GSM48_MT_GMM_DETACH_ACK)
1780 return gprs_llgmm_unassign(llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001781
Jacob Erlbeck218ed402014-11-11 08:55:13 +01001782 gprs_llgmm_reset(llme);
1783
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001784 /* Don't force it into re-attachment */
1785 if (gh->msg_type == GSM48_MT_GMM_DETACH_REQ) {
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001786 /* Handle Detach Request */
1787 rc = gsm48_rx_gmm_det_req(NULL, msg);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001788
1789 /* TLLI unassignment */
Maxa86f5c02016-06-28 17:39:20 +02001790 gprs_llgmm_unassign(llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001791 return rc;
1792 }
1793
1794 /* Force the MS to re-attach */
Max6d999582016-07-06 15:57:01 +02001795 rc = gsm0408_gprs_force_reattach_oldmsg(msg, llme);
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01001796
1797 /* TLLI unassignment */
Maxa86f5c02016-06-28 17:39:20 +02001798 gprs_llgmm_unassign(llme);
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01001799 return rc;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001800 }
1801
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001802 /*
1803 * For a few messages, mmctx may be NULL. For most, we want to ensure a
1804 * non-NULL mmctx. At the same time, we want to keep the message
1805 * validity check intact, so that all message types appear in the
1806 * switch statement and the default case thus means "unknown message".
1807 * If we split the switch in two parts to check non-NULL halfway, the
1808 * unknown-message check breaks, or we'd need to duplicate the switch
1809 * cases in both parts. Just keep one large switch and add some gotos.
1810 */
Harald Welte75bb8202010-03-14 15:45:01 +08001811 switch (gh->msg_type) {
1812 case GSM48_MT_GMM_RA_UPD_REQ:
Harald Welte75871c72010-06-01 11:53:01 +02001813 rc = gsm48_rx_gmm_ra_upd_req(mmctx, msg, llme);
Harald Welte75bb8202010-03-14 15:45:01 +08001814 break;
1815 case GSM48_MT_GMM_ATTACH_REQ:
Harald Welte75871c72010-06-01 11:53:01 +02001816 rc = gsm48_rx_gmm_att_req(mmctx, msg, llme);
Harald Welte75bb8202010-03-14 15:45:01 +08001817 break;
Daniel Willmann65edec82016-05-21 00:15:29 +02001818 case GSM48_MT_GMM_SERVICE_REQ:
1819 rc = gsm48_rx_gmm_service_req(mmctx, msg);
1820 break;
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001821 /* For all the following types mmctx can not be NULL */
Harald Welte75bb8202010-03-14 15:45:01 +08001822 case GSM48_MT_GMM_ID_RESP:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001823 if (!mmctx)
1824 goto null_mmctx;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001825 rc = gsm48_rx_gmm_id_resp(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001826 break;
1827 case GSM48_MT_GMM_STATUS:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001828 if (!mmctx)
1829 goto null_mmctx;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001830 rc = gsm48_rx_gmm_status(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001831 break;
Harald Welte8f77f192010-05-17 00:44:57 +02001832 case GSM48_MT_GMM_DETACH_REQ:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001833 if (!mmctx)
1834 goto null_mmctx;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001835 rc = gsm48_rx_gmm_det_req(mmctx, msg);
Harald Welte8f77f192010-05-17 00:44:57 +02001836 break;
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001837 case GSM48_MT_GMM_DETACH_ACK:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001838 if (!mmctx)
1839 goto null_mmctx;
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001840 LOGMMCTXP(LOGL_INFO, mmctx, "-> DETACH ACK\n");
1841 mm_ctx_cleanup_free(mmctx, "GPRS DETACH ACK");
1842 rc = 0;
1843 break;
Harald Welte75bb8202010-03-14 15:45:01 +08001844 case GSM48_MT_GMM_ATTACH_COMPL:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001845 if (!mmctx)
1846 goto null_mmctx;
Harald Welte75bb8202010-03-14 15:45:01 +08001847 /* only in case SGSN offered new P-TMSI */
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001848 LOGMMCTXP(LOGL_INFO, mmctx, "-> ATTACH COMPLETE\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001849 mmctx_timer_stop(mmctx, 3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001850 mmctx->t3350_mode = GMM_T3350_MODE_NONE;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001851 mmctx->p_tmsi_old = 0;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001852 mmctx->pending_req = 0;
Harald Welte15487002015-12-25 22:23:27 +01001853 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1854 /* Unassign the old TLLI */
1855 mmctx->gb.tlli = mmctx->gb.tlli_new;
Maxeb64e3f2016-07-06 11:33:04 +02001856 gprs_llme_copy_key(mmctx, mmctx->gb.llme);
Harald Welte15487002015-12-25 22:23:27 +01001857 gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
Maxeb64e3f2016-07-06 11:33:04 +02001858 mmctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001859 }
Alexander Couzens5e33f442017-01-31 15:34:26 +01001860 mmctx->gmm_state = GMM_REGISTERED_NORMAL;
Daniel Willmanne9861832016-05-11 12:42:54 +02001861 mmctx_set_pmm_state(mmctx, PMM_CONNECTED);
Alexander Couzens5e33f442017-01-31 15:34:26 +01001862 mmctx_set_mm_state(mmctx, MM_READY);
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001863 rc = 0;
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001864
1865 memset(&sig_data, 0, sizeof(sig_data));
1866 sig_data.mm = mmctx;
1867 osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001868 break;
Harald Welteebe8a6d2010-05-18 19:58:38 +02001869 case GSM48_MT_GMM_RA_UPD_COMPL:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001870 if (!mmctx)
1871 goto null_mmctx;
Harald Welteebe8a6d2010-05-18 19:58:38 +02001872 /* only in case SGSN offered new P-TMSI */
Harald Welteb25510a2015-08-16 18:14:33 +02001873 LOGMMCTXP(LOGL_INFO, mmctx, "-> ROUTING AREA UPDATE COMPLETE\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001874 mmctx_timer_stop(mmctx, 3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001875 mmctx->t3350_mode = GMM_T3350_MODE_NONE;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001876 mmctx->p_tmsi_old = 0;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001877 mmctx->pending_req = 0;
Harald Welte15487002015-12-25 22:23:27 +01001878 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1879 /* Unassign the old TLLI */
1880 mmctx->gb.tlli = mmctx->gb.tlli_new;
Maxeb64e3f2016-07-06 11:33:04 +02001881 gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
1882 mmctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001883 }
Alexander Couzens5e33f442017-01-31 15:34:26 +01001884 mmctx->gmm_state = GMM_REGISTERED_NORMAL;
Daniel Willmanne9861832016-05-11 12:42:54 +02001885 mmctx_set_pmm_state(mmctx, PMM_CONNECTED);
Alexander Couzens5e33f442017-01-31 15:34:26 +01001886 mmctx_set_mm_state(mmctx, MM_READY);
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001887 rc = 0;
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001888
1889 memset(&sig_data, 0, sizeof(sig_data));
1890 sig_data.mm = mmctx;
1891 osmo_signal_dispatch(SS_SGSN, S_SGSN_UPDATE, &sig_data);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001892 break;
Harald Welte75bb8202010-03-14 15:45:01 +08001893 case GSM48_MT_GMM_PTMSI_REALL_COMPL:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001894 if (!mmctx)
1895 goto null_mmctx;
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001896 LOGMMCTXP(LOGL_INFO, mmctx, "-> PTMSI REALLLICATION COMPLETE\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001897 mmctx_timer_stop(mmctx, 3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001898 mmctx->t3350_mode = GMM_T3350_MODE_NONE;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001899 mmctx->p_tmsi_old = 0;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001900 mmctx->pending_req = 0;
Harald Welte15487002015-12-25 22:23:27 +01001901 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1902 /* Unassign the old TLLI */
1903 mmctx->gb.tlli = mmctx->gb.tlli_new;
1904 //gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff, mmctx->gb.tlli_new, GPRS_ALGO_GEA0, NULL);
1905 }
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001906 rc = 0;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001907 break;
Harald Welte75bb8202010-03-14 15:45:01 +08001908 case GSM48_MT_GMM_AUTH_CIPH_RESP:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001909 if (!mmctx)
1910 goto null_mmctx;
Harald Welte45fcf682010-07-03 11:09:06 +02001911 rc = gsm48_rx_gmm_auth_ciph_resp(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001912 break;
1913 default:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001914 LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
Harald Welte75bb8202010-03-14 15:45:01 +08001915 gh->msg_type);
Neels Hofmeyrd0ba6d62016-06-03 00:44:23 +02001916 if (mmctx)
1917 rc = gsm48_tx_gmm_status(mmctx, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
1918 else
1919 rc = -EINVAL;
Harald Welte75bb8202010-03-14 15:45:01 +08001920 break;
1921 }
1922
1923 return rc;
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001924
1925null_mmctx:
1926 LOGP(DMM, LOGL_ERROR,
1927 "Received GSM 04.08 message type 0x%02x,"
1928 " but no MM context available\n",
1929 gh->msg_type);
1930 return -EINVAL;
Harald Welte75bb8202010-03-14 15:45:01 +08001931}
1932
Harald Welte7e01d8e2010-05-31 20:23:38 +02001933static void mmctx_timer_cb(void *_mm)
1934{
1935 struct sgsn_mm_ctx *mm = _mm;
Jacob Erlbeck4d127672014-12-01 12:33:33 +01001936 struct gsm_auth_tuple *at;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001937
1938 mm->num_T_exp++;
1939
1940 switch (mm->T) {
1941 case 3350: /* waiting for ATTACH COMPLETE */
1942 if (mm->num_T_exp >= 5) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001943 LOGMMCTXP(LOGL_NOTICE, mm, "T3350 expired >= 5 times\n");
Jacob Erlbeck25335882014-11-03 10:12:52 +01001944 mm_ctx_cleanup_free(mm, "T3350");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001945 /* FIXME: should we return some error? */
1946 break;
1947 }
1948 /* re-transmit the respective msg and re-start timer */
1949 switch (mm->t3350_mode) {
1950 case GMM_T3350_MODE_ATT:
1951 gsm48_tx_gmm_att_ack(mm);
1952 break;
1953 case GMM_T3350_MODE_RAU:
1954 gsm48_tx_gmm_ra_upd_ack(mm);
1955 break;
1956 case GMM_T3350_MODE_PTMSI_REALL:
1957 /* FIXME */
1958 break;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001959 case GMM_T3350_MODE_NONE:
1960 LOGMMCTXP(LOGL_NOTICE, mm,
1961 "T3350 mode wasn't set, ignoring timeout\n");
1962 break;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001963 }
Harald Welte9b57a3d2015-08-15 19:08:21 +02001964 osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3350, 0);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001965 break;
Harald Welte45fcf682010-07-03 11:09:06 +02001966 case 3360: /* waiting for AUTH AND CIPH RESP */
1967 if (mm->num_T_exp >= 5) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001968 LOGMMCTXP(LOGL_NOTICE, mm, "T3360 expired >= 5 times\n");
Jacob Erlbeck25335882014-11-03 10:12:52 +01001969 mm_ctx_cleanup_free(mm, "T3360");
Harald Welte45fcf682010-07-03 11:09:06 +02001970 break;
1971 }
Jacob Erlbeck4d127672014-12-01 12:33:33 +01001972 /* Re-transmit the respective msg and re-start timer */
1973 if (mm->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
1974 LOGMMCTXP(LOGL_ERROR, mm,
1975 "timeout: invalid auth triplet reference\n");
1976 mm_ctx_cleanup_free(mm, "T3360");
1977 break;
1978 }
1979 at = &mm->auth_triplet;
1980
Max6d999582016-07-06 15:57:01 +02001981 gsm48_tx_gmm_auth_ciph_req(mm, at->vec.rand, at->key_seq, false);
Harald Welte9b57a3d2015-08-15 19:08:21 +02001982 osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0);
Harald Welte45fcf682010-07-03 11:09:06 +02001983 break;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001984 case 3370: /* waiting for IDENTITY RESPONSE */
1985 if (mm->num_T_exp >= 5) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001986 LOGMMCTXP(LOGL_NOTICE, mm, "T3370 expired >= 5 times\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001987 gsm48_tx_gmm_att_rej(mm, GMM_CAUSE_MS_ID_NOT_DERIVED);
Jacob Erlbeck25335882014-11-03 10:12:52 +01001988 mm_ctx_cleanup_free(mm, "GPRS ATTACH REJECT (T3370)");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001989 break;
1990 }
1991 /* re-tranmit IDENTITY REQUEST and re-start timer */
1992 gsm48_tx_gmm_id_req(mm, mm->t3370_id_type);
Harald Welte9b57a3d2015-08-15 19:08:21 +02001993 osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3370, 0);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001994 break;
1995 default:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001996 LOGMMCTXP(LOGL_ERROR, mm, "timer expired in unknown mode %u\n",
Harald Welte7e01d8e2010-05-31 20:23:38 +02001997 mm->T);
1998 }
1999}
2000
2001/* GPRS SESSION MANAGEMENT */
2002
Harald Welte94ecef32010-12-24 21:13:26 +01002003static void pdpctx_timer_cb(void *_mm);
2004
2005static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T,
2006 unsigned int seconds)
2007{
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02002008 if (osmo_timer_pending(&pdp->timer))
Pravin Kumarvelb9d251d2016-11-17 12:19:01 +05302009 LOGPDPCTXP(LOGL_ERROR, pdp, "Starting PDP timer %u while old "
Harald Welte94ecef32010-12-24 21:13:26 +01002010 "timer %u pending\n", T, pdp->T);
2011 pdp->T = T;
2012 pdp->num_T_exp = 0;
2013
2014 /* FIXME: we should do this only once ? */
2015 pdp->timer.data = pdp;
2016 pdp->timer.cb = &pdpctx_timer_cb;
2017
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02002018 osmo_timer_schedule(&pdp->timer, seconds, 0);
Harald Welte94ecef32010-12-24 21:13:26 +01002019}
2020
Pravin Kumarvel7b742462016-11-17 12:20:01 +05302021static void pdpctx_timer_stop(struct sgsn_pdp_ctx *pdp, unsigned int T)
2022{
2023 if (pdp->T != T)
2024 LOGPDPCTXP(LOGL_ERROR, pdp, "Stopping PDP timer %u but "
2025 "%u is running\n", T, pdp->T);
2026 osmo_timer_del(&pdp->timer);
2027}
2028
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02002029#if 0
Harald Welte2aea7492010-05-02 23:11:50 +02002030static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr)
2031{
2032 uint8_t v[6];
2033
2034 v[0] = PDP_TYPE_ORG_IETF;
2035 v[1] = PDP_TYPE_N_IETF_IPv4;
2036 *(uint32_t *)(v+2) = htonl(ipaddr);
2037
2038 msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
2039}
2040
2041static void msgb_put_pdp_addr_ppp(struct msgb *msg)
2042{
2043 uint8_t v[2];
2044
2045 v[0] = PDP_TYPE_ORG_ETSI;
2046 v[1] = PDP_TYPE_N_ETSI_PPP;
2047
2048 msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
2049}
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02002050#endif
Harald Welte2aea7492010-05-02 23:11:50 +02002051
Alexander Couzens32fdba02016-07-05 09:52:52 +02002052/* Section 9.5.2: Activate PDP Context Accept */
Harald Welte29d838e2010-05-18 10:35:06 +02002053int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp)
Harald Welte75bb8202010-03-14 15:45:01 +08002054{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01002055 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP ACC");
Harald Welte75bb8202010-03-14 15:45:01 +08002056 struct gsm48_hdr *gh;
Harald Welte29d838e2010-05-18 10:35:06 +02002057 uint8_t transaction_id = pdp->ti ^ 0x8; /* flip */
Harald Welte75bb8202010-03-14 15:45:01 +08002058
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002059 LOGPDPCTXP(LOGL_INFO, pdp, "<- ACTIVATE PDP CONTEXT ACK\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02002060 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_ACCEPT]);
Harald Welte75bb8202010-03-14 15:45:01 +08002061
Harald Welte29d838e2010-05-18 10:35:06 +02002062 mmctx2msgid(msg, pdp->mm);
Harald Welte75bb8202010-03-14 15:45:01 +08002063
2064 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2065 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
2066 gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
Harald Welte2aea7492010-05-02 23:11:50 +02002067
2068 /* Negotiated LLC SAPI */
Harald Welte29d838e2010-05-18 10:35:06 +02002069 msgb_v_put(msg, pdp->sapi);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02002070
Harald Welte540dcbc2010-05-18 13:20:08 +02002071 /* FIXME: copy QoS parameters from original request */
2072 //msgb_lv_put(msg, pdp->lib->qos_neg.l, pdp->lib->qos_neg.v);
2073 msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02002074
Harald Welte2aea7492010-05-02 23:11:50 +02002075 /* Radio priority 10.5.7.2 */
Harald Welte29d838e2010-05-18 10:35:06 +02002076 msgb_v_put(msg, pdp->lib->radio_pri);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02002077
Harald Welte2aea7492010-05-02 23:11:50 +02002078 /* PDP address */
Harald Welte7d7fd2b2010-05-18 14:51:18 +02002079 /* Highest 4 bits of first byte need to be set to 1, otherwise
2080 * the IE is identical with the 04.08 PDP Address IE */
2081 pdp->lib->eua.v[0] &= ~0xf0;
Harald Welte29d838e2010-05-18 10:35:06 +02002082 msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR,
2083 pdp->lib->eua.l, pdp->lib->eua.v);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02002084 pdp->lib->eua.v[0] |= 0xf0;
2085
Harald Welteeb471c92010-05-18 14:32:29 +02002086 /* Optional: Protocol configuration options (FIXME: why 'req') */
Holger Hans Peter Freyther1b51fc22014-04-04 11:55:21 +02002087 if (pdp->lib->pco_req.l)
Harald Welte29d838e2010-05-18 10:35:06 +02002088 msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
Harald Weltef2d66582010-05-18 14:36:11 +02002089 pdp->lib->pco_req.l, pdp->lib->pco_req.v);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02002090
Harald Welte2aea7492010-05-02 23:11:50 +02002091 /* Optional: Packet Flow Identifier */
Harald Welte75bb8202010-03-14 15:45:01 +08002092
Max4bc28212016-07-06 11:59:18 +02002093 return gsm48_gmm_sendmsg(msg, 0, pdp->mm, true);
Harald Welte75bb8202010-03-14 15:45:01 +08002094}
2095
Harald Welte29d838e2010-05-18 10:35:06 +02002096/* Section 9.5.3: Activate PDP Context reject */
2097int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
2098 uint8_t cause, uint8_t pco_len, uint8_t *pco_v)
2099{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01002100 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP REJ");
Harald Welte29d838e2010-05-18 10:35:06 +02002101 struct gsm48_hdr *gh;
2102 uint8_t transaction_id = tid ^ 0x8; /* flip */
2103
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002104 LOGMMCTXP(LOGL_NOTICE, mm, "<- ACTIVATE PDP CONTEXT REJ(cause=%u)\n", cause);
Alexander Couzens32fdba02016-07-05 09:52:52 +02002105 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REJECT]);
Harald Welte29d838e2010-05-18 10:35:06 +02002106
2107 mmctx2msgid(msg, mm);
2108
2109 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2110 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
2111 gh->msg_type = GSM48_MT_GSM_ACT_PDP_REJ;
2112
2113 msgb_v_put(msg, cause);
2114 if (pco_len && pco_v)
2115 msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v);
2116
Max4bc28212016-07-06 11:59:18 +02002117 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte29d838e2010-05-18 10:35:06 +02002118}
2119
Harald Welte94ecef32010-12-24 21:13:26 +01002120/* Section 9.5.8: Deactivate PDP Context Request */
2121static int _gsm48_tx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, uint8_t tid,
2122 uint8_t sm_cause)
2123{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01002124 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET REQ");
Harald Welte94ecef32010-12-24 21:13:26 +01002125 struct gsm48_hdr *gh;
2126 uint8_t transaction_id = tid ^ 0x8; /* flip */
2127
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002128 LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT REQ\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02002129 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_REQUEST]);
Harald Welte94ecef32010-12-24 21:13:26 +01002130
2131 mmctx2msgid(msg, mm);
2132
2133 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2134 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
2135 gh->msg_type = GSM48_MT_GSM_DEACT_PDP_REQ;
2136
2137 msgb_v_put(msg, sm_cause);
2138
Max4bc28212016-07-06 11:59:18 +02002139 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte94ecef32010-12-24 21:13:26 +01002140}
2141int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause)
2142{
Harald Welte9b57a3d2015-08-15 19:08:21 +02002143 pdpctx_timer_start(pdp, 3395, sgsn->cfg.timers.T3395);
Harald Welte94ecef32010-12-24 21:13:26 +01002144
2145 return _gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, sm_cause);
2146}
2147
Harald Welte75bb8202010-03-14 15:45:01 +08002148/* Section 9.5.9: Deactivate PDP Context Accept */
Harald Welte3b807312010-06-08 18:08:59 +02002149static int _gsm48_tx_gsm_deact_pdp_acc(struct sgsn_mm_ctx *mm, uint8_t tid)
Harald Welte75bb8202010-03-14 15:45:01 +08002150{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01002151 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET ACC");
Harald Welte75bb8202010-03-14 15:45:01 +08002152 struct gsm48_hdr *gh;
Harald Welte3b807312010-06-08 18:08:59 +02002153 uint8_t transaction_id = tid ^ 0x8; /* flip */
Harald Welte75bb8202010-03-14 15:45:01 +08002154
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002155 LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT ACK\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02002156 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_ACCEPT]);
Harald Welte75bb8202010-03-14 15:45:01 +08002157
Harald Welte3b807312010-06-08 18:08:59 +02002158 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +08002159
2160 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
2161 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
2162 gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
2163
Max4bc28212016-07-06 11:59:18 +02002164 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte3b807312010-06-08 18:08:59 +02002165}
2166int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
2167{
2168 return _gsm48_tx_gsm_deact_pdp_acc(pdp->mm, pdp->ti);
Harald Welte75bb8202010-03-14 15:45:01 +08002169}
2170
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08002171static int activate_ggsn(struct sgsn_mm_ctx *mmctx,
2172 struct sgsn_ggsn_ctx *ggsn, const uint8_t transaction_id,
2173 const uint8_t req_nsapi, const uint8_t req_llc_sapi,
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002174 struct tlv_parsed *tp, int destroy_ggsn)
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08002175{
2176 struct sgsn_pdp_ctx *pdp;
2177
Holger Hans Peter Freyther4b4f7b72015-05-29 15:11:55 +02002178 LOGMMCTXP(LOGL_DEBUG, mmctx, "Using GGSN %u\n", ggsn->id);
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08002179 ggsn->gsn = sgsn->gsn;
2180 pdp = sgsn_create_pdp_ctx(ggsn, mmctx, req_nsapi, tp);
2181 if (!pdp)
2182 return -1;
2183
2184 /* Store SAPI and Transaction Identifier */
2185 pdp->sapi = req_llc_sapi;
2186 pdp->ti = transaction_id;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002187 pdp->destroy_ggsn = destroy_ggsn;
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08002188
2189 return 0;
2190}
2191
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002192static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *hostent)
2193{
2194 struct sgsn_ggsn_ctx *ggsn;
2195 struct sgsn_ggsn_lookup *lookup = arg;
2196 struct in_addr *addr = NULL;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002197
2198 /* The context is gone while we made a request */
2199 if (!lookup->mmctx) {
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002200 talloc_free(lookup->orig_msg);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002201 talloc_free(lookup);
2202 return;
2203 }
2204
2205 if (status != ARES_SUCCESS) {
2206 struct sgsn_mm_ctx *mmctx = lookup->mmctx;
2207
2208 LOGMMCTXP(LOGL_ERROR, mmctx, "DNS query failed.\n");
2209
2210 /* Need to try with three digits now */
2211 if (lookup->state == SGSN_GGSN_2DIGIT) {
2212 char *hostname;
2213 int rc;
2214
2215 lookup->state = SGSN_GGSN_3DIGIT;
2216 hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
2217 lookup->apn_str, 1);
2218 LOGMMCTXP(LOGL_DEBUG, mmctx,
2219 "Going to query %s\n", hostname);
2220 rc = sgsn_ares_query(sgsn, hostname,
2221 ggsn_lookup_cb, lookup);
2222 if (rc != 0) {
Harald Welte0b8dbb72015-08-16 17:16:28 +02002223 LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't start GGSN\n");
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002224 goto reject_due_failure;
2225 }
2226 return;
2227 }
2228
2229 LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't resolve GGSN\n");
2230 goto reject_due_failure;
2231 }
2232
2233 if (hostent->h_length != sizeof(struct in_addr)) {
2234 LOGMMCTXP(LOGL_ERROR, lookup->mmctx,
Harald Welte369fb072015-08-16 17:16:57 +02002235 "Wrong addr size(%zu)\n", sizeof(struct in_addr));
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002236 goto reject_due_failure;
2237 }
2238
Holger Hans Peter Freytherb9852342015-06-02 09:38:41 +02002239 /* Get the first addr from the list */
2240 addr = (struct in_addr *) hostent->h_addr_list[0];
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002241 if (!addr) {
2242 LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "No host address.\n");
2243 goto reject_due_failure;
2244 }
2245
2246 ggsn = sgsn_ggsn_ctx_alloc(UINT32_MAX);
2247 if (!ggsn) {
2248 LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "Failed to create ggsn.\n");
2249 goto reject_due_failure;
2250 }
2251 ggsn->remote_addr = *addr;
2252 LOGMMCTXP(LOGL_NOTICE, lookup->mmctx,
2253 "Selected %s as GGSN.\n", inet_ntoa(*addr));
2254
2255 /* forget about the ggsn look-up */
2256 lookup->mmctx->ggsn_lookup = NULL;
2257
2258 activate_ggsn(lookup->mmctx, ggsn, lookup->ti, lookup->nsapi,
2259 lookup->sapi, &lookup->tp, 1);
2260
2261 /* Now free it */
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002262 talloc_free(lookup->orig_msg);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002263 talloc_free(lookup);
2264 return;
2265
2266reject_due_failure:
2267 gsm48_tx_gsm_act_pdp_rej(lookup->mmctx, lookup->ti,
2268 GMM_CAUSE_NET_FAIL, 0, NULL);
2269 lookup->mmctx->ggsn_lookup = NULL;
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002270 talloc_free(lookup->orig_msg);
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002271 talloc_free(lookup);
2272}
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002273
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002274static int do_act_pdp_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg, bool *delete)
Harald Welte75bb8202010-03-14 15:45:01 +08002275{
Harald Weltecf3c4142010-04-30 16:33:12 +02002276 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002277 struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
Harald Welteb1fd23a2010-05-02 21:07:14 +02002278 uint8_t req_qos_len, req_pdpa_len;
2279 uint8_t *req_qos, *req_pdpa;
2280 struct tlv_parsed tp;
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002281 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Harald Welte8bf65d02010-07-02 10:17:24 +02002282 struct sgsn_ggsn_ctx *ggsn;
Harald Welte29d838e2010-05-18 10:35:06 +02002283 struct sgsn_pdp_ctx *pdp;
Jacob Erlbeck3400f112015-02-02 18:03:05 +01002284 enum gsm48_gsm_cause gsm_cause;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002285 char apn_str[GSM_APN_LENGTH] = { 0, };
2286 char *hostname;
2287 int rc;
Harald Welte75bb8202010-03-14 15:45:01 +08002288
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002289 LOGMMCTXP(LOGL_INFO, mmctx, "-> ACTIVATE PDP CONTEXT REQ: SAPI=%u NSAPI=%u ",
Harald Welte29d838e2010-05-18 10:35:06 +02002290 act_req->req_llc_sapi, act_req->req_nsapi);
Harald Welte8a035af2010-05-18 10:57:45 +02002291
Harald Welteb7b0fd72010-07-02 22:52:04 +02002292 /* FIXME: length checks! */
Harald Welteb1fd23a2010-05-02 21:07:14 +02002293 req_qos_len = act_req->data[0];
2294 req_qos = act_req->data + 1; /* 10.5.6.5 */
2295 req_pdpa_len = act_req->data[1 + req_qos_len];
2296 req_pdpa = act_req->data + 1 + req_qos_len + 1; /* 10.5.6.4 */
Harald Welte75bb8202010-03-14 15:45:01 +08002297
Harald Welteb1fd23a2010-05-02 21:07:14 +02002298 switch (req_pdpa[0] & 0xf) {
2299 case 0x0:
2300 DEBUGPC(DMM, "ETSI ");
2301 break;
2302 case 0x1:
2303 DEBUGPC(DMM, "IETF ");
2304 break;
2305 case 0xf:
2306 DEBUGPC(DMM, "Empty ");
2307 break;
2308 }
2309
2310 switch (req_pdpa[1]) {
2311 case 0x21:
2312 DEBUGPC(DMM, "IPv4 ");
2313 if (req_pdpa_len >= 6) {
2314 struct in_addr ia;
2315 ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
2316 DEBUGPC(DMM, "%s ", inet_ntoa(ia));
2317 }
2318 break;
2319 case 0x57:
2320 DEBUGPC(DMM, "IPv6 ");
2321 if (req_pdpa_len >= 18) {
2322 /* FIXME: print IPv6 address */
2323 }
2324 break;
2325 default:
2326 DEBUGPC(DMM, "0x%02x ", req_pdpa[1]);
2327 break;
2328 }
2329
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002330 LOGPC(DMM, LOGL_INFO, "\n");
Harald Welteeb471c92010-05-18 14:32:29 +02002331
Harald Welte29d838e2010-05-18 10:35:06 +02002332 /* Check if NSAPI is out of range (TS 04.65 / 7.2) */
2333 if (act_req->req_nsapi < 5 || act_req->req_nsapi > 15) {
2334 /* Send reject with GSM_CAUSE_INV_MAND_INFO */
2335 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
2336 GSM_CAUSE_INV_MAND_INFO,
2337 0, NULL);
2338 }
2339
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08002340 /* Optional: Access Point Name, Protocol Config Options */
2341 if (req_pdpa + req_pdpa_len < msg->data + msg->len)
2342 tlv_parse(&tp, &gsm48_sm_att_tlvdef, req_pdpa + req_pdpa_len,
2343 (msg->data + msg->len) - (req_pdpa + req_pdpa_len), 0, 0);
2344 else
2345 memset(&tp, 0, sizeof(tp));
2346
2347
2348 /* put the non-TLV elements in the TLV parser structure to
2349 * pass them on to the SGSN / GTP code */
2350 tp.lv[OSMO_IE_GSM_REQ_QOS].len = req_qos_len;
2351 tp.lv[OSMO_IE_GSM_REQ_QOS].val = req_qos;
2352 tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].len = req_pdpa_len;
2353 tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].val = req_pdpa;
2354
Harald Welte29d838e2010-05-18 10:35:06 +02002355 /* Check if NSAPI is already in use */
Harald Welte5fbac982010-07-02 10:12:58 +02002356 pdp = sgsn_pdp_ctx_by_nsapi(mmctx, act_req->req_nsapi);
2357 if (pdp) {
2358 /* We already have a PDP context for this TLLI + NSAPI tuple */
2359 if (pdp->sapi == act_req->req_llc_sapi &&
2360 pdp->ti == transaction_id) {
2361 /* This apparently is a re-transmission of a PDP CTX
2362 * ACT REQ (our ACT ACK must have got dropped) */
2363 return gsm48_tx_gsm_act_pdp_acc(pdp);
2364 }
2365
2366 /* Send reject with GSM_CAUSE_NSAPI_IN_USE */
Harald Welte29d838e2010-05-18 10:35:06 +02002367 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
2368 GSM_CAUSE_NSAPI_IN_USE,
2369 0, NULL);
2370 }
Harald Welte75bb8202010-03-14 15:45:01 +08002371
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002372 if (mmctx->ggsn_lookup) {
2373 if (mmctx->ggsn_lookup->sapi == act_req->req_llc_sapi &&
2374 mmctx->ggsn_lookup->ti == transaction_id) {
2375 LOGMMCTXP(LOGL_NOTICE, mmctx,
2376 "Re-transmission while doing look-up. Ignoring.\n");
2377 return 0;
2378 }
2379 }
2380
Harald Weltea456a232010-07-02 10:15:49 +02002381 /* Only increment counter for a real activation, after we checked
2382 * for re-transmissions */
2383 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PDP_CTX_ACT]);
2384
Jacob Erlbeck3400f112015-02-02 18:03:05 +01002385 /* Determine GGSN based on APN and subscription options */
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002386 ggsn = sgsn_mm_ctx_find_ggsn_ctx(mmctx, &tp, &gsm_cause, apn_str);
2387 if (ggsn)
2388 return activate_ggsn(mmctx, ggsn, transaction_id,
2389 act_req->req_nsapi, act_req->req_llc_sapi,
2390 &tp, 0);
2391
2392 if (strlen(apn_str) == 0)
2393 goto no_context;
2394 if (!sgsn->cfg.dynamic_lookup)
2395 goto no_context;
2396
2397 /* schedule a dynamic look-up */
2398 mmctx->ggsn_lookup = talloc_zero(tall_bsc_ctx, struct sgsn_ggsn_lookup);
2399 if (!mmctx->ggsn_lookup)
2400 goto no_context;
2401
2402 mmctx->ggsn_lookup->state = SGSN_GGSN_2DIGIT;
2403 mmctx->ggsn_lookup->mmctx = mmctx;
2404 strcpy(mmctx->ggsn_lookup->apn_str, apn_str);
2405
2406 mmctx->ggsn_lookup->orig_msg = msg;
2407 mmctx->ggsn_lookup->tp = tp;
2408
2409 mmctx->ggsn_lookup->ti = transaction_id;
2410 mmctx->ggsn_lookup->nsapi = act_req->req_nsapi;
2411 mmctx->ggsn_lookup->sapi = act_req->req_llc_sapi;
2412
2413 hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
2414 mmctx->ggsn_lookup->apn_str, 0);
2415
2416 LOGMMCTXP(LOGL_DEBUG, mmctx, "Going to query %s\n", hostname);
2417 rc = sgsn_ares_query(sgsn, hostname,
2418 ggsn_lookup_cb, mmctx->ggsn_lookup);
2419 if (rc != 0) {
2420 LOGMMCTXP(LOGL_ERROR, mmctx, "Failed to start ares query.\n");
2421 goto no_context;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002422 }
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002423 *delete = 0;
Harald Welte8bf65d02010-07-02 10:17:24 +02002424
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002425 return 0;
2426
2427no_context:
Harald Welte0b8dbb72015-08-16 17:16:28 +02002428 LOGMMCTXP(LOGL_ERROR, mmctx, "No GGSN context found!\n");
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08002429 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
2430 gsm_cause, 0, NULL);
Harald Welte75bb8202010-03-14 15:45:01 +08002431}
2432
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002433/* Section 9.5.1: Activate PDP Context Request */
2434static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
2435 struct msgb *_msg)
2436{
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002437 bool delete = 1;
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002438 struct msgb *msg;
2439 int rc;
2440
Alexander Couzens32fdba02016-07-05 09:52:52 +02002441 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REQUEST]);
2442
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002443 /*
2444 * This is painful. We might not have a static GGSN
2445 * configuration and then would need to copy the msg
2446 * and re-do most of this routine (or call it again
2447 * and make sure it only goes through the dynamic
2448 * resolving. The question is what to optimize for
2449 * and the dynamic resolution will be the right thing
2450 * in the long run.
2451 */
2452 msg = gprs_msgb_copy(_msg, __func__);
2453 if (!msg) {
2454 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(_msg);
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002455 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002456
2457 LOGMMCTXP(LOGL_ERROR, mmctx, "-> ACTIVATE PDP CONTEXT REQ failed copy.\n");
2458 /* Send reject with GSM_CAUSE_INV_MAND_INFO */
2459 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
2460 GSM_CAUSE_NET_FAIL,
2461 0, NULL);
2462 }
2463
Holger Hans Peter Freyther87ac2582017-01-26 11:05:33 +01002464 rc = do_act_pdp_req(mmctx, msg, &delete);
2465 if (delete)
2466 msgb_free(msg);
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002467 return rc;
2468}
2469
Harald Welte75bb8202010-03-14 15:45:01 +08002470/* Section 9.5.8: Deactivate PDP Context Request */
Harald Welteeb471c92010-05-18 14:32:29 +02002471static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08002472{
Harald Weltecf3c4142010-04-30 16:33:12 +02002473 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002474 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Harald Welteeb471c92010-05-18 14:32:29 +02002475 struct sgsn_pdp_ctx *pdp;
Harald Welte75bb8202010-03-14 15:45:01 +08002476
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002477 LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01002478 get_value_string(gsm48_gsm_cause_names, gh->data[0]));
Alexander Couzens32fdba02016-07-05 09:52:52 +02002479 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_REQUEST]);
Harald Welte75bb8202010-03-14 15:45:01 +08002480
Harald Welteeb471c92010-05-18 14:32:29 +02002481 pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
2482 if (!pdp) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002483 LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Request for "
Harald Welteeb471c92010-05-18 14:32:29 +02002484 "non-existing PDP Context (IMSI=%s, TI=%u)\n",
2485 mm->imsi, transaction_id);
Harald Welte3b807312010-06-08 18:08:59 +02002486 return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
Harald Welteeb471c92010-05-18 14:32:29 +02002487 }
2488
2489 return sgsn_delete_pdp_ctx(pdp);
Harald Welte75bb8202010-03-14 15:45:01 +08002490}
2491
Harald Welte94ecef32010-12-24 21:13:26 +01002492/* Section 9.5.9: Deactivate PDP Context Accept */
2493static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
2494{
2495 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002496 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Harald Welte94ecef32010-12-24 21:13:26 +01002497 struct sgsn_pdp_ctx *pdp;
2498
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002499 LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT ACK\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02002500 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_ACCEPT]);
Harald Welte94ecef32010-12-24 21:13:26 +01002501
2502 pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
2503 if (!pdp) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002504 LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Accept for "
Harald Welte94ecef32010-12-24 21:13:26 +01002505 "non-existing PDP Context (IMSI=%s, TI=%u)\n",
2506 mm->imsi, transaction_id);
2507 return 0;
2508 }
Pravin Kumarvel7b742462016-11-17 12:20:01 +05302509 /* stop timer 3395 */
2510 pdpctx_timer_stop(pdp, 3395);
Harald Welte94ecef32010-12-24 21:13:26 +01002511 return sgsn_delete_pdp_ctx(pdp);
2512}
2513
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002514static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08002515{
2516 struct gsm48_hdr *gh = msgb_l3(msg);
2517
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002518 LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS SM STATUS (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01002519 get_value_string(gsm48_gsm_cause_names, gh->data[0]));
Harald Welte75bb8202010-03-14 15:45:01 +08002520
2521 return 0;
2522}
2523
Harald Welte94ecef32010-12-24 21:13:26 +01002524static void pdpctx_timer_cb(void *_pdp)
2525{
2526 struct sgsn_pdp_ctx *pdp = _pdp;
2527
2528 pdp->num_T_exp++;
2529
2530 switch (pdp->T) {
2531 case 3395: /* waiting for PDP CTX DEACT ACK */
2532 if (pdp->num_T_exp >= 4) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002533 LOGPDPCTXP(LOGL_NOTICE, pdp, "T3395 expired >= 5 times\n");
Harald Welte94ecef32010-12-24 21:13:26 +01002534 pdp->state = PDP_STATE_INACTIVE;
2535 sgsn_delete_pdp_ctx(pdp);
2536 break;
2537 }
Alexander Couzens88790b22016-07-19 15:14:03 +02002538 gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL);
Harald Welte94ecef32010-12-24 21:13:26 +01002539 break;
2540 default:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002541 LOGPDPCTXP(LOGL_ERROR, pdp, "timer expired in unknown mode %u\n",
Harald Welte94ecef32010-12-24 21:13:26 +01002542 pdp->T);
2543 }
2544}
2545
2546
Harald Welte75bb8202010-03-14 15:45:01 +08002547/* GPRS Session Management */
Harald Welte75871c72010-06-01 11:53:01 +02002548static int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
2549 struct gprs_llc_llme *llme)
Harald Welte75bb8202010-03-14 15:45:01 +08002550{
Harald Weltecf3c4142010-04-30 16:33:12 +02002551 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002552 int rc;
2553
Harald Welte75871c72010-06-01 11:53:01 +02002554 /* MMCTX can be NULL when called */
2555
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002556 if (!mmctx) {
2557 LOGP(DMM, LOGL_NOTICE, "Cannot handle SM for unknown MM CTX\n");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002558 /* 6.1.3.6 */
2559 if (gh->msg_type == GSM48_MT_GSM_STATUS)
2560 return 0;
2561
Max6d999582016-07-06 15:57:01 +02002562 return gsm0408_gprs_force_reattach_oldmsg(msg, llme);
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002563 }
2564
Harald Welte75bb8202010-03-14 15:45:01 +08002565 switch (gh->msg_type) {
2566 case GSM48_MT_GSM_ACT_PDP_REQ:
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002567 rc = gsm48_rx_gsm_act_pdp_req(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002568 break;
2569 case GSM48_MT_GSM_DEACT_PDP_REQ:
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002570 rc = gsm48_rx_gsm_deact_pdp_req(mmctx, msg);
Harald Welteeb471c92010-05-18 14:32:29 +02002571 break;
Harald Welte94ecef32010-12-24 21:13:26 +01002572 case GSM48_MT_GSM_DEACT_PDP_ACK:
2573 rc = gsm48_rx_gsm_deact_pdp_ack(mmctx, msg);
2574 break;
Harald Welte75bb8202010-03-14 15:45:01 +08002575 case GSM48_MT_GSM_STATUS:
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002576 rc = gsm48_rx_gsm_status(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002577 break;
2578 case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
2579 case GSM48_MT_GSM_ACT_AA_PDP_REQ:
2580 case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
Harald Welte20cbe912015-08-16 12:18:13 +02002581 LOGMMCTXP(LOGL_NOTICE, mmctx, "Unimplemented GSM 04.08 GSM msg type 0x%02x: %s\n",
2582 gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
Harald Welte263edd12010-06-09 10:51:23 +02002583 rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Harald Welte75bb8202010-03-14 15:45:01 +08002584 break;
2585 default:
Harald Welte20cbe912015-08-16 12:18:13 +02002586 LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GSM msg type 0x%02x: %s\n",
2587 gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
Harald Welte263edd12010-06-09 10:51:23 +02002588 rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Harald Welte75bb8202010-03-14 15:45:01 +08002589 break;
2590
2591 }
2592
2593 return rc;
2594}
2595
Max6d999582016-07-06 15:57:01 +02002596int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
2597 struct gprs_llc_llme *llme)
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002598{
Jacob Erlbeck6e15b732014-10-31 12:20:49 +01002599 int rc;
Alexander Couzens9625a612016-08-30 18:50:58 +02002600 if (llme)
2601 gprs_llgmm_reset_oldmsg(msg, GPRS_SAPI_GMM, llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002602
Jacob Erlbeck6e15b732014-10-31 12:20:49 +01002603 rc = gsm48_tx_gmm_detach_req_oldmsg(
2604 msg, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002605
Jacob Erlbeck6e15b732014-10-31 12:20:49 +01002606 return rc;
2607}
2608
2609int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx)
2610{
2611 int rc;
Harald Welte15487002015-12-25 22:23:27 +01002612 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb)
2613 gprs_llgmm_reset(mmctx->gb.llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002614
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01002615 rc = gsm48_tx_gmm_detach_req(
2616 mmctx, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002617
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01002618 mm_ctx_cleanup_free(mmctx, "forced reattach");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002619
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01002620 return rc;
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002621}
2622
Daniel Willmann945f6082016-05-21 17:35:57 +02002623/* Main entry point for incoming 04.08 GPRS messages from Iu */
2624int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
2625 uint16_t *sai)
2626{
2627 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
2628 uint8_t pdisc = gsm48_hdr_pdisc(gh);
2629 struct sgsn_mm_ctx *mmctx;
2630 int rc = -EINVAL;
2631
2632 mmctx = sgsn_mm_ctx_by_ue_ctx(msg->dst);
2633 if (mmctx) {
2634 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
2635 if (ra_id)
2636 memcpy(&mmctx->ra, ra_id, sizeof(mmctx->ra));
2637 }
2638
2639 /* MMCTX can be NULL */
2640
2641 switch (pdisc) {
2642 case GSM48_PDISC_MM_GPRS:
2643 rc = gsm0408_rcv_gmm(mmctx, msg, NULL, false);
2644#warning "set drop_cipherable arg for gsm0408_rcv_gmm() from IuPS?"
2645 break;
2646 case GSM48_PDISC_SM_GPRS:
2647 rc = gsm0408_rcv_gsm(mmctx, msg, NULL);
2648 break;
2649 default:
2650 LOGMMCTXP(LOGL_NOTICE, mmctx,
2651 "Unknown GSM 04.08 discriminator 0x%02x: %s\n",
2652 pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
2653 /* FIXME: return status message */
2654 break;
2655 }
2656
2657 /* MMCTX can be invalid */
2658
2659 return rc;
2660}
2661
Harald Weltebeaf11d2015-12-25 19:14:57 +01002662/* Main entry point for incoming 04.08 GPRS messages from Gb */
Max4bc28212016-07-06 11:59:18 +02002663int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
2664 bool drop_cipherable)
Harald Welte75bb8202010-03-14 15:45:01 +08002665{
Harald Weltecf3c4142010-04-30 16:33:12 +02002666 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Neels Hofmeyrf94dfd52016-03-14 16:13:24 +01002667 uint8_t pdisc = gsm48_hdr_pdisc(gh);
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002668 struct sgsn_mm_ctx *mmctx;
2669 struct gprs_ra_id ra_id;
Harald Welte75bb8202010-03-14 15:45:01 +08002670 int rc = -EINVAL;
2671
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002672 bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
2673 mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
Harald Welte8a035af2010-05-18 10:57:45 +02002674 if (mmctx) {
Harald Welte29d838e2010-05-18 10:35:06 +02002675 msgid2mmctx(mmctx, msg);
Harald Welte8a035af2010-05-18 10:57:45 +02002676 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
Harald Weltec28dc2f2015-12-25 19:12:21 +01002677 mmctx->gb.llme = llme;
Harald Welte8a035af2010-05-18 10:57:45 +02002678 }
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002679
2680 /* MMCTX can be NULL */
2681
Harald Welte75bb8202010-03-14 15:45:01 +08002682 switch (pdisc) {
2683 case GSM48_PDISC_MM_GPRS:
Max4bc28212016-07-06 11:59:18 +02002684 rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
Harald Welte75bb8202010-03-14 15:45:01 +08002685 break;
2686 case GSM48_PDISC_SM_GPRS:
Harald Welte75871c72010-06-01 11:53:01 +02002687 rc = gsm0408_rcv_gsm(mmctx, msg, llme);
Harald Welte75bb8202010-03-14 15:45:01 +08002688 break;
2689 default:
Harald Weltebdeaf5f2015-08-16 17:11:32 +02002690 LOGMMCTXP(LOGL_NOTICE, mmctx,
2691 "Unknown GSM 04.08 discriminator 0x%02x: %s\n",
Harald Welte20cbe912015-08-16 12:18:13 +02002692 pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
Harald Welte29d838e2010-05-18 10:35:06 +02002693 /* FIXME: return status message */
Harald Welte75bb8202010-03-14 15:45:01 +08002694 break;
2695 }
2696
Jacob Erlbeck12396bd2014-09-30 13:51:45 +02002697 /* MMCTX can be invalid */
2698
Harald Welte75bb8202010-03-14 15:45:01 +08002699 return rc;
2700}
Harald Welte50264822010-06-09 11:22:47 +02002701
2702int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli)
2703{
2704 struct sgsn_mm_ctx *mmctx;
2705
2706 mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
2707 if (!mmctx) {
2708 LOGP(DMM, LOGL_NOTICE, "SUSPEND request for unknown "
2709 "TLLI=%08x\n", tlli);
2710 return -EINVAL;
2711 }
2712
Alexander Couzens5e33f442017-01-31 15:34:26 +01002713 if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&
2714 mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002715 LOGMMCTXP(LOGL_NOTICE, mmctx, "SUSPEND request while state "
Harald Welte50264822010-06-09 11:22:47 +02002716 "!= REGISTERED (TLLI=%08x)\n", tlli);
2717 return -EINVAL;
2718 }
2719
2720 /* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */
Alexander Couzens5e33f442017-01-31 15:34:26 +01002721 mmctx->gmm_state = GMM_REGISTERED_SUSPENDED;
Harald Welte50264822010-06-09 11:22:47 +02002722 return 0;
2723}
2724
2725int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
2726 uint8_t suspend_ref)
2727{
2728 struct sgsn_mm_ctx *mmctx;
2729
2730 /* FIXME: make use of suspend reference? */
2731
2732 mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
2733 if (!mmctx) {
2734 LOGP(DMM, LOGL_NOTICE, "RESUME request for unknown "
2735 "TLLI=%08x\n", tlli);
2736 return -EINVAL;
2737 }
2738
Alexander Couzens5e33f442017-01-31 15:34:26 +01002739 if (mmctx->gmm_state != GMM_REGISTERED_NORMAL &&
2740 mmctx->gmm_state != GMM_REGISTERED_SUSPENDED) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002741 LOGMMCTXP(LOGL_NOTICE, mmctx, "RESUME request while state "
Harald Welte50264822010-06-09 11:22:47 +02002742 "!= SUSPENDED (TLLI=%08x)\n", tlli);
2743 /* FIXME: should we not simply ignore it? */
2744 return -EINVAL;
2745 }
2746
2747 /* Transition from SUSPENDED to NORMAL */
Alexander Couzens5e33f442017-01-31 15:34:26 +01002748 mmctx->gmm_state = GMM_REGISTERED_NORMAL;
Harald Welte50264822010-06-09 11:22:47 +02002749 return 0;
2750}
Daniel Willmann943f9732016-05-21 00:53:42 +02002751
2752#ifdef BUILD_IU
2753int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp, bool use_x213_nsap)
2754{
2755 struct msgb *msg;
2756 struct sgsn_mm_ctx *mm = pdp->mm;
2757 struct ue_conn_ctx *uectx;
2758 uint32_t ggsn_ip;
2759
2760 uectx = mm->iu.ue_ctx;
2761
2762 /* Get the IP address for ggsn user plane */
2763 memcpy(&ggsn_ip, pdp->lib->gsnru.v, pdp->lib->gsnru.l);
2764 ggsn_ip = htonl(ggsn_ip);
2765
2766 LOGP(DRANAP, LOGL_DEBUG, "Assigning RAB: rab_id=%d, ggsn_ip=%x,"
2767 " teid_gn=%x, use_x213_nsap=%d\n",
2768 rab_id, ggsn_ip, pdp->lib->teid_gn, use_x213_nsap);
2769
2770 msg = ranap_new_msg_rab_assign_data(rab_id, ggsn_ip,
2771 pdp->lib->teid_gn, use_x213_nsap);
2772 msg->l2h = msg->data;
2773 return iu_rab_act(uectx, msg);
2774}
2775#endif