blob: aa4991955e9daacb799c749cb05fd971a44aa82a [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
Harald Welte75bb8202010-03-14 15:45:01 +080036#include <openbsc/db.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010037#include <osmocom/core/msgb.h>
Harald Welte8b1713a2011-03-23 18:26:56 +010038#include <osmocom/gsm/tlv.h>
39#include <osmocom/gsm/gsm_utils.h>
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010040#include <osmocom/core/signal.h>
41#include <osmocom/core/talloc.h>
42#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +080043#include <osmocom/gsm/apn.h>
Harald Welte35ade5e2016-04-20 17:11:43 +020044#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
Harald Weltee4cc19a2010-05-02 12:57:45 +020045
Harald Weltecfb6b282012-06-16 14:59:56 +080046#include <osmocom/gprs/gprs_bssgp.h>
47
Harald Welte75bb8202010-03-14 15:45:01 +080048#include <openbsc/debug.h>
49#include <openbsc/gsm_data.h>
Harald Welte75bb8202010-03-14 15:45:01 +080050#include <openbsc/gsm_subscriber.h>
51#include <openbsc/gsm_04_08.h>
Harald Welte75bb8202010-03-14 15:45:01 +080052#include <openbsc/paging.h>
Harald Welte75bb8202010-03-14 15:45:01 +080053#include <openbsc/transaction.h>
54#include <openbsc/gprs_llc.h>
55#include <openbsc/gprs_sgsn.h>
Harald Welte29d838e2010-05-18 10:35:06 +020056#include <openbsc/gprs_gmm.h>
Jacob Erlbeck1063ae02015-01-23 11:44:39 +010057#include <openbsc/gprs_utils.h>
Harald Weltec1f6bfe2010-05-17 22:58:03 +020058#include <openbsc/sgsn.h>
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +020059#include <openbsc/signal.h>
Harald Weltec1f6bfe2010-05-17 22:58:03 +020060
Harald Welte29d838e2010-05-18 10:35:06 +020061#include <pdp.h>
62
Harald Welte7e01d8e2010-05-31 20:23:38 +020063#define PTMSI_ALLOC
64
Harald Weltec1f6bfe2010-05-17 22:58:03 +020065extern struct sgsn_instance *sgsn;
Harald Welte75bb8202010-03-14 15:45:01 +080066
Harald Welted9610722010-06-09 10:28:29 +020067static const struct tlv_definition gsm48_gmm_att_tlvdef = {
68 .def = {
Harald Welte45fcf682010-07-03 11:09:06 +020069 [GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 },
Harald Welted9610722010-06-09 10:28:29 +020070 [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 },
71 [GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 },
Harald Welte45fcf682010-07-03 11:09:06 +020072 [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 },
73 [GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_FIXED, 16 },
74 [GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_FIXED, 4 },
Harald Welted9610722010-06-09 10:28:29 +020075 [GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 },
Harald Welte45fcf682010-07-03 11:09:06 +020076 [GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 },
Harald Welted9610722010-06-09 10:28:29 +020077 [GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 },
78 [GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 },
79 [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 },
80 [GSM48_IE_GMM_GMM_MBMS_CTX_ST] = { TLV_TYPE_TLV, 0 },
81 },
82};
83
84static const struct tlv_definition gsm48_sm_att_tlvdef = {
85 .def = {
86 [GSM48_IE_GSM_APN] = { TLV_TYPE_TLV, 0 },
87 [GSM48_IE_GSM_PROTO_CONF_OPT] = { TLV_TYPE_TLV, 0 },
88 [GSM48_IE_GSM_PDP_ADDR] = { TLV_TYPE_TLV, 0 },
89 [GSM48_IE_GSM_AA_TMR] = { TLV_TYPE_TV, 1 },
90 [GSM48_IE_GSM_NAME_FULL] = { TLV_TYPE_TLV, 0 },
91 [GSM48_IE_GSM_NAME_SHORT] = { TLV_TYPE_TLV, 0 },
Harald Welte45fcf682010-07-03 11:09:06 +020092 [GSM48_IE_GSM_TIMEZONE] = { TLV_TYPE_FIXED, 1 },
93 [GSM48_IE_GSM_UTC_AND_TZ] = { TLV_TYPE_FIXED, 7 },
Harald Welted9610722010-06-09 10:28:29 +020094 [GSM48_IE_GSM_LSA_ID] = { TLV_TYPE_TLV, 0 },
95 },
96};
97
Jacob Erlbeckac336982014-12-02 09:47:26 +010098static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx);
99
Harald Welte8f77f192010-05-17 00:44:57 +0200100/* Our implementation, should be kept in SGSN */
Harald Welte75bb8202010-03-14 15:45:01 +0800101
Harald Welte7e01d8e2010-05-31 20:23:38 +0200102static void mmctx_timer_cb(void *_mm);
103
104static void mmctx_timer_start(struct sgsn_mm_ctx *mm, unsigned int T,
105 unsigned int seconds)
106{
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200107 if (osmo_timer_pending(&mm->timer))
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200108 LOGMMCTXP(LOGL_ERROR, mm, "Starting MM timer %u while old "
Harald Welte7e01d8e2010-05-31 20:23:38 +0200109 "timer %u pending\n", T, mm->T);
110 mm->T = T;
111 mm->num_T_exp = 0;
112
113 /* FIXME: we should do this only once ? */
114 mm->timer.data = mm;
115 mm->timer.cb = &mmctx_timer_cb;
116
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200117 osmo_timer_schedule(&mm->timer, seconds, 0);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200118}
119
120static void mmctx_timer_stop(struct sgsn_mm_ctx *mm, unsigned int T)
121{
122 if (mm->T != T)
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200123 LOGMMCTXP(LOGL_ERROR, mm, "Stopping MM timer %u but "
Harald Welte7e01d8e2010-05-31 20:23:38 +0200124 "%u is running\n", T, mm->T);
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +0200125 osmo_timer_del(&mm->timer);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200126}
127
Jacob Erlbecke6140d02015-01-23 11:33:51 +0100128time_t gprs_max_time_to_idle(void)
129{
Harald Welte9b57a3d2015-08-15 19:08:21 +0200130 return sgsn->cfg.timers.T3314 + (sgsn->cfg.timers.T3312 + 4 * 60);
Jacob Erlbecke6140d02015-01-23 11:33:51 +0100131}
132
Harald Welte75bb8202010-03-14 15:45:01 +0800133/* Send a message through the underlying layer */
Harald Welte8a035af2010-05-18 10:57:45 +0200134static int gsm48_gmm_sendmsg(struct msgb *msg, int command,
Max4bc28212016-07-06 11:59:18 +0200135 struct sgsn_mm_ctx *mm, bool encryptable)
Harald Welte75bb8202010-03-14 15:45:01 +0800136{
Harald Welte8a035af2010-05-18 10:57:45 +0200137 if (mm)
138 rate_ctr_inc(&mm->ctrg->ctr[GMM_CTR_PKTS_SIG_OUT]);
139
Harald Welte2351f1f2010-05-02 11:54:55 +0200140 /* caller needs to provide TLLI, BVCI and NSEI */
Max4bc28212016-07-06 11:59:18 +0200141 return gprs_llc_tx_ui(msg, GPRS_SAPI_GMM, command, mm, encryptable);
Harald Welte75bb8202010-03-14 15:45:01 +0800142}
143
Harald Welte2351f1f2010-05-02 11:54:55 +0200144/* copy identifiers from old message to new message, this
145 * is required so lower layers can route it correctly */
146static void gmm_copy_id(struct msgb *msg, const struct msgb *old)
147{
148 msgb_tlli(msg) = msgb_tlli(old);
149 msgb_bvci(msg) = msgb_bvci(old);
150 msgb_nsei(msg) = msgb_nsei(old);
151}
152
Harald Welte29d838e2010-05-18 10:35:06 +0200153/* Store BVCI/NSEI in MM context */
154static void msgid2mmctx(struct sgsn_mm_ctx *mm, const struct msgb *msg)
155{
Harald Weltec28dc2f2015-12-25 19:12:21 +0100156 mm->gb.bvci = msgb_bvci(msg);
157 mm->gb.nsei = msgb_nsei(msg);
Harald Welte29d838e2010-05-18 10:35:06 +0200158}
159
160/* Store BVCI/NSEI in MM context */
161static void mmctx2msgid(struct msgb *msg, const struct sgsn_mm_ctx *mm)
162{
Harald Weltec28dc2f2015-12-25 19:12:21 +0100163 msgb_tlli(msg) = mm->gb.tlli;
164 msgb_bvci(msg) = mm->gb.bvci;
165 msgb_nsei(msg) = mm->gb.nsei;
Harald Welte29d838e2010-05-18 10:35:06 +0200166}
167
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200168static void mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx, const char *log_text)
169{
Jacob Erlbeck70c177a2015-01-26 14:43:07 +0100170 LOGMMCTXP(LOGL_INFO, ctx, "Cleaning MM context due to %s\n", log_text);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200171
172 /* Mark MM state as deregistered */
173 ctx->mm_state = GMM_DEREGISTERED;
174
Jacob Erlbeck70c177a2015-01-26 14:43:07 +0100175 sgsn_mm_ctx_cleanup_free(ctx);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200176}
177
Harald Welte263edd12010-06-09 10:51:23 +0200178/* Chapter 9.4.18 */
179static int _tx_status(struct msgb *msg, uint8_t cause,
180 struct sgsn_mm_ctx *mmctx, int sm)
181{
182 struct gsm48_hdr *gh;
183
184 /* MMCTX might be NULL! */
185
186 DEBUGP(DMM, "<- GPRS MM STATUS (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +0100187 get_value_string(gsm48_gmm_cause_names, cause));
Harald Welte263edd12010-06-09 10:51:23 +0200188
189 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
190 if (sm) {
191 gh->proto_discr = GSM48_PDISC_SM_GPRS;
192 gh->msg_type = GSM48_MT_GSM_STATUS;
193 } else {
194 gh->proto_discr = GSM48_PDISC_MM_GPRS;
195 gh->msg_type = GSM48_MT_GMM_STATUS;
196 }
197 gh->data[0] = cause;
198
Max4bc28212016-07-06 11:59:18 +0200199 return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
Harald Welte263edd12010-06-09 10:51:23 +0200200}
Jacob Erlbeckce61bb72014-10-29 22:57:30 +0100201
Harald Welte263edd12010-06-09 10:51:23 +0200202static int gsm48_tx_gmm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
203{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100204 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 GMM STATUS");
Harald Welte263edd12010-06-09 10:51:23 +0200205
206 mmctx2msgid(msg, mmctx);
207 return _tx_status(msg, cause, mmctx, 0);
Harald Welte263edd12010-06-09 10:51:23 +0200208}
Jacob Erlbeckce61bb72014-10-29 22:57:30 +0100209
Harald Welte263edd12010-06-09 10:51:23 +0200210static int gsm48_tx_sm_status(struct sgsn_mm_ctx *mmctx, uint8_t cause)
211{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100212 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SM STATUS");
Harald Welte263edd12010-06-09 10:51:23 +0200213
214 mmctx2msgid(msg, mmctx);
215 return _tx_status(msg, cause, mmctx, 1);
Harald Welte263edd12010-06-09 10:51:23 +0200216}
217
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200218static int _tx_detach_req(struct msgb *msg, uint8_t detach_type, uint8_t cause,
219 struct sgsn_mm_ctx *mmctx)
220{
221 struct gsm48_hdr *gh;
222
223 /* MMCTX might be NULL! */
224
225 DEBUGP(DMM, "<- GPRS MM DETACH REQ (type: %s, cause: %s)\n",
226 get_value_string(gprs_det_t_mt_strs, detach_type),
Jacob Erlbeck9346dad2015-01-05 17:30:02 +0100227 get_value_string(gsm48_gmm_cause_names, cause));
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200228
229 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
230
231 gh->proto_discr = GSM48_PDISC_MM_GPRS;
232 gh->msg_type = GSM48_MT_GMM_DETACH_REQ;
233 gh->data[0] = detach_type & 0x07;
234
235 msgb_tv_put(msg, GSM48_IE_GMM_CAUSE, cause);
236
Max4bc28212016-07-06 11:59:18 +0200237 return gsm48_gmm_sendmsg(msg, 0, mmctx, true);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200238}
239
240static int gsm48_tx_gmm_detach_req(struct sgsn_mm_ctx *mmctx,
241 uint8_t detach_type, uint8_t cause)
242{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100243 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET REQ");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200244
245 mmctx2msgid(msg, mmctx);
246 return _tx_detach_req(msg, detach_type, cause, mmctx);
247}
248
249static int gsm48_tx_gmm_detach_req_oldmsg(struct msgb *oldmsg,
250 uint8_t detach_type, uint8_t cause)
251{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100252 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET OLD");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +0200253
254 gmm_copy_id(msg, oldmsg);
255 return _tx_detach_req(msg, detach_type, cause, NULL);
256}
Harald Welte263edd12010-06-09 10:51:23 +0200257
Harald Welte242d1722010-05-03 10:54:35 +0200258static struct gsm48_qos default_qos = {
259 .delay_class = 4, /* best effort */
260 .reliab_class = GSM48_QOS_RC_LLC_UN_RLC_ACK_DATA_PROT,
261 .peak_tput = GSM48_QOS_PEAK_TPUT_32000bps,
262 .preced_class = GSM48_QOS_PC_NORMAL,
263 .mean_tput = GSM48_QOS_MEAN_TPUT_BEST_EFFORT,
264 .traf_class = GSM48_QOS_TC_INTERACTIVE,
265 .deliv_order = GSM48_QOS_DO_UNORDERED,
266 .deliv_err_sdu = GSM48_QOS_ERRSDU_YES,
267 .max_sdu_size = GSM48_QOS_MAXSDU_1520,
268 .max_bitrate_up = GSM48_QOS_MBRATE_63k,
269 .max_bitrate_down = GSM48_QOS_MBRATE_63k,
270 .resid_ber = GSM48_QOS_RBER_5e_2,
271 .sdu_err_ratio = GSM48_QOS_SERR_1e_2,
272 .handling_prio = 3,
273 .xfer_delay = 0x10, /* 200ms */
274 .guar_bitrate_up = GSM48_QOS_MBRATE_0k,
275 .guar_bitrate_down = GSM48_QOS_MBRATE_0k,
276 .sig_ind = 0, /* not optimised for signalling */
277 .max_bitrate_down_ext = 0, /* use octet 9 */
278 .guar_bitrate_down_ext = 0, /* use octet 13 */
279};
280
Harald Welte75bb8202010-03-14 15:45:01 +0800281/* Chapter 9.4.2: Attach accept */
Harald Welte64df8ed2010-05-18 17:04:55 +0200282static int gsm48_tx_gmm_att_ack(struct sgsn_mm_ctx *mm)
Harald Welte75bb8202010-03-14 15:45:01 +0800283{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100284 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT ACK");
Harald Welte75bb8202010-03-14 15:45:01 +0800285 struct gsm48_hdr *gh;
286 struct gsm48_attach_ack *aa;
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +0200287 uint8_t *mid;
288#if 0
289 uint8_t *ptsig;
290#endif
Harald Welte75bb8202010-03-14 15:45:01 +0800291
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200292 LOGMMCTXP(LOGL_INFO, mm, "<- GPRS ATTACH ACCEPT (new P-TMSI=0x%08x)\n", mm->p_tmsi);
Alexander Couzens32fdba02016-07-05 09:52:52 +0200293 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_ACKED]);
Harald Welte75bb8202010-03-14 15:45:01 +0800294
Harald Welte64df8ed2010-05-18 17:04:55 +0200295 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +0800296
297 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
298 gh->proto_discr = GSM48_PDISC_MM_GPRS;
299 gh->msg_type = GSM48_MT_GMM_ATTACH_ACK;
300
301 aa = (struct gsm48_attach_ack *) msgb_put(msg, sizeof(*aa));
302 aa->force_stby = 0; /* not indicated */
303 aa->att_result = 1; /* GPRS only */
Harald Welte9b57a3d2015-08-15 19:08:21 +0200304 aa->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
Harald Welte75bb8202010-03-14 15:45:01 +0800305 aa->radio_prio = 4; /* lowest */
Harald Welte64df8ed2010-05-18 17:04:55 +0200306 gsm48_construct_ra(aa->ra_id.digits, &mm->ra);
Harald Welte75bb8202010-03-14 15:45:01 +0800307
Harald Welteebe8a6d2010-05-18 19:58:38 +0200308#if 0
Harald Welte64df8ed2010-05-18 17:04:55 +0200309 /* Optional: P-TMSI signature */
310 msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
311 ptsig = msgb_put(msg, 3);
312 ptsig[0] = mm->p_tmsi_sig >> 16;
313 ptsig[1] = mm->p_tmsi_sig >> 8;
314 ptsig[2] = mm->p_tmsi_sig & 0xff;
315
Harald Welte7e01d8e2010-05-31 20:23:38 +0200316#endif
Jacob Erlbeck1063ae02015-01-23 11:44:39 +0100317 /* Optional: Negotiated Ready timer value
318 * (fixed 44s, default value, GSM 04.08, table 11.4a) to safely limit
319 * the inactivity time READY->STANDBY.
320 */
321 msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
Harald Welte9b57a3d2015-08-15 19:08:21 +0200322 gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
Harald Welte64df8ed2010-05-18 17:04:55 +0200323
Harald Welte7e01d8e2010-05-31 20:23:38 +0200324#ifdef PTMSI_ALLOC
Harald Welte64df8ed2010-05-18 17:04:55 +0200325 /* Optional: Allocated P-TMSI */
Harald Welte64df8ed2010-05-18 17:04:55 +0200326 mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
327 gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
Harald Welteebe8a6d2010-05-18 19:58:38 +0200328 mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
329#endif
Harald Welte7e01d8e2010-05-31 20:23:38 +0200330
Harald Welte64df8ed2010-05-18 17:04:55 +0200331 /* Optional: MS-identity (combined attach) */
332 /* Optional: GMM cause (partial attach result for combined attach) */
333
Max4bc28212016-07-06 11:59:18 +0200334 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte75bb8202010-03-14 15:45:01 +0800335}
336
337/* Chapter 9.4.5: Attach reject */
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200338static int _tx_gmm_att_rej(struct msgb *msg, uint8_t gmm_cause,
339 const struct sgsn_mm_ctx *mm)
Harald Welte75bb8202010-03-14 15:45:01 +0800340{
Harald Welte75bb8202010-03-14 15:45:01 +0800341 struct gsm48_hdr *gh;
342
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200343 LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS ATTACH REJECT: %s\n",
344 get_value_string(gsm48_gmm_cause_names, gmm_cause));
Alexander Couzens32fdba02016-07-05 09:52:52 +0200345 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_REJECTED]);
Harald Welte75bb8202010-03-14 15:45:01 +0800346
Harald Welte75bb8202010-03-14 15:45:01 +0800347 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
348 gh->proto_discr = GSM48_PDISC_MM_GPRS;
349 gh->msg_type = GSM48_MT_GMM_ATTACH_REJ;
350 gh->data[0] = gmm_cause;
351
Max4bc28212016-07-06 11:59:18 +0200352 return gsm48_gmm_sendmsg(msg, 0, NULL, false);
Harald Welte75bb8202010-03-14 15:45:01 +0800353}
Harald Welte64df8ed2010-05-18 17:04:55 +0200354static int gsm48_tx_gmm_att_rej_oldmsg(const struct msgb *old_msg,
355 uint8_t gmm_cause)
356{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100357 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT REJ OLD");
Harald Welte64df8ed2010-05-18 17:04:55 +0200358 gmm_copy_id(msg, old_msg);
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200359 return _tx_gmm_att_rej(msg, gmm_cause, NULL);
Harald Welte64df8ed2010-05-18 17:04:55 +0200360}
361static int gsm48_tx_gmm_att_rej(struct sgsn_mm_ctx *mm,
362 uint8_t gmm_cause)
363{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100364 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ATT REJ");
Harald Welte64df8ed2010-05-18 17:04:55 +0200365 mmctx2msgid(msg, mm);
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200366 return _tx_gmm_att_rej(msg, gmm_cause, mm);
Harald Welte64df8ed2010-05-18 17:04:55 +0200367}
Harald Welte75bb8202010-03-14 15:45:01 +0800368
Harald Welte8f77f192010-05-17 00:44:57 +0200369/* Chapter 9.4.6.2 Detach accept */
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200370static int _tx_detach_ack(struct msgb *msg, uint8_t force_stby,
371 struct sgsn_mm_ctx *mm)
Harald Welte8f77f192010-05-17 00:44:57 +0200372{
Harald Welte8f77f192010-05-17 00:44:57 +0200373 struct gsm48_hdr *gh;
374
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200375 /* MMCTX might be NULL! */
Harald Welte8f77f192010-05-17 00:44:57 +0200376
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200377 DEBUGP(DMM, "<- GPRS MM DETACH ACC (force-standby: %d)\n", force_stby);
Alexander Couzens32fdba02016-07-05 09:52:52 +0200378 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_DETACH_ACKED]);
Harald Welte64df8ed2010-05-18 17:04:55 +0200379
Harald Welte8f77f192010-05-17 00:44:57 +0200380 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
381 gh->proto_discr = GSM48_PDISC_MM_GPRS;
382 gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
383 gh->data[0] = force_stby;
384
Max4bc28212016-07-06 11:59:18 +0200385 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte8f77f192010-05-17 00:44:57 +0200386}
387
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200388static int gsm48_tx_gmm_det_ack(struct sgsn_mm_ctx *mm, uint8_t force_stby)
389{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100390 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACK");
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200391
392 mmctx2msgid(msg, mm);
393 return _tx_detach_ack(msg, force_stby, mm);
394}
395
396static int gsm48_tx_gmm_det_ack_oldmsg(struct msgb *oldmsg, uint8_t force_stby)
397{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100398 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACK OLD");
Jacob Erlbeck42d284f2014-10-21 13:09:55 +0200399
400 gmm_copy_id(msg, oldmsg);
401 return _tx_detach_ack(msg, force_stby, NULL);
402}
403
Harald Welte75bb8202010-03-14 15:45:01 +0800404/* Transmit Chapter 9.4.12 Identity Request */
Harald Welte64df8ed2010-05-18 17:04:55 +0200405static int gsm48_tx_gmm_id_req(struct sgsn_mm_ctx *mm, uint8_t id_type)
Harald Welte75bb8202010-03-14 15:45:01 +0800406{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100407 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 ID REQ");
Harald Welte75bb8202010-03-14 15:45:01 +0800408 struct gsm48_hdr *gh;
409
Harald Welte7e3e9332015-08-16 18:07:48 +0200410 LOGMMCTXP(LOGL_DEBUG, mm, "<- GPRS IDENTITY REQUEST: mi_type=%s\n",
411 gsm48_mi_type_name(id_type));
Harald Welte75bb8202010-03-14 15:45:01 +0800412
Harald Welte64df8ed2010-05-18 17:04:55 +0200413 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +0800414
415 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
416 gh->proto_discr = GSM48_PDISC_MM_GPRS;
417 gh->msg_type = GSM48_MT_GMM_ID_REQ;
418 /* 10.5.5.9 ID type 2 + identity type and 10.5.5.7 'force to standby' IE */
419 gh->data[0] = id_type & 0xf;
420
Max4bc28212016-07-06 11:59:18 +0200421 return gsm48_gmm_sendmsg(msg, 1, mm, false);
Harald Welte75bb8202010-03-14 15:45:01 +0800422}
423
Max6d999582016-07-06 15:57:01 +0200424/* 3GPP TS 24.008 Section 9.4.9: Authentication and Ciphering Request */
Max9943d7a2016-07-05 15:19:12 +0200425static int gsm48_tx_gmm_auth_ciph_req(struct sgsn_mm_ctx *mm, uint8_t *rnd,
Max6d999582016-07-06 15:57:01 +0200426 uint8_t key_seq, bool force_standby)
Harald Welte45fcf682010-07-03 11:09:06 +0200427{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100428 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REQ");
Harald Welte45fcf682010-07-03 11:09:06 +0200429 struct gsm48_hdr *gh;
430 struct gsm48_auth_ciph_req *acreq;
Max9943d7a2016-07-05 15:19:12 +0200431 uint8_t *m_rand, *m_cksn, rbyte;
Harald Welte45fcf682010-07-03 11:09:06 +0200432
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200433 LOGMMCTXP(LOGL_INFO, mm, "<- GPRS AUTH AND CIPHERING REQ (rand = %s)\n",
Max9943d7a2016-07-05 15:19:12 +0200434 osmo_hexdump(rnd, 16));
Harald Welte45fcf682010-07-03 11:09:06 +0200435
436 mmctx2msgid(msg, mm);
437
438 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
439 gh->proto_discr = GSM48_PDISC_MM_GPRS;
440 gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REQ;
441
442 acreq = (struct gsm48_auth_ciph_req *) msgb_put(msg, sizeof(*acreq));
Max6d999582016-07-06 15:57:01 +0200443 acreq->ciph_alg = mm->ciph_algo & 0xf;
444 /* § 10.5.5.10: */
Harald Welte45fcf682010-07-03 11:09:06 +0200445 acreq->imeisv_req = 0x1;
Max6d999582016-07-06 15:57:01 +0200446 /* § 10.5.5.7: */
447 acreq->force_stby = force_standby;
Max9943d7a2016-07-05 15:19:12 +0200448 /* 3GPP TS 24.008 § 10.5.5.19: */
449 if (RAND_bytes(&rbyte, 1) != 1) {
450 LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed for A&C ref, falling "
451 "back to rand()\n");
452 acreq->ac_ref_nr = rand();
453 } else
454 acreq->ac_ref_nr = rbyte;
455 mm->ac_ref_nr_used = acreq->ac_ref_nr;
Harald Welte45fcf682010-07-03 11:09:06 +0200456
457 /* Only if authentication is requested we need to set RAND + CKSN */
Max9943d7a2016-07-05 15:19:12 +0200458 if (rnd) {
Harald Welte45fcf682010-07-03 11:09:06 +0200459 m_rand = msgb_put(msg, 16+1);
460 m_rand[0] = GSM48_IE_GMM_AUTH_RAND;
Max9943d7a2016-07-05 15:19:12 +0200461 memcpy(m_rand + 1, rnd, 16);
Max6d999582016-07-06 15:57:01 +0200462 /* § 10.5.1.2: */
Jacob Erlbeck79dcaa42014-12-01 10:36:17 +0100463 m_cksn = msgb_put(msg, 1);
464 m_cksn[0] = (GSM48_IE_GMM_CIPH_CKSN << 4) | (key_seq & 0x07);
Harald Welte45fcf682010-07-03 11:09:06 +0200465 }
Max6d999582016-07-06 15:57:01 +0200466 /* FIXME: add AUTN for 3g auth according to 3GPP TS 24.008 § 10.5.3.1.1 */
Harald Welte45fcf682010-07-03 11:09:06 +0200467 /* FIXME: make sure we don't send any other messages to the MS */
468
Max4bc28212016-07-06 11:59:18 +0200469 return gsm48_gmm_sendmsg(msg, 1, mm, false);
Harald Welte45fcf682010-07-03 11:09:06 +0200470}
471
472/* Section 9.4.11: Authentication and Ciphering Reject */
473static int gsm48_tx_gmm_auth_ciph_rej(struct sgsn_mm_ctx *mm)
474{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +0100475 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 AUTH CIPH REJ");
Harald Welte45fcf682010-07-03 11:09:06 +0200476 struct gsm48_hdr *gh;
477
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200478 LOGMMCTXP(LOGL_NOTICE, mm, "<- GPRS AUTH AND CIPH REJECT\n");
Harald Welte45fcf682010-07-03 11:09:06 +0200479
480 mmctx2msgid(msg, mm);
481
482 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
483 gh->proto_discr = GSM48_PDISC_MM_GPRS;
484 gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_REJ;
485
Max4bc28212016-07-06 11:59:18 +0200486 return gsm48_gmm_sendmsg(msg, 0, mm, false);
Harald Welte45fcf682010-07-03 11:09:06 +0200487}
488
489/* Section 9.4.10: Authentication and Ciphering Response */
490static int gsm48_rx_gmm_auth_ciph_resp(struct sgsn_mm_ctx *ctx,
491 struct msgb *msg)
492{
493 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
494 struct gsm48_auth_ciph_resp *acr = (struct gsm48_auth_ciph_resp *)gh->data;
495 struct tlv_parsed tp;
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100496 struct gsm_auth_tuple *at;
497 int rc;
498
499 LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS AUTH AND CIPH RESPONSE\n");
500
501 if (ctx->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
502 LOGMMCTXP(LOGL_NOTICE, ctx,
503 "Unexpected Auth & Ciph Response (ignored)\n");
504 return 0;
505 }
Harald Welte45fcf682010-07-03 11:09:06 +0200506
Max9943d7a2016-07-05 15:19:12 +0200507 if (acr->ac_ref_nr != ctx->ac_ref_nr_used) {
508 LOGMMCTXP(LOGL_NOTICE, ctx, "Reference mismatch for Auth & Ciph"
509 " Response: %u received, %u expected\n",
510 acr->ac_ref_nr, ctx->ac_ref_nr_used);
511 return 0;
512 }
513
Jacob Erlbeck4d127672014-12-01 12:33:33 +0100514 /* Stop T3360 */
515 mmctx_timer_stop(ctx, 3360);
Harald Welte45fcf682010-07-03 11:09:06 +0200516
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +0200517 tlv_parse(&tp, &gsm48_gmm_att_tlvdef, acr->data,
Harald Welte45fcf682010-07-03 11:09:06 +0200518 (msg->data + msg->len) - acr->data, 0, 0);
519
Harald Welte45fcf682010-07-03 11:09:06 +0200520 if (!TLVP_PRESENT(&tp, GSM48_IE_GMM_AUTH_SRES) ||
521 !TLVP_PRESENT(&tp, GSM48_IE_GMM_IMEISV)) {
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100522 /* TODO: missing mandatory IE, return STATUS or REJ? */
523 LOGMMCTXP(LOGL_ERROR, ctx, "Missing mandantory IE\n");
524 return -EINVAL;
Harald Welte45fcf682010-07-03 11:09:06 +0200525 }
526
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100527 /* Compare SRES with what we expected */
528 LOGMMCTXP(LOGL_DEBUG, ctx, "checking received auth info, SRES = %s\n",
529 osmo_hexdump(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES),
530 TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES)));
531
532 at = &ctx->auth_triplet;
533
Harald Welte34ef4c52016-04-20 13:13:19 +0200534 if (TLVP_LEN(&tp, GSM48_IE_GMM_AUTH_SRES) != sizeof(at->vec.sres) ||
535 memcmp(TLVP_VAL(&tp, GSM48_IE_GMM_AUTH_SRES), at->vec.sres,
536 sizeof(at->vec.sres)) != 0) {
Jacob Erlbeckc9cb9b02014-12-01 12:44:24 +0100537
538 LOGMMCTXP(LOGL_NOTICE, ctx, "Received SRES doesn't match\n");
539 rc = gsm48_tx_gmm_auth_ciph_rej(ctx);
540 mm_ctx_cleanup_free(ctx, "GPRS AUTH AND CIPH REJECT");
541 return rc;
542 }
543
544 ctx->is_authenticated = 1;
545
Harald Welte45fcf682010-07-03 11:09:06 +0200546 /* FIXME: enable LLC cipheirng */
Jacob Erlbeckac336982014-12-02 09:47:26 +0100547
548 /* Check if we can let the mobile station enter */
549 return gsm48_gmm_authorize(ctx);
Harald Welte45fcf682010-07-03 11:09:06 +0200550}
551
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +0200552static void extract_subscr_msisdn(struct sgsn_mm_ctx *ctx)
553{
554 struct gsm_mncc_number called;
555 uint8_t msisdn[sizeof(ctx->subscr->sgsn_data->msisdn) + 1];
556
557 /* Convert MSISDN from encoded to string.. */
558 if (!ctx->subscr)
559 return;
560
561 if (ctx->subscr->sgsn_data->msisdn_len < 1)
562 return;
563
564 /* prepare the data for the decoder */
565 memset(&called, 0, sizeof(called));
566 msisdn[0] = ctx->subscr->sgsn_data->msisdn_len;
567 memcpy(&msisdn[1], ctx->subscr->sgsn_data->msisdn,
568 ctx->subscr->sgsn_data->msisdn_len);
569
570 /* decode the string now */
571 gsm48_decode_called(&called, msisdn);
572
573 /* Prepend a '+' for international numbers */
574 if (called.plan == 1 && called.type == 1) {
575 ctx->msisdn[0] = '+';
576 strncpy(&ctx->msisdn[1], called.number,
577 sizeof(ctx->msisdn) - 1);
578 } else {
579 strncpy(&ctx->msisdn[0], called.number,
580 sizeof(ctx->msisdn) - 1);
581 }
582}
583
Holger Hans Peter Freyther8b2b5fb2015-05-18 10:00:03 +0200584static void extract_subscr_hlr(struct sgsn_mm_ctx *ctx)
585{
586 struct gsm_mncc_number called;
587 uint8_t hlr_number[sizeof(ctx->subscr->sgsn_data->hlr) + 1];
588
589 if (!ctx->subscr)
590 return;
591
592 if (ctx->subscr->sgsn_data->hlr_len < 1)
593 return;
594
595 /* prepare the data for the decoder */
596 memset(&called, 0, sizeof(called));
597 hlr_number[0] = ctx->subscr->sgsn_data->hlr_len;
598 memcpy(&hlr_number[1], ctx->subscr->sgsn_data->hlr,
599 ctx->subscr->sgsn_data->hlr_len);
600
601 /* decode the string now */
602 gsm48_decode_called(&called, hlr_number);
603
604 if (called.plan != 1) {
605 LOGMMCTXP(LOGL_ERROR, ctx,
606 "Numbering plan(%d) not allowed\n",
607 called.plan);
608 return;
609 }
610
611 if (called.type != 1) {
612 LOGMMCTXP(LOGL_ERROR, ctx,
613 "Numbering type(%d) not allowed\n",
614 called.type);
615 return;
616 }
617
618 strncpy(&ctx->hlr[0], called.number, sizeof(ctx->hlr) - 1);
619}
620
Harald Welte75bb8202010-03-14 15:45:01 +0800621/* Check if we can already authorize a subscriber */
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100622static int gsm48_gmm_authorize(struct sgsn_mm_ctx *ctx)
Harald Welte75bb8202010-03-14 15:45:01 +0800623{
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +0200624#ifndef PTMSI_ALLOC
625 struct sgsn_signal_data sig_data;
626#endif
627
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100628 /* Request IMSI and IMEI from the MS if they are unknown */
Harald Welte7e01d8e2010-05-31 20:23:38 +0200629 if (!strlen(ctx->imei)) {
Harald Welte7e01d8e2010-05-31 20:23:38 +0200630 ctx->t3370_id_type = GSM_MI_TYPE_IMEI;
Harald Welte9b57a3d2015-08-15 19:08:21 +0200631 mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
Harald Welte64df8ed2010-05-18 17:04:55 +0200632 return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMEI);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200633 }
Harald Welte7e01d8e2010-05-31 20:23:38 +0200634 if (!strlen(ctx->imsi)) {
Harald Welte7e01d8e2010-05-31 20:23:38 +0200635 ctx->t3370_id_type = GSM_MI_TYPE_IMSI;
Harald Welte9b57a3d2015-08-15 19:08:21 +0200636 mmctx_timer_start(ctx, 3370, sgsn->cfg.timers.T3370);
Harald Welte64df8ed2010-05-18 17:04:55 +0200637 return gsm48_tx_gmm_id_req(ctx, GSM_MI_TYPE_IMSI);
Harald Welte7e01d8e2010-05-31 20:23:38 +0200638 }
Harald Welte75bb8202010-03-14 15:45:01 +0800639
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100640 /* All information required for authentication is available */
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100641 ctx->t3370_id_type = GSM_MI_TYPE_NONE;
642
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200643 if (ctx->auth_state == SGSN_AUTH_UNKNOWN) {
644 /* Request authorization, this leads to a call to
Jacob Erlbeck802d78a2014-11-07 14:17:44 +0100645 * sgsn_auth_update which in turn calls
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200646 * gsm0408_gprs_access_granted or gsm0408_gprs_access_denied */
647
Jacob Erlbeckb2acd742014-11-13 10:48:39 +0100648 sgsn_auth_request(ctx);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200649 /* Note that gsm48_gmm_authorize can be called recursively via
650 * sgsn_auth_request iff ctx->auth_info changes to AUTH_ACCEPTED
651 */
652 return 0;
653 }
654
Jacob Erlbeckac336982014-12-02 09:47:26 +0100655 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && !ctx->is_authenticated) {
656 struct gsm_auth_tuple *at = &ctx->auth_triplet;
657
Harald Welte9b57a3d2015-08-15 19:08:21 +0200658 mmctx_timer_start(ctx, 3360, sgsn->cfg.timers.T3360);
Harald Welte34ef4c52016-04-20 13:13:19 +0200659 return gsm48_tx_gmm_auth_ciph_req(ctx, at->vec.rand,
Max6d999582016-07-06 15:57:01 +0200660 at->key_seq, false);
Jacob Erlbeckac336982014-12-02 09:47:26 +0100661 }
662
663 if (ctx->auth_state == SGSN_AUTH_AUTHENTICATE && ctx->is_authenticated &&
664 ctx->auth_triplet.key_seq != GSM_KEY_SEQ_INVAL) {
665 /* Check again for authorization */
666 sgsn_auth_request(ctx);
667 return 0;
668 }
669
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200670 if (ctx->auth_state != SGSN_AUTH_ACCEPTED) {
671 LOGMMCTXP(LOGL_NOTICE, ctx,
672 "authorization is denied, aborting procedure\n");
673 return -EACCES;
Jacob Erlbeck79d438a2014-10-29 22:12:20 +0100674 }
675
676 /* The MS is authorized */
677
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100678 switch (ctx->pending_req) {
679 case 0:
680 LOGMMCTXP(LOGL_INFO, ctx,
681 "no pending request, authorization completed\n");
682 break;
683 case GSM48_MT_GMM_ATTACH_REQ:
Holger Hans Peter Freythera9f671c2015-05-05 22:52:40 +0200684
685 extract_subscr_msisdn(ctx);
Holger Hans Peter Freyther8b2b5fb2015-05-18 10:00:03 +0200686 extract_subscr_hlr(ctx);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100687#ifdef PTMSI_ALLOC
688 /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
Harald Welte9b57a3d2015-08-15 19:08:21 +0200689 mmctx_timer_start(ctx, 3350, sgsn->cfg.timers.T3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100690 ctx->t3350_mode = GMM_T3350_MODE_ATT;
Jacob Erlbeck67318ef2014-10-28 16:23:46 +0100691#else
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +0200692 memset(&sig_data, 0, sizeof(sig_data));
693 sig_data.mm = mmctx;
694 osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
Jacob Erlbeck67318ef2014-10-28 16:23:46 +0100695 ctx->mm_state = GMM_REGISTERED_NORMAL;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100696#endif
697
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100698 return gsm48_tx_gmm_att_ack(ctx);
699 default:
700 LOGMMCTXP(LOGL_ERROR, ctx,
701 "only Attach Request is supported yet, "
702 "got request type %u\n", ctx->pending_req);
703 break;
704 }
705
Harald Welte75bb8202010-03-14 15:45:01 +0800706 return 0;
707}
708
Jacob Erlbeckac336982014-12-02 09:47:26 +0100709void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *ctx)
710{
711 ctx->is_authenticated = 0;
712
713 gsm48_gmm_authorize(ctx);
714}
715
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200716void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *ctx)
717{
718 switch (ctx->mm_state) {
719 case GMM_COMMON_PROC_INIT:
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200720 LOGMMCTXP(LOGL_NOTICE, ctx,
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200721 "Authorized, continuing procedure, IMSI=%s\n",
722 ctx->imsi);
723 /* Continue with the authorization */
724 gsm48_gmm_authorize(ctx);
725 break;
726 default:
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200727 LOGMMCTXP(LOGL_INFO, ctx,
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200728 "Authorized, ignored, IMSI=%s\n",
729 ctx->imsi);
730 }
731}
732
Jacob Erlbeck41010082015-01-05 17:51:17 +0100733void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *ctx, int gmm_cause)
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200734{
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100735 if (gmm_cause == SGSN_ERROR_CAUSE_NONE)
Jacob Erlbeck41010082015-01-05 17:51:17 +0100736 gmm_cause = GMM_CAUSE_GPRS_NOTALLOWED;
737
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200738 switch (ctx->mm_state) {
739 case GMM_COMMON_PROC_INIT:
Jacob Erlbeck41010082015-01-05 17:51:17 +0100740 LOGMMCTXP(LOGL_NOTICE, ctx,
741 "Not authorized, rejecting ATTACH REQUEST "
742 "with cause '%s' (%d)\n",
743 get_value_string(gsm48_gmm_cause_names, gmm_cause),
744 gmm_cause);
745 gsm48_tx_gmm_att_rej(ctx, gmm_cause);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200746 mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJECT");
747 break;
748 case GMM_REGISTERED_NORMAL:
749 case GMM_REGISTERED_SUSPENDED:
Jacob Erlbeck41010082015-01-05 17:51:17 +0100750 LOGMMCTXP(LOGL_NOTICE, ctx,
751 "Authorization lost, detaching "
752 "with cause '%s' (%d)\n",
753 get_value_string(gsm48_gmm_cause_names, gmm_cause),
754 gmm_cause);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200755 gsm48_tx_gmm_detach_req(
Jacob Erlbeck41010082015-01-05 17:51:17 +0100756 ctx, GPRS_DET_T_MT_REATT_NOTREQ, gmm_cause);
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200757
758 mm_ctx_cleanup_free(ctx, "auth lost");
759 break;
760 default:
Jacob Erlbeck41010082015-01-05 17:51:17 +0100761 LOGMMCTXP(LOGL_INFO, ctx,
762 "Authorization lost, cause is '%s' (%d)\n",
763 get_value_string(gsm48_gmm_cause_names, gmm_cause),
764 gmm_cause);
765 mm_ctx_cleanup_free(ctx, "auth lost");
Jacob Erlbeckc64af7a2014-10-24 18:09:54 +0200766 }
767}
768
Jacob Erlbeck41010082015-01-05 17:51:17 +0100769void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *ctx, int gmm_cause)
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +0100770{
Jacob Erlbeckf96779f2015-01-19 11:10:04 +0100771 if (gmm_cause != SGSN_ERROR_CAUSE_NONE) {
Jacob Erlbeck41010082015-01-05 17:51:17 +0100772 LOGMMCTXP(LOGL_INFO, ctx,
773 "Cancelled with cause '%s' (%d), deleting context\n",
774 get_value_string(gsm48_gmm_cause_names, gmm_cause),
775 gmm_cause);
776 gsm0408_gprs_access_denied(ctx, gmm_cause);
777 return;
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +0100778 }
Jacob Erlbeck41010082015-01-05 17:51:17 +0100779
780 LOGMMCTXP(LOGL_INFO, ctx, "Cancelled, deleting context silently\n");
Jacob Erlbeckbf0b8742014-11-11 14:47:38 +0100781 mm_ctx_cleanup_free(ctx, "access cancelled");
782}
783
Harald Welte75bb8202010-03-14 15:45:01 +0800784/* Parse Chapter 9.4.13 Identity Response */
Harald Weltec1f6bfe2010-05-17 22:58:03 +0200785static int gsm48_rx_gmm_id_resp(struct sgsn_mm_ctx *ctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +0800786{
Harald Weltecf3c4142010-04-30 16:33:12 +0200787 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welted85d9a92010-05-02 11:26:34 +0200788 uint8_t mi_type = gh->data[1] & GSM_MI_TYPE_MASK;
Harald Welte75bb8202010-03-14 15:45:01 +0800789 char mi_string[GSM48_MI_SIZE];
Harald Welte75bb8202010-03-14 15:45:01 +0800790
791 gsm48_mi_to_string(mi_string, sizeof(mi_string), &gh->data[1], gh->data[0]);
Harald Welte75bb8202010-03-14 15:45:01 +0800792 if (!ctx) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200793 DEBUGP(DMM, "from unknown TLLI 0x%08x?!? This should not happen\n", msgb_tlli(msg));
Harald Welte75bb8202010-03-14 15:45:01 +0800794 return -EINVAL;
795 }
796
Harald Welte7e3e9332015-08-16 18:07:48 +0200797 LOGMMCTXP(LOGL_DEBUG, ctx, "-> GMM IDENTITY RESPONSE: MI(%s)=%s\n",
798 gsm48_mi_type_name(mi_type), mi_string);
Daniel Willmann09827d52014-09-23 18:48:44 +0200799
Jacob Erlbeck5233c0c2014-10-22 12:20:26 +0200800 if (ctx->t3370_id_type == GSM_MI_TYPE_NONE) {
801 LOGMMCTXP(LOGL_NOTICE, ctx,
Harald Welte7e3e9332015-08-16 18:07:48 +0200802 "Got unexpected IDENTITY RESPONSE: MI(%s)=%s, "
Jacob Erlbeck5233c0c2014-10-22 12:20:26 +0200803 "ignoring message\n",
Harald Welte7e3e9332015-08-16 18:07:48 +0200804 gsm48_mi_type_name(mi_type), mi_string);
Jacob Erlbeck5233c0c2014-10-22 12:20:26 +0200805 return -EINVAL;
806 }
807
Harald Welte7e01d8e2010-05-31 20:23:38 +0200808 if (mi_type == ctx->t3370_id_type)
809 mmctx_timer_stop(ctx, 3370);
810
Harald Welte75bb8202010-03-14 15:45:01 +0800811 switch (mi_type) {
812 case GSM_MI_TYPE_IMSI:
813 /* we already have a mm context with current TLLI, but no
814 * P-TMSI / IMSI yet. What we now need to do is to fill
815 * this initial context with data from the HLR */
Harald Weltec6e196f2010-12-24 23:07:18 +0100816 if (strlen(ctx->imsi) == 0) {
817 /* Check if we already have a MM context for this IMSI */
818 struct sgsn_mm_ctx *ictx;
819 ictx = sgsn_mm_ctx_by_imsi(mi_string);
820 if (ictx) {
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200821 /* Handle it like in gsm48_rx_gmm_det_req,
822 * except that no messages are sent to the BSS */
823
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200824 LOGMMCTXP(LOGL_NOTICE, ctx, "Deleting old MM Context for same IMSI "
825 "p_tmsi_old=0x%08x\n",
826 ictx->p_tmsi);
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200827
Jacob Erlbeckd781c7a2014-10-13 10:32:00 +0200828 mm_ctx_cleanup_free(ictx, "GPRS IMSI re-use");
Harald Weltec6e196f2010-12-24 23:07:18 +0100829 }
830 }
Jacob Erlbeckb485ee92015-01-26 10:38:12 +0100831 strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi) - 1);
Harald Welte75bb8202010-03-14 15:45:01 +0800832 break;
833 case GSM_MI_TYPE_IMEI:
Jacob Erlbeckb485ee92015-01-26 10:38:12 +0100834 strncpy(ctx->imei, mi_string, sizeof(ctx->imei) - 1);
Harald Welte75bb8202010-03-14 15:45:01 +0800835 break;
836 case GSM_MI_TYPE_IMEISV:
837 break;
838 }
839
Harald Welte75bb8202010-03-14 15:45:01 +0800840 /* Check if we can let the mobile station enter */
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100841 return gsm48_gmm_authorize(ctx);
Harald Welte75bb8202010-03-14 15:45:01 +0800842}
843
844/* Section 9.4.1 Attach request */
Harald Welte75871c72010-06-01 11:53:01 +0200845static int gsm48_rx_gmm_att_req(struct sgsn_mm_ctx *ctx, struct msgb *msg,
846 struct gprs_llc_llme *llme)
Harald Welte75bb8202010-03-14 15:45:01 +0800847{
Harald Weltecf3c4142010-04-30 16:33:12 +0200848 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +0200849 uint8_t *cur = gh->data, *msnc, *mi, *ms_ra_acc_cap;
Harald Weltecca80c92010-05-31 22:12:30 +0200850 uint8_t msnc_len, att_type, mi_len, mi_type, ms_ra_acc_cap_len;
Harald Welted85d9a92010-05-02 11:26:34 +0200851 uint16_t drx_par;
852 uint32_t tmsi;
Harald Welte75bb8202010-03-14 15:45:01 +0800853 char mi_string[GSM48_MI_SIZE];
854 struct gprs_ra_id ra_id;
Harald Weltede34afa2010-05-02 12:56:57 +0200855 uint16_t cid;
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +0100856 enum gsm48_gmm_cause reject_cause;
857 int rc;
Harald Welte75bb8202010-03-14 15:45:01 +0800858
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200859 LOGMMCTXP(LOGL_INFO, ctx, "-> GMM ATTACH REQUEST ");
Alexander Couzens32fdba02016-07-05 09:52:52 +0200860 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ATTACH_REQUEST]);
Harald Welte75bb8202010-03-14 15:45:01 +0800861
862 /* As per TS 04.08 Chapter 4.7.1.4, the attach request arrives either
863 * with a foreign TLLI (P-TMSI that was allocated to the MS before),
864 * or with random TLLI. */
865
Harald Weltede34afa2010-05-02 12:56:57 +0200866 cid = bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
Harald Welte75bb8202010-03-14 15:45:01 +0800867
868 /* MS network capability 10.5.5.12 */
869 msnc_len = *cur++;
870 msnc = cur;
Alexander Chemeris6824c502013-07-03 10:12:23 +0400871 if (msnc_len > sizeof(ctx->ms_network_capa.buf))
Harald Welte75bb8202010-03-14 15:45:01 +0800872 goto err_inval;
873 cur += msnc_len;
874
875 /* aTTACH Type 10.5.5.2 */
876 att_type = *cur++ & 0x0f;
877
878 /* DRX parameter 10.5.5.6 */
Harald Weltecca80c92010-05-31 22:12:30 +0200879 drx_par = *cur++ << 8;
880 drx_par |= *cur++;
Harald Welte75bb8202010-03-14 15:45:01 +0800881
882 /* Mobile Identity (P-TMSI or IMSI) 10.5.1.4 */
883 mi_len = *cur++;
884 mi = cur;
885 if (mi_len > 8)
886 goto err_inval;
887 mi_type = *mi & GSM_MI_TYPE_MASK;
888 cur += mi_len;
889
890 gsm48_mi_to_string(mi_string, sizeof(mi_string), mi, mi_len);
891
Harald Welte8f77f192010-05-17 00:44:57 +0200892 DEBUGPC(DMM, "MI(%s) type=\"%s\" ", mi_string,
893 get_value_string(gprs_att_t_strs, att_type));
Harald Welte75bb8202010-03-14 15:45:01 +0800894
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +0200895 /* Old routing area identification 10.5.5.15. Skip it */
Harald Welte75bb8202010-03-14 15:45:01 +0800896 cur += 6;
897
898 /* MS Radio Access Capability 10.5.5.12a */
Harald Weltecca80c92010-05-31 22:12:30 +0200899 ms_ra_acc_cap_len = *cur++;
900 ms_ra_acc_cap = cur;
Alexander Chemeris6824c502013-07-03 10:12:23 +0400901 if (ms_ra_acc_cap_len > sizeof(ctx->ms_radio_access_capa.buf))
Harald Welteabe06132010-07-03 21:20:06 +0200902 goto err_inval;
Harald Welte45ca5522011-07-27 23:35:38 +0200903 cur += ms_ra_acc_cap_len;
Harald Welte75bb8202010-03-14 15:45:01 +0800904
Daniel Willmannc9ac9732014-09-03 17:46:44 +0200905 LOGPC(DMM, LOGL_INFO, "\n");
906
Harald Welte75bb8202010-03-14 15:45:01 +0800907 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status */
908
909 switch (mi_type) {
910 case GSM_MI_TYPE_IMSI:
911 /* Try to find MM context based on IMSI */
Harald Welte75871c72010-06-01 11:53:01 +0200912 if (!ctx)
913 ctx = sgsn_mm_ctx_by_imsi(mi_string);
Harald Welte75bb8202010-03-14 15:45:01 +0800914 if (!ctx) {
915#if 0
916 return gsm48_tx_gmm_att_rej(msg, GMM_CAUSE_IMSI_UNKNOWN);
917#else
Harald Welte75bb8202010-03-14 15:45:01 +0800918 ctx = sgsn_mm_ctx_alloc(0, &ra_id);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +0100919 if (!ctx) {
920 reject_cause = GMM_CAUSE_NET_FAIL;
921 goto rejected;
922 }
Jacob Erlbeckb485ee92015-01-26 10:38:12 +0100923 strncpy(ctx->imsi, mi_string, sizeof(ctx->imsi) - 1);
Harald Welte75bb8202010-03-14 15:45:01 +0800924#endif
925 }
Harald Welte15487002015-12-25 22:23:27 +0100926 if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
927 ctx->gb.tlli = msgb_tlli(msg);
928 ctx->gb.llme = llme;
929 }
Harald Welte5c23bfc2010-05-18 12:05:42 +0200930 msgid2mmctx(ctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +0800931 break;
932 case GSM_MI_TYPE_TMSI:
Harald Welteebe8a6d2010-05-18 19:58:38 +0200933 memcpy(&tmsi, mi+1, 4);
934 tmsi = ntohl(tmsi);
Harald Welte75bb8202010-03-14 15:45:01 +0800935 /* Try to find MM context based on P-TMSI */
Harald Welte75871c72010-06-01 11:53:01 +0200936 if (!ctx)
937 ctx = sgsn_mm_ctx_by_ptmsi(tmsi);
Harald Welte75bb8202010-03-14 15:45:01 +0800938 if (!ctx) {
Harald Weltec6e196f2010-12-24 23:07:18 +0100939 /* Allocate a context as most of our code expects one.
940 * Context will not have an IMSI ultil ID RESP is received */
Harald Weltecf3c4142010-04-30 16:33:12 +0200941 ctx = sgsn_mm_ctx_alloc(msgb_tlli(msg), &ra_id);
Harald Welte75871c72010-06-01 11:53:01 +0200942 ctx->p_tmsi = tmsi;
Harald Welte75bb8202010-03-14 15:45:01 +0800943 }
Harald Welte15487002015-12-25 22:23:27 +0100944 if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
945 ctx->gb.tlli = msgb_tlli(msg);
946 ctx->gb.llme = llme;
947 }
Harald Welte75871c72010-06-01 11:53:01 +0200948 msgid2mmctx(ctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +0800949 break;
950 default:
Harald Weltebdeaf5f2015-08-16 17:11:32 +0200951 LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with "
Harald Welte7e3e9332015-08-16 18:07:48 +0200952 "MI type %s\n", gsm48_mi_type_name(mi_type));
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +0100953 reject_cause = GMM_CAUSE_MS_ID_NOT_DERIVED;
954 goto rejected;
Harald Welte75bb8202010-03-14 15:45:01 +0800955 }
Harald Weltede34afa2010-05-02 12:56:57 +0200956 /* Update MM Context with currient RA and Cell ID */
957 ctx->ra = ra_id;
Harald Welte15487002015-12-25 22:23:27 +0100958 if (ctx->ran_type == MM_CTX_T_GERAN_Gb)
959 ctx->gb.cell_id = cid;
Harald Weltecca80c92010-05-31 22:12:30 +0200960 /* Update MM Context with other data */
961 ctx->drx_parms = drx_par;
Alexander Chemeris6824c502013-07-03 10:12:23 +0400962 ctx->ms_radio_access_capa.len = ms_ra_acc_cap_len;
Harald Welte45ca5522011-07-27 23:35:38 +0200963 memcpy(ctx->ms_radio_access_capa.buf, ms_ra_acc_cap,
964 ctx->ms_radio_access_capa.len);
Harald Weltecca80c92010-05-31 22:12:30 +0200965 ctx->ms_network_capa.len = msnc_len;
966 memcpy(ctx->ms_network_capa.buf, msnc, msnc_len);
Max6d999582016-07-06 15:57:01 +0200967 if (!gprs_ms_net_cap_gea_supported(ctx->ms_network_capa.buf, msnc_len,
968 ctx->ciph_algo)) {
969 reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
970 LOGMMCTXP(LOGL_NOTICE, ctx, "Rejecting ATTACH REQUEST with MI "
971 "type %s because MS do not support required %s "
972 "encryption\n", gsm48_mi_type_name(mi_type),
973 get_value_string(gprs_cipher_names,ctx->ciph_algo));
974 goto rejected;
975 }
Harald Welte7e01d8e2010-05-31 20:23:38 +0200976#ifdef PTMSI_ALLOC
Harald Welte75871c72010-06-01 11:53:01 +0200977 /* Allocate a new P-TMSI (+ P-TMSI signature) and update TLLI */
Jacob Erlbecke06476a2014-11-06 15:43:10 +0100978 /* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
979 if (ctx->mm_state != GMM_COMMON_PROC_INIT) {
980 ctx->p_tmsi_old = ctx->p_tmsi;
981 ctx->p_tmsi = sgsn_alloc_ptmsi();
982 }
Jacob Erlbeck67318ef2014-10-28 16:23:46 +0100983 ctx->mm_state = GMM_COMMON_PROC_INIT;
Harald Welteebe8a6d2010-05-18 19:58:38 +0200984#endif
Harald Welte75871c72010-06-01 11:53:01 +0200985
Harald Welte15487002015-12-25 22:23:27 +0100986 if (ctx->ran_type == MM_CTX_T_GERAN_Gb) {
987 /* Even if there is no P-TMSI allocated, the MS will
988 * switch from foreign TLLI to local TLLI */
989 ctx->gb.tlli_new = gprs_tmsi2tlli(ctx->p_tmsi, TLLI_LOCAL);
990
991 /* Inform LLC layer about new TLLI but keep old active */
Maxeb64e3f2016-07-06 11:33:04 +0200992 if (ctx->is_authenticated)
993 gprs_llme_copy_key(ctx, ctx->gb.llme);
994
995 gprs_llgmm_assign(ctx->gb.llme, ctx->gb.tlli, ctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +0100996 }
Harald Welte75bb8202010-03-14 15:45:01 +0800997
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +0100998 ctx->pending_req = GSM48_MT_GMM_ATTACH_REQ;
999 return gsm48_gmm_authorize(ctx);
Harald Welte75bb8202010-03-14 15:45:01 +08001000
1001err_inval:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001002 LOGPC(DMM, LOGL_INFO, "\n");
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001003 reject_cause = GMM_CAUSE_SEM_INCORR_MSG;
1004
1005rejected:
1006 /* Send ATTACH REJECT */
1007 LOGMMCTXP(LOGL_NOTICE, ctx,
1008 "Rejecting Attach Request with cause '%s' (%d)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01001009 get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001010 rc = gsm48_tx_gmm_att_rej_oldmsg(msg, reject_cause);
1011 if (ctx)
1012 mm_ctx_cleanup_free(ctx, "GPRS ATTACH REJ");
1013 else
Maxa86f5c02016-06-28 17:39:20 +02001014 gprs_llgmm_unassign(llme);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001015
1016 return rc;
1017
Harald Welte75bb8202010-03-14 15:45:01 +08001018}
1019
Harald Welte8f77f192010-05-17 00:44:57 +02001020/* Section 4.7.4.1 / 9.4.5.2 MO Detach request */
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001021static int gsm48_rx_gmm_det_req(struct sgsn_mm_ctx *ctx, struct msgb *msg)
Harald Welte8f77f192010-05-17 00:44:57 +02001022{
1023 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte8f77f192010-05-17 00:44:57 +02001024 uint8_t detach_type, power_off;
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001025 int rc = 0;
Harald Welte8f77f192010-05-17 00:44:57 +02001026
1027 detach_type = gh->data[0] & 0x7;
1028 power_off = gh->data[0] & 0x8;
1029
1030 /* FIXME: In 24.008 there is an optional P-TMSI and P-TMSI signature IE */
Alexander Couzens32fdba02016-07-05 09:52:52 +02001031 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_DETACH_REQUEST]);
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001032 LOGMMCTXP(LOGL_INFO, ctx, "-> GMM DETACH REQUEST TLLI=0x%08x type=%s %s\n",
Harald Welte8f77f192010-05-17 00:44:57 +02001033 msgb_tlli(msg), get_value_string(gprs_det_t_mo_strs, detach_type),
1034 power_off ? "Power-off" : "");
1035
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001036 /* Only send the Detach Accept (MO) if power off isn't indicated,
Jacob Erlbeck97ee3762014-10-21 09:52:05 +02001037 * see 04.08, 4.7.4.1.2/3 for details */
1038 if (!power_off) {
1039 /* force_stby = 0 */
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001040 if (ctx)
1041 rc = gsm48_tx_gmm_det_ack(ctx, 0);
1042 else
1043 rc = gsm48_tx_gmm_det_ack_oldmsg(msg, 0);
Jacob Erlbeck97ee3762014-10-21 09:52:05 +02001044 }
Harald Welte309b5932010-06-28 22:18:53 +02001045
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001046 if (ctx) {
1047 struct sgsn_signal_data sig_data;
1048 memset(&sig_data, 0, sizeof(sig_data));
1049 sig_data.mm = ctx;
1050 osmo_signal_dispatch(SS_SGSN, S_SGSN_DETACH, &sig_data);
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001051 mm_ctx_cleanup_free(ctx, "GPRS DETACH REQUEST");
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001052 }
Jacob Erlbeck12396bd2014-09-30 13:51:45 +02001053
Harald Welte309b5932010-06-28 22:18:53 +02001054 return rc;
Harald Welte8f77f192010-05-17 00:44:57 +02001055}
1056
Harald Welte75bb8202010-03-14 15:45:01 +08001057/* Chapter 9.4.15: Routing area update accept */
Harald Welte64df8ed2010-05-18 17:04:55 +02001058static int gsm48_tx_gmm_ra_upd_ack(struct sgsn_mm_ctx *mm)
Harald Welte75bb8202010-03-14 15:45:01 +08001059{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001060 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 UPD ACK");
Harald Welte75bb8202010-03-14 15:45:01 +08001061 struct gsm48_hdr *gh;
1062 struct gsm48_ra_upd_ack *rua;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001063 uint8_t *mid;
Harald Welte75bb8202010-03-14 15:45:01 +08001064
Alexander Couzens32fdba02016-07-05 09:52:52 +02001065 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_ACKED]);
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001066 LOGMMCTXP(LOGL_INFO, mm, "<- ROUTING AREA UPDATE ACCEPT\n");
Harald Welte75bb8202010-03-14 15:45:01 +08001067
Harald Welte64df8ed2010-05-18 17:04:55 +02001068 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +08001069
1070 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1071 gh->proto_discr = GSM48_PDISC_MM_GPRS;
1072 gh->msg_type = GSM48_MT_GMM_RA_UPD_ACK;
1073
1074 rua = (struct gsm48_ra_upd_ack *) msgb_put(msg, sizeof(*rua));
1075 rua->force_stby = 0; /* not indicated */
1076 rua->upd_result = 0; /* RA updated */
Harald Welte9b57a3d2015-08-15 19:08:21 +02001077 rua->ra_upd_timer = gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3312);
Harald Welte2351f1f2010-05-02 11:54:55 +02001078
Harald Welte64df8ed2010-05-18 17:04:55 +02001079 gsm48_construct_ra(rua->ra_id.digits, &mm->ra);
Harald Welte75bb8202010-03-14 15:45:01 +08001080
Harald Welte7e01d8e2010-05-31 20:23:38 +02001081#if 0
1082 /* Optional: P-TMSI signature */
1083 msgb_v_put(msg, GSM48_IE_GMM_PTMSI_SIG);
1084 ptsig = msgb_put(msg, 3);
1085 ptsig[0] = mm->p_tmsi_sig >> 16;
1086 ptsig[1] = mm->p_tmsi_sig >> 8;
1087 ptsig[2] = mm->p_tmsi_sig & 0xff;
1088#endif
1089
1090#ifdef PTMSI_ALLOC
1091 /* Optional: Allocated P-TMSI */
1092 mid = msgb_put(msg, GSM48_MID_TMSI_LEN);
1093 gsm48_generate_mid_from_tmsi(mid, mm->p_tmsi);
1094 mid[0] = GSM48_IE_GMM_ALLOC_PTMSI;
1095#endif
1096
Jacob Erlbeck1063ae02015-01-23 11:44:39 +01001097 /* Optional: Negotiated READY timer value */
1098 msgb_tv_put(msg, GSM48_IE_GMM_TIMER_READY,
Harald Welte9b57a3d2015-08-15 19:08:21 +02001099 gprs_secs_to_tmr_floor(sgsn->cfg.timers.T3314));
Jacob Erlbeck1063ae02015-01-23 11:44:39 +01001100
Harald Welte7e01d8e2010-05-31 20:23:38 +02001101 /* Option: MS ID, ... */
Max4bc28212016-07-06 11:59:18 +02001102 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte75bb8202010-03-14 15:45:01 +08001103}
1104
1105/* Chapter 9.4.17: Routing area update reject */
Harald Welted85d9a92010-05-02 11:26:34 +02001106static int gsm48_tx_gmm_ra_upd_rej(struct msgb *old_msg, uint8_t cause)
Harald Welte75bb8202010-03-14 15:45:01 +08001107{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001108 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 RA UPD REJ");
Harald Welte75bb8202010-03-14 15:45:01 +08001109 struct gsm48_hdr *gh;
1110
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001111 LOGP(DMM, LOGL_NOTICE, "<- ROUTING AREA UPDATE REJECT\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02001112 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_REJECT]);
Harald Welte75bb8202010-03-14 15:45:01 +08001113
Harald Welte2351f1f2010-05-02 11:54:55 +02001114 gmm_copy_id(msg, old_msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001115
1116 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 2);
1117 gh->proto_discr = GSM48_PDISC_MM_GPRS;
1118 gh->msg_type = GSM48_MT_GMM_RA_UPD_REJ;
1119 gh->data[0] = cause;
1120 gh->data[1] = 0; /* ? */
1121
1122 /* Option: P-TMSI signature, allocated P-TMSI, MS ID, ... */
Max4bc28212016-07-06 11:59:18 +02001123 return gsm48_gmm_sendmsg(msg, 0, NULL, false);
Harald Welte75bb8202010-03-14 15:45:01 +08001124}
1125
Harald Welted9610722010-06-09 10:28:29 +02001126static void process_ms_ctx_status(struct sgsn_mm_ctx *mmctx,
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001127 const uint8_t *pdp_status)
Harald Welted9610722010-06-09 10:28:29 +02001128{
1129 struct sgsn_pdp_ctx *pdp, *pdp2;
1130 /* 24.008 4.7.5.1.3: If the PDP context status information element is
1131 * included in ROUTING AREA UPDATE REQUEST message, then the network
1132 * shall deactivate all those PDP contexts locally (without peer to
1133 * peer signalling between the MS and the network), which are not in SM
1134 * state PDP-INACTIVE on network side but are indicated by the MS as
1135 * being in state PDP-INACTIVE. */
1136
1137 llist_for_each_entry_safe(pdp, pdp2, &mmctx->pdp_list, list) {
Harald Welte9e7093c2011-08-05 21:23:46 +02001138 if (pdp->nsapi < 8) {
1139 if (!(pdp_status[0] & (1 << pdp->nsapi))) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001140 LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for NSAPI=%u "
Harald Welte9e7093c2011-08-05 21:23:46 +02001141 "due to PDP CTX STATUS IE= 0x%02x%02x\n",
1142 pdp->nsapi, pdp_status[1], pdp_status[0]);
1143 sgsn_delete_pdp_ctx(pdp);
1144 }
1145 } else {
1146 if (!(pdp_status[1] & (1 << (pdp->nsapi - 8)))) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001147 LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping PDP context for NSAPI=%u "
Harald Welte9e7093c2011-08-05 21:23:46 +02001148 "due to PDP CTX STATUS IE= 0x%02x%02x\n",
1149 pdp->nsapi, pdp_status[1], pdp_status[0]);
1150 sgsn_delete_pdp_ctx(pdp);
1151 }
Harald Welted9610722010-06-09 10:28:29 +02001152 }
1153 }
1154}
1155
Harald Welte75bb8202010-03-14 15:45:01 +08001156/* Chapter 9.4.14: Routing area update request */
Harald Welte75871c72010-06-01 11:53:01 +02001157static int gsm48_rx_gmm_ra_upd_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
1158 struct gprs_llc_llme *llme)
Harald Welte75bb8202010-03-14 15:45:01 +08001159{
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001160#ifndef PTMSI_ALLOC
1161 struct sgsn_signal_data sig_data;
1162#endif
Harald Weltecf3c4142010-04-30 16:33:12 +02001163 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welted85d9a92010-05-02 11:26:34 +02001164 uint8_t *cur = gh->data;
Harald Welted9610722010-06-09 10:28:29 +02001165 uint8_t ms_ra_acc_cap_len;
Harald Welte75bb8202010-03-14 15:45:01 +08001166 struct gprs_ra_id old_ra_id;
Harald Welted9610722010-06-09 10:28:29 +02001167 struct tlv_parsed tp;
Harald Welted85d9a92010-05-02 11:26:34 +02001168 uint8_t upd_type;
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001169 enum gsm48_gmm_cause reject_cause;
1170 int rc;
Harald Welte75bb8202010-03-14 15:45:01 +08001171
1172 /* Update Type 10.5.5.18 */
1173 upd_type = *cur++ & 0x0f;
1174
Alexander Couzens32fdba02016-07-05 09:52:52 +02001175 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_GPRS_ROUTING_AREA_REQUEST]);
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001176 LOGP(DMM, LOGL_INFO, "-> GMM RA UPDATE REQUEST type=\"%s\"\n",
Harald Welte8f77f192010-05-17 00:44:57 +02001177 get_value_string(gprs_upd_t_strs, upd_type));
Harald Welte75bb8202010-03-14 15:45:01 +08001178
1179 /* Old routing area identification 10.5.5.15 */
1180 gsm48_parse_ra(&old_ra_id, cur);
1181 cur += 6;
1182
1183 /* MS Radio Access Capability 10.5.5.12a */
Harald Welted9610722010-06-09 10:28:29 +02001184 ms_ra_acc_cap_len = *cur++;
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001185 if (ms_ra_acc_cap_len > 52) {
1186 reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
1187 goto rejected;
1188 }
Harald Welte45ca5522011-07-27 23:35:38 +02001189 cur += ms_ra_acc_cap_len;
Harald Welte75bb8202010-03-14 15:45:01 +08001190
1191 /* Optional: Old P-TMSI Signature, Requested READY timer, TMSI Status,
1192 * DRX parameter, MS network capability */
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02001193 tlv_parse(&tp, &gsm48_gmm_att_tlvdef, cur,
Harald Welted9610722010-06-09 10:28:29 +02001194 (msg->data + msg->len) - cur, 0, 0);
Harald Welte75bb8202010-03-14 15:45:01 +08001195
1196 switch (upd_type) {
1197 case GPRS_UPD_T_RA_LA:
1198 case GPRS_UPD_T_RA_LA_IMSI_ATT:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001199 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 +01001200 reject_cause = GMM_CAUSE_PROTO_ERR_UNSPEC;
1201 goto rejected;
Harald Welte75bb8202010-03-14 15:45:01 +08001202 case GPRS_UPD_T_RA:
1203 case GPRS_UPD_T_PERIODIC:
1204 break;
1205 }
1206
Jacob Erlbecke437e122016-01-04 18:43:36 +01001207 if (!mmctx) {
1208 /* BSSGP doesn't give us an mmctx */
1209
1210 /* TODO: Check if there is an MM CTX with old_ra_id and
1211 * the P-TMSI (if given, reguired for UMTS) or as last resort
1212 * if the TLLI matches foreign_tlli (P-TMSI). Note that this
1213 * is an optimization to avoid the RA reject (impl detached)
1214 * below, which will cause a new attach cycle. */
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001215 /* Look-up the MM context based on old RA-ID and TLLI */
1216 mmctx = sgsn_mm_ctx_by_tlli_and_ptmsi(msgb_tlli(msg), &old_ra_id);
1217 if (mmctx) {
1218 LOGMMCTXP(LOGL_INFO, mmctx,
1219 "Looked up by matching TLLI and P_TMSI. "
1220 "BSSGP TLLI: %08x, P-TMSI: %08x (%08x), "
1221 "TLLI: %08x (%08x), RA: %d-%d-%d-%d\n",
1222 msgb_tlli(msg),
1223 mmctx->p_tmsi, mmctx->p_tmsi_old,
Harald Weltec28dc2f2015-12-25 19:12:21 +01001224 mmctx->gb.tlli, mmctx->gb.tlli_new,
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001225 mmctx->ra.mcc, mmctx->ra.mnc,
1226 mmctx->ra.lac, mmctx->ra.rac);
Jacob Erlbecke437e122016-01-04 18:43:36 +01001227
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001228 mmctx->mm_state = GMM_COMMON_PROC_INIT;
1229 }
1230 } else if (!gprs_ra_id_equals(&mmctx->ra, &old_ra_id) ||
Jacob Erlbecke437e122016-01-04 18:43:36 +01001231 mmctx->mm_state == GMM_DEREGISTERED)
1232 {
1233 /* We cannot use the mmctx */
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001234 LOGMMCTXP(LOGL_INFO, mmctx,
1235 "The MM context cannot be used, RA: %d-%d-%d-%d\n",
1236 mmctx->ra.mcc, mmctx->ra.mnc,
1237 mmctx->ra.lac, mmctx->ra.rac);
1238 mmctx = NULL;
1239 }
Jacob Erlbecke437e122016-01-04 18:43:36 +01001240
Jacob Erlbeck556aa912016-01-04 18:43:38 +01001241 if (!mmctx) {
Harald Welte95de4d52015-12-25 22:31:36 +01001242 if (llme) {
1243 /* send a XID reset to re-set all LLC sequence numbers
1244 * in the MS */
1245 LOGMMCTXP(LOGL_NOTICE, mmctx, "LLC XID RESET\n");
1246 gprs_llgmm_reset(llme);
1247 }
Harald Welte75bb8202010-03-14 15:45:01 +08001248 /* The MS has to perform GPRS attach */
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001249 /* Device is still IMSI attached for CS but initiate GPRS ATTACH,
1250 * see GSM 04.08, 4.7.5.1.4 and G.6 */
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001251 reject_cause = GMM_CAUSE_IMPL_DETACHED;
1252 goto rejected;
Harald Welte75bb8202010-03-14 15:45:01 +08001253 }
1254
Harald Welte66d062a2010-12-26 10:39:26 +01001255 /* Store new BVCI/NSEI in MM context (FIXME: delay until we ack?) */
1256 msgid2mmctx(mmctx, msg);
1257 /* Bump the statistics of received signalling msgs for this MM context */
1258 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
1259
Harald Weltede34afa2010-05-02 12:56:57 +02001260 /* Update the MM context with the new RA-ID */
Harald Welte15487002015-12-25 22:23:27 +01001261 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
Daniel Willmann711adc22016-05-20 22:36:23 +02001262 bssgp_parse_cell_id(&mmctx->ra, msgb_bcid(msg));
Harald Welte15487002015-12-25 22:23:27 +01001263 /* Update the MM context with the new (i.e. foreign) TLLI */
1264 mmctx->gb.tlli = msgb_tlli(msg);
1265 }
Harald Welte75bb8202010-03-14 15:45:01 +08001266 /* FIXME: Update the MM context with the MS radio acc capabilities */
1267 /* FIXME: Update the MM context with the MS network capabilities */
1268
Harald Welteeb471c92010-05-18 14:32:29 +02001269 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_RA_UPDATE]);
1270
Harald Welte7e01d8e2010-05-31 20:23:38 +02001271#ifdef PTMSI_ALLOC
Jacob Erlbecke06476a2014-11-06 15:43:10 +01001272 /* Don't change the P-TMSI if a P-TMSI re-assignment is under way */
1273 if (mmctx->mm_state != GMM_COMMON_PROC_INIT) {
1274 mmctx->p_tmsi_old = mmctx->p_tmsi;
1275 mmctx->p_tmsi = sgsn_alloc_ptmsi();
1276 }
Harald Welte7e01d8e2010-05-31 20:23:38 +02001277 /* Start T3350 and re-transmit up to 5 times until ATTACH COMPLETE */
1278 mmctx->t3350_mode = GMM_T3350_MODE_RAU;
Harald Welte9b57a3d2015-08-15 19:08:21 +02001279 mmctx_timer_start(mmctx, 3350, sgsn->cfg.timers.T3350);
Jacob Erlbeck67318ef2014-10-28 16:23:46 +01001280
1281 mmctx->mm_state = GMM_COMMON_PROC_INIT;
1282#else
1283 /* Make sure we are NORMAL (i.e. not SUSPENDED anymore) */
1284 mmctx->mm_state = GMM_REGISTERED_NORMAL;
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001285
1286 memset(&sig_data, 0, sizeof(sig_data));
1287 sig_data.mm = mmctx;
1288 osmo_signal_dispatch(SS_SGSN, S_SGSN_UPDATE, &sig_data);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001289#endif
Harald Welte15487002015-12-25 22:23:27 +01001290 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1291 /* Even if there is no P-TMSI allocated, the MS will switch from
1292 * foreign TLLI to local TLLI */
1293 mmctx->gb.tlli_new = gprs_tmsi2tlli(mmctx->p_tmsi, TLLI_LOCAL);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001294
Harald Welte15487002015-12-25 22:23:27 +01001295 /* Inform LLC layer about new TLLI but keep old active */
1296 gprs_llgmm_assign(mmctx->gb.llme, mmctx->gb.tlli,
Maxeb64e3f2016-07-06 11:33:04 +02001297 mmctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001298 }
Harald Welte75871c72010-06-01 11:53:01 +02001299
Harald Welted9610722010-06-09 10:28:29 +02001300 /* Look at PDP Context Status IE and see if MS's view of
1301 * activated/deactivated NSAPIs agrees with our view */
1302 if (TLVP_PRESENT(&tp, GSM48_IE_GMM_PDP_CTX_STATUS)) {
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001303 const uint8_t *pdp_status = TLVP_VAL(&tp, GSM48_IE_GMM_PDP_CTX_STATUS);
Harald Welted9610722010-06-09 10:28:29 +02001304 process_ms_ctx_status(mmctx, pdp_status);
1305 }
1306
Harald Welte75871c72010-06-01 11:53:01 +02001307 /* Send RA UPDATE ACCEPT */
Harald Welte64df8ed2010-05-18 17:04:55 +02001308 return gsm48_tx_gmm_ra_upd_ack(mmctx);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001309
1310rejected:
1311 /* Send RA UPDATE REJECT */
1312 LOGMMCTXP(LOGL_NOTICE, mmctx,
1313 "Rejecting RA Update Request with cause '%s' (%d)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01001314 get_value_string(gsm48_gmm_cause_names, reject_cause), reject_cause);
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001315 rc = gsm48_tx_gmm_ra_upd_rej(msg, reject_cause);
1316 if (mmctx)
1317 mm_ctx_cleanup_free(mmctx, "GPRS RA UPDATE REJ");
Harald Welte15487002015-12-25 22:23:27 +01001318 else {
Maxa86f5c02016-06-28 17:39:20 +02001319 if (llme)
1320 gprs_llgmm_unassign(llme);
Harald Welte15487002015-12-25 22:23:27 +01001321 }
Jacob Erlbeck6f4bbd42014-11-06 13:43:41 +01001322
1323 return rc;
Harald Welte75bb8202010-03-14 15:45:01 +08001324}
1325
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001326static int gsm48_rx_gmm_status(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08001327{
1328 struct gsm48_hdr *gh = msgb_l3(msg);
1329
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001330 LOGMMCTXP(LOGL_INFO, mmctx, "-> GPRS MM STATUS (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01001331 get_value_string(gsm48_gmm_cause_names, gh->data[0]));
Harald Welte75bb8202010-03-14 15:45:01 +08001332
1333 return 0;
1334}
1335
1336/* GPRS Mobility Management */
Harald Welte75871c72010-06-01 11:53:01 +02001337static int gsm0408_rcv_gmm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
Max4bc28212016-07-06 11:59:18 +02001338 struct gprs_llc_llme *llme, bool drop_cipherable)
Harald Welte75bb8202010-03-14 15:45:01 +08001339{
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001340 struct sgsn_signal_data sig_data;
Harald Weltecf3c4142010-04-30 16:33:12 +02001341 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001342 int rc;
1343
Harald Welte75871c72010-06-01 11:53:01 +02001344 /* MMCTX can be NULL when called */
Max4bc28212016-07-06 11:59:18 +02001345 if (drop_cipherable && gsm48_hdr_gmm_cipherable(gh)) {
1346 LOGMMCTXP(LOGL_NOTICE, mmctx, "Dropping cleartext GMM %s which "
1347 "is expected to be encrypted for TLLI 0x%08x\n",
1348 get_value_string(gprs_msgt_gmm_names, gh->msg_type),
1349 llme->tlli);
1350 return -EBADMSG;
1351 }
Harald Welte75871c72010-06-01 11:53:01 +02001352
Harald Welte95de4d52015-12-25 22:31:36 +01001353 if (llme && !mmctx &&
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001354 gh->msg_type != GSM48_MT_GMM_ATTACH_REQ &&
Harald Welte7e01d8e2010-05-31 20:23:38 +02001355 gh->msg_type != GSM48_MT_GMM_RA_UPD_REQ) {
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001356 LOGP(DMM, LOGL_NOTICE, "Cannot handle GMM for unknown MM CTX\n");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001357 /* 4.7.10 */
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001358 if (gh->msg_type == GSM48_MT_GMM_STATUS) {
1359 /* TLLI unassignment */
Maxa86f5c02016-06-28 17:39:20 +02001360 gprs_llgmm_unassign(llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001361 return 0;
Jacob Erlbeckb35ee6b2014-10-28 09:47:03 +01001362 }
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001363
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001364 /* Don't reply or establish a LLME on DETACH_ACK */
Maxa86f5c02016-06-28 17:39:20 +02001365 if (gh->msg_type == GSM48_MT_GMM_DETACH_ACK)
1366 return gprs_llgmm_unassign(llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001367
Jacob Erlbeck218ed402014-11-11 08:55:13 +01001368 gprs_llgmm_reset(llme);
1369
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001370 /* Don't force it into re-attachment */
1371 if (gh->msg_type == GSM48_MT_GMM_DETACH_REQ) {
Jacob Erlbeck42d284f2014-10-21 13:09:55 +02001372 /* Handle Detach Request */
1373 rc = gsm48_rx_gmm_det_req(NULL, msg);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001374
1375 /* TLLI unassignment */
Maxa86f5c02016-06-28 17:39:20 +02001376 gprs_llgmm_unassign(llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001377 return rc;
1378 }
1379
1380 /* Force the MS to re-attach */
Max6d999582016-07-06 15:57:01 +02001381 rc = gsm0408_gprs_force_reattach_oldmsg(msg, llme);
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01001382
1383 /* TLLI unassignment */
Maxa86f5c02016-06-28 17:39:20 +02001384 gprs_llgmm_unassign(llme);
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01001385 return rc;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001386 }
1387
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001388 /*
1389 * For a few messages, mmctx may be NULL. For most, we want to ensure a
1390 * non-NULL mmctx. At the same time, we want to keep the message
1391 * validity check intact, so that all message types appear in the
1392 * switch statement and the default case thus means "unknown message".
1393 * If we split the switch in two parts to check non-NULL halfway, the
1394 * unknown-message check breaks, or we'd need to duplicate the switch
1395 * cases in both parts. Just keep one large switch and add some gotos.
1396 */
Harald Welte75bb8202010-03-14 15:45:01 +08001397 switch (gh->msg_type) {
1398 case GSM48_MT_GMM_RA_UPD_REQ:
Harald Welte75871c72010-06-01 11:53:01 +02001399 rc = gsm48_rx_gmm_ra_upd_req(mmctx, msg, llme);
Harald Welte75bb8202010-03-14 15:45:01 +08001400 break;
1401 case GSM48_MT_GMM_ATTACH_REQ:
Harald Welte75871c72010-06-01 11:53:01 +02001402 rc = gsm48_rx_gmm_att_req(mmctx, msg, llme);
Harald Welte75bb8202010-03-14 15:45:01 +08001403 break;
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001404 /* For all the following types mmctx can not be NULL */
Harald Welte75bb8202010-03-14 15:45:01 +08001405 case GSM48_MT_GMM_ID_RESP:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001406 if (!mmctx)
1407 goto null_mmctx;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001408 rc = gsm48_rx_gmm_id_resp(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001409 break;
1410 case GSM48_MT_GMM_STATUS:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001411 if (!mmctx)
1412 goto null_mmctx;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001413 rc = gsm48_rx_gmm_status(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001414 break;
Harald Welte8f77f192010-05-17 00:44:57 +02001415 case GSM48_MT_GMM_DETACH_REQ:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001416 if (!mmctx)
1417 goto null_mmctx;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001418 rc = gsm48_rx_gmm_det_req(mmctx, msg);
Harald Welte8f77f192010-05-17 00:44:57 +02001419 break;
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001420 case GSM48_MT_GMM_DETACH_ACK:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001421 if (!mmctx)
1422 goto null_mmctx;
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02001423 LOGMMCTXP(LOGL_INFO, mmctx, "-> DETACH ACK\n");
1424 mm_ctx_cleanup_free(mmctx, "GPRS DETACH ACK");
1425 rc = 0;
1426 break;
Harald Welte75bb8202010-03-14 15:45:01 +08001427 case GSM48_MT_GMM_ATTACH_COMPL:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001428 if (!mmctx)
1429 goto null_mmctx;
Harald Welte75bb8202010-03-14 15:45:01 +08001430 /* only in case SGSN offered new P-TMSI */
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001431 LOGMMCTXP(LOGL_INFO, mmctx, "-> ATTACH COMPLETE\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001432 mmctx_timer_stop(mmctx, 3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001433 mmctx->t3350_mode = GMM_T3350_MODE_NONE;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001434 mmctx->p_tmsi_old = 0;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001435 mmctx->pending_req = 0;
Harald Welte15487002015-12-25 22:23:27 +01001436 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1437 /* Unassign the old TLLI */
1438 mmctx->gb.tlli = mmctx->gb.tlli_new;
Maxeb64e3f2016-07-06 11:33:04 +02001439 gprs_llme_copy_key(mmctx, mmctx->gb.llme);
Harald Welte15487002015-12-25 22:23:27 +01001440 gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
Maxeb64e3f2016-07-06 11:33:04 +02001441 mmctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001442 }
Jacob Erlbeck67318ef2014-10-28 16:23:46 +01001443 mmctx->mm_state = GMM_REGISTERED_NORMAL;
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001444 rc = 0;
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001445
1446 memset(&sig_data, 0, sizeof(sig_data));
1447 sig_data.mm = mmctx;
1448 osmo_signal_dispatch(SS_SGSN, S_SGSN_ATTACH, &sig_data);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001449 break;
Harald Welteebe8a6d2010-05-18 19:58:38 +02001450 case GSM48_MT_GMM_RA_UPD_COMPL:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001451 if (!mmctx)
1452 goto null_mmctx;
Harald Welteebe8a6d2010-05-18 19:58:38 +02001453 /* only in case SGSN offered new P-TMSI */
Harald Welteb25510a2015-08-16 18:14:33 +02001454 LOGMMCTXP(LOGL_INFO, mmctx, "-> ROUTING AREA UPDATE COMPLETE\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001455 mmctx_timer_stop(mmctx, 3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001456 mmctx->t3350_mode = GMM_T3350_MODE_NONE;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001457 mmctx->p_tmsi_old = 0;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001458 mmctx->pending_req = 0;
Harald Welte15487002015-12-25 22:23:27 +01001459 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1460 /* Unassign the old TLLI */
1461 mmctx->gb.tlli = mmctx->gb.tlli_new;
Maxeb64e3f2016-07-06 11:33:04 +02001462 gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff,
1463 mmctx->gb.tlli_new);
Harald Welte15487002015-12-25 22:23:27 +01001464 }
Jacob Erlbeck67318ef2014-10-28 16:23:46 +01001465 mmctx->mm_state = GMM_REGISTERED_NORMAL;
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001466 rc = 0;
Holger Hans Peter Freytherf14098a2015-05-02 19:55:38 +02001467
1468 memset(&sig_data, 0, sizeof(sig_data));
1469 sig_data.mm = mmctx;
1470 osmo_signal_dispatch(SS_SGSN, S_SGSN_UPDATE, &sig_data);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001471 break;
Harald Welte75bb8202010-03-14 15:45:01 +08001472 case GSM48_MT_GMM_PTMSI_REALL_COMPL:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001473 if (!mmctx)
1474 goto null_mmctx;
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001475 LOGMMCTXP(LOGL_INFO, mmctx, "-> PTMSI REALLLICATION COMPLETE\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001476 mmctx_timer_stop(mmctx, 3350);
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001477 mmctx->t3350_mode = GMM_T3350_MODE_NONE;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001478 mmctx->p_tmsi_old = 0;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001479 mmctx->pending_req = 0;
Harald Welte15487002015-12-25 22:23:27 +01001480 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb) {
1481 /* Unassign the old TLLI */
1482 mmctx->gb.tlli = mmctx->gb.tlli_new;
1483 //gprs_llgmm_assign(mmctx->gb.llme, 0xffffffff, mmctx->gb.tlli_new, GPRS_ALGO_GEA0, NULL);
1484 }
Holger Hans Peter Freytherf01f18e2011-10-14 23:31:34 +02001485 rc = 0;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001486 break;
Harald Welte75bb8202010-03-14 15:45:01 +08001487 case GSM48_MT_GMM_AUTH_CIPH_RESP:
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001488 if (!mmctx)
1489 goto null_mmctx;
Harald Welte45fcf682010-07-03 11:09:06 +02001490 rc = gsm48_rx_gmm_auth_ciph_resp(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001491 break;
1492 default:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001493 LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GMM msg type 0x%02x\n",
Harald Welte75bb8202010-03-14 15:45:01 +08001494 gh->msg_type);
Neels Hofmeyrd0ba6d62016-06-03 00:44:23 +02001495 if (mmctx)
1496 rc = gsm48_tx_gmm_status(mmctx, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
1497 else
1498 rc = -EINVAL;
Harald Welte75bb8202010-03-14 15:45:01 +08001499 break;
1500 }
1501
1502 return rc;
Neels Hofmeyr4805d8f2016-05-22 14:28:19 +02001503
1504null_mmctx:
1505 LOGP(DMM, LOGL_ERROR,
1506 "Received GSM 04.08 message type 0x%02x,"
1507 " but no MM context available\n",
1508 gh->msg_type);
1509 return -EINVAL;
Harald Welte75bb8202010-03-14 15:45:01 +08001510}
1511
Harald Welte7e01d8e2010-05-31 20:23:38 +02001512static void mmctx_timer_cb(void *_mm)
1513{
1514 struct sgsn_mm_ctx *mm = _mm;
Jacob Erlbeck4d127672014-12-01 12:33:33 +01001515 struct gsm_auth_tuple *at;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001516
1517 mm->num_T_exp++;
1518
1519 switch (mm->T) {
1520 case 3350: /* waiting for ATTACH COMPLETE */
1521 if (mm->num_T_exp >= 5) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001522 LOGMMCTXP(LOGL_NOTICE, mm, "T3350 expired >= 5 times\n");
Jacob Erlbeck25335882014-11-03 10:12:52 +01001523 mm_ctx_cleanup_free(mm, "T3350");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001524 /* FIXME: should we return some error? */
1525 break;
1526 }
1527 /* re-transmit the respective msg and re-start timer */
1528 switch (mm->t3350_mode) {
1529 case GMM_T3350_MODE_ATT:
1530 gsm48_tx_gmm_att_ack(mm);
1531 break;
1532 case GMM_T3350_MODE_RAU:
1533 gsm48_tx_gmm_ra_upd_ack(mm);
1534 break;
1535 case GMM_T3350_MODE_PTMSI_REALL:
1536 /* FIXME */
1537 break;
Jacob Erlbeck4f9b64a2014-10-28 12:23:29 +01001538 case GMM_T3350_MODE_NONE:
1539 LOGMMCTXP(LOGL_NOTICE, mm,
1540 "T3350 mode wasn't set, ignoring timeout\n");
1541 break;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001542 }
Harald Welte9b57a3d2015-08-15 19:08:21 +02001543 osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3350, 0);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001544 break;
Harald Welte45fcf682010-07-03 11:09:06 +02001545 case 3360: /* waiting for AUTH AND CIPH RESP */
1546 if (mm->num_T_exp >= 5) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001547 LOGMMCTXP(LOGL_NOTICE, mm, "T3360 expired >= 5 times\n");
Jacob Erlbeck25335882014-11-03 10:12:52 +01001548 mm_ctx_cleanup_free(mm, "T3360");
Harald Welte45fcf682010-07-03 11:09:06 +02001549 break;
1550 }
Jacob Erlbeck4d127672014-12-01 12:33:33 +01001551 /* Re-transmit the respective msg and re-start timer */
1552 if (mm->auth_triplet.key_seq == GSM_KEY_SEQ_INVAL) {
1553 LOGMMCTXP(LOGL_ERROR, mm,
1554 "timeout: invalid auth triplet reference\n");
1555 mm_ctx_cleanup_free(mm, "T3360");
1556 break;
1557 }
1558 at = &mm->auth_triplet;
1559
Max6d999582016-07-06 15:57:01 +02001560 gsm48_tx_gmm_auth_ciph_req(mm, at->vec.rand, at->key_seq, false);
Harald Welte9b57a3d2015-08-15 19:08:21 +02001561 osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3360, 0);
Harald Welte45fcf682010-07-03 11:09:06 +02001562 break;
Harald Welte7e01d8e2010-05-31 20:23:38 +02001563 case 3370: /* waiting for IDENTITY RESPONSE */
1564 if (mm->num_T_exp >= 5) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001565 LOGMMCTXP(LOGL_NOTICE, mm, "T3370 expired >= 5 times\n");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001566 gsm48_tx_gmm_att_rej(mm, GMM_CAUSE_MS_ID_NOT_DERIVED);
Jacob Erlbeck25335882014-11-03 10:12:52 +01001567 mm_ctx_cleanup_free(mm, "GPRS ATTACH REJECT (T3370)");
Harald Welte7e01d8e2010-05-31 20:23:38 +02001568 break;
1569 }
1570 /* re-tranmit IDENTITY REQUEST and re-start timer */
1571 gsm48_tx_gmm_id_req(mm, mm->t3370_id_type);
Harald Welte9b57a3d2015-08-15 19:08:21 +02001572 osmo_timer_schedule(&mm->timer, sgsn->cfg.timers.T3370, 0);
Harald Welte7e01d8e2010-05-31 20:23:38 +02001573 break;
1574 default:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001575 LOGMMCTXP(LOGL_ERROR, mm, "timer expired in unknown mode %u\n",
Harald Welte7e01d8e2010-05-31 20:23:38 +02001576 mm->T);
1577 }
1578}
1579
1580/* GPRS SESSION MANAGEMENT */
1581
Harald Welte94ecef32010-12-24 21:13:26 +01001582static void pdpctx_timer_cb(void *_mm);
1583
1584static void pdpctx_timer_start(struct sgsn_pdp_ctx *pdp, unsigned int T,
1585 unsigned int seconds)
1586{
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001587 if (osmo_timer_pending(&pdp->timer))
Harald Weltebdeaf5f2015-08-16 17:11:32 +02001588 LOGMMCTXP(LOGL_ERROR, pdp->mm, "Starting MM timer %u while old "
Harald Welte94ecef32010-12-24 21:13:26 +01001589 "timer %u pending\n", T, pdp->T);
1590 pdp->T = T;
1591 pdp->num_T_exp = 0;
1592
1593 /* FIXME: we should do this only once ? */
1594 pdp->timer.data = pdp;
1595 pdp->timer.cb = &pdpctx_timer_cb;
1596
Pablo Neira Ayuso840ccf62011-05-06 12:11:06 +02001597 osmo_timer_schedule(&pdp->timer, seconds, 0);
Harald Welte94ecef32010-12-24 21:13:26 +01001598}
1599
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02001600#if 0
Harald Welte2aea7492010-05-02 23:11:50 +02001601static void msgb_put_pdp_addr_ipv4(struct msgb *msg, uint32_t ipaddr)
1602{
1603 uint8_t v[6];
1604
1605 v[0] = PDP_TYPE_ORG_IETF;
1606 v[1] = PDP_TYPE_N_IETF_IPv4;
1607 *(uint32_t *)(v+2) = htonl(ipaddr);
1608
1609 msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
1610}
1611
1612static void msgb_put_pdp_addr_ppp(struct msgb *msg)
1613{
1614 uint8_t v[2];
1615
1616 v[0] = PDP_TYPE_ORG_ETSI;
1617 v[1] = PDP_TYPE_N_ETSI_PPP;
1618
1619 msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR, sizeof(v), v);
1620}
Holger Hans Peter Freytherb32f34a2014-04-04 12:40:34 +02001621#endif
Harald Welte2aea7492010-05-02 23:11:50 +02001622
Alexander Couzens32fdba02016-07-05 09:52:52 +02001623/* Section 9.5.2: Activate PDP Context Accept */
Harald Welte29d838e2010-05-18 10:35:06 +02001624int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp)
Harald Welte75bb8202010-03-14 15:45:01 +08001625{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001626 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP ACC");
Harald Welte75bb8202010-03-14 15:45:01 +08001627 struct gsm48_hdr *gh;
Harald Welte29d838e2010-05-18 10:35:06 +02001628 uint8_t transaction_id = pdp->ti ^ 0x8; /* flip */
Harald Welte75bb8202010-03-14 15:45:01 +08001629
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001630 LOGPDPCTXP(LOGL_INFO, pdp, "<- ACTIVATE PDP CONTEXT ACK\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02001631 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_ACCEPT]);
Harald Welte75bb8202010-03-14 15:45:01 +08001632
Harald Welte29d838e2010-05-18 10:35:06 +02001633 mmctx2msgid(msg, pdp->mm);
Harald Welte75bb8202010-03-14 15:45:01 +08001634
1635 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1636 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
1637 gh->msg_type = GSM48_MT_GSM_ACT_PDP_ACK;
Harald Welte2aea7492010-05-02 23:11:50 +02001638
1639 /* Negotiated LLC SAPI */
Harald Welte29d838e2010-05-18 10:35:06 +02001640 msgb_v_put(msg, pdp->sapi);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02001641
Harald Welte540dcbc2010-05-18 13:20:08 +02001642 /* FIXME: copy QoS parameters from original request */
1643 //msgb_lv_put(msg, pdp->lib->qos_neg.l, pdp->lib->qos_neg.v);
1644 msgb_lv_put(msg, sizeof(default_qos), (uint8_t *)&default_qos);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02001645
Harald Welte2aea7492010-05-02 23:11:50 +02001646 /* Radio priority 10.5.7.2 */
Harald Welte29d838e2010-05-18 10:35:06 +02001647 msgb_v_put(msg, pdp->lib->radio_pri);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02001648
Harald Welte2aea7492010-05-02 23:11:50 +02001649 /* PDP address */
Harald Welte7d7fd2b2010-05-18 14:51:18 +02001650 /* Highest 4 bits of first byte need to be set to 1, otherwise
1651 * the IE is identical with the 04.08 PDP Address IE */
1652 pdp->lib->eua.v[0] &= ~0xf0;
Harald Welte29d838e2010-05-18 10:35:06 +02001653 msgb_tlv_put(msg, GSM48_IE_GSM_PDP_ADDR,
1654 pdp->lib->eua.l, pdp->lib->eua.v);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02001655 pdp->lib->eua.v[0] |= 0xf0;
1656
Harald Welteeb471c92010-05-18 14:32:29 +02001657 /* Optional: Protocol configuration options (FIXME: why 'req') */
Holger Hans Peter Freyther1b51fc22014-04-04 11:55:21 +02001658 if (pdp->lib->pco_req.l)
Harald Welte29d838e2010-05-18 10:35:06 +02001659 msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
Harald Weltef2d66582010-05-18 14:36:11 +02001660 pdp->lib->pco_req.l, pdp->lib->pco_req.v);
Harald Welte7d7fd2b2010-05-18 14:51:18 +02001661
Harald Welte2aea7492010-05-02 23:11:50 +02001662 /* Optional: Packet Flow Identifier */
Harald Welte75bb8202010-03-14 15:45:01 +08001663
Max4bc28212016-07-06 11:59:18 +02001664 return gsm48_gmm_sendmsg(msg, 0, pdp->mm, true);
Harald Welte75bb8202010-03-14 15:45:01 +08001665}
1666
Harald Welte29d838e2010-05-18 10:35:06 +02001667/* Section 9.5.3: Activate PDP Context reject */
1668int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
1669 uint8_t cause, uint8_t pco_len, uint8_t *pco_v)
1670{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001671 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP REJ");
Harald Welte29d838e2010-05-18 10:35:06 +02001672 struct gsm48_hdr *gh;
1673 uint8_t transaction_id = tid ^ 0x8; /* flip */
1674
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001675 LOGMMCTXP(LOGL_NOTICE, mm, "<- ACTIVATE PDP CONTEXT REJ(cause=%u)\n", cause);
Alexander Couzens32fdba02016-07-05 09:52:52 +02001676 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REJECT]);
Harald Welte29d838e2010-05-18 10:35:06 +02001677
1678 mmctx2msgid(msg, mm);
1679
1680 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1681 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
1682 gh->msg_type = GSM48_MT_GSM_ACT_PDP_REJ;
1683
1684 msgb_v_put(msg, cause);
1685 if (pco_len && pco_v)
1686 msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT, pco_len, pco_v);
1687
Max4bc28212016-07-06 11:59:18 +02001688 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte29d838e2010-05-18 10:35:06 +02001689}
1690
Harald Welte94ecef32010-12-24 21:13:26 +01001691/* Section 9.5.8: Deactivate PDP Context Request */
1692static int _gsm48_tx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, uint8_t tid,
1693 uint8_t sm_cause)
1694{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001695 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET REQ");
Harald Welte94ecef32010-12-24 21:13:26 +01001696 struct gsm48_hdr *gh;
1697 uint8_t transaction_id = tid ^ 0x8; /* flip */
1698
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001699 LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT REQ\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02001700 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_REQUEST]);
Harald Welte94ecef32010-12-24 21:13:26 +01001701
1702 mmctx2msgid(msg, mm);
1703
1704 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1705 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
1706 gh->msg_type = GSM48_MT_GSM_DEACT_PDP_REQ;
1707
1708 msgb_v_put(msg, sm_cause);
1709
Max4bc28212016-07-06 11:59:18 +02001710 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte94ecef32010-12-24 21:13:26 +01001711}
1712int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause)
1713{
Harald Welte9b57a3d2015-08-15 19:08:21 +02001714 pdpctx_timer_start(pdp, 3395, sgsn->cfg.timers.T3395);
Harald Welte94ecef32010-12-24 21:13:26 +01001715
1716 return _gsm48_tx_gsm_deact_pdp_req(pdp->mm, pdp->ti, sm_cause);
1717}
1718
Harald Welte75bb8202010-03-14 15:45:01 +08001719/* Section 9.5.9: Deactivate PDP Context Accept */
Harald Welte3b807312010-06-08 18:08:59 +02001720static int _gsm48_tx_gsm_deact_pdp_acc(struct sgsn_mm_ctx *mm, uint8_t tid)
Harald Welte75bb8202010-03-14 15:45:01 +08001721{
Holger Hans Peter Freytherdd5012a2016-01-25 22:03:25 +01001722 struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 PDP DET ACC");
Harald Welte75bb8202010-03-14 15:45:01 +08001723 struct gsm48_hdr *gh;
Harald Welte3b807312010-06-08 18:08:59 +02001724 uint8_t transaction_id = tid ^ 0x8; /* flip */
Harald Welte75bb8202010-03-14 15:45:01 +08001725
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001726 LOGMMCTXP(LOGL_INFO, mm, "<- DEACTIVATE PDP CONTEXT ACK\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02001727 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_DL_DEACTIVATE_ACCEPT]);
Harald Welte75bb8202010-03-14 15:45:01 +08001728
Harald Welte3b807312010-06-08 18:08:59 +02001729 mmctx2msgid(msg, mm);
Harald Welte75bb8202010-03-14 15:45:01 +08001730
1731 gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
1732 gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
1733 gh->msg_type = GSM48_MT_GSM_DEACT_PDP_ACK;
1734
Max4bc28212016-07-06 11:59:18 +02001735 return gsm48_gmm_sendmsg(msg, 0, mm, true);
Harald Welte3b807312010-06-08 18:08:59 +02001736}
1737int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp)
1738{
1739 return _gsm48_tx_gsm_deact_pdp_acc(pdp->mm, pdp->ti);
Harald Welte75bb8202010-03-14 15:45:01 +08001740}
1741
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08001742static int activate_ggsn(struct sgsn_mm_ctx *mmctx,
1743 struct sgsn_ggsn_ctx *ggsn, const uint8_t transaction_id,
1744 const uint8_t req_nsapi, const uint8_t req_llc_sapi,
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001745 struct tlv_parsed *tp, int destroy_ggsn)
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08001746{
1747 struct sgsn_pdp_ctx *pdp;
1748
Holger Hans Peter Freyther4b4f7b72015-05-29 15:11:55 +02001749 LOGMMCTXP(LOGL_DEBUG, mmctx, "Using GGSN %u\n", ggsn->id);
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08001750 ggsn->gsn = sgsn->gsn;
1751 pdp = sgsn_create_pdp_ctx(ggsn, mmctx, req_nsapi, tp);
1752 if (!pdp)
1753 return -1;
1754
1755 /* Store SAPI and Transaction Identifier */
1756 pdp->sapi = req_llc_sapi;
1757 pdp->ti = transaction_id;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001758 pdp->destroy_ggsn = destroy_ggsn;
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08001759
1760 return 0;
1761}
1762
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001763static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *hostent)
1764{
1765 struct sgsn_ggsn_ctx *ggsn;
1766 struct sgsn_ggsn_lookup *lookup = arg;
1767 struct in_addr *addr = NULL;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001768
1769 /* The context is gone while we made a request */
1770 if (!lookup->mmctx) {
1771 talloc_free(lookup);
1772 return;
1773 }
1774
1775 if (status != ARES_SUCCESS) {
1776 struct sgsn_mm_ctx *mmctx = lookup->mmctx;
1777
1778 LOGMMCTXP(LOGL_ERROR, mmctx, "DNS query failed.\n");
1779
1780 /* Need to try with three digits now */
1781 if (lookup->state == SGSN_GGSN_2DIGIT) {
1782 char *hostname;
1783 int rc;
1784
1785 lookup->state = SGSN_GGSN_3DIGIT;
1786 hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
1787 lookup->apn_str, 1);
1788 LOGMMCTXP(LOGL_DEBUG, mmctx,
1789 "Going to query %s\n", hostname);
1790 rc = sgsn_ares_query(sgsn, hostname,
1791 ggsn_lookup_cb, lookup);
1792 if (rc != 0) {
Harald Welte0b8dbb72015-08-16 17:16:28 +02001793 LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't start GGSN\n");
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001794 goto reject_due_failure;
1795 }
1796 return;
1797 }
1798
1799 LOGMMCTXP(LOGL_ERROR, mmctx, "Couldn't resolve GGSN\n");
1800 goto reject_due_failure;
1801 }
1802
1803 if (hostent->h_length != sizeof(struct in_addr)) {
1804 LOGMMCTXP(LOGL_ERROR, lookup->mmctx,
Harald Welte369fb072015-08-16 17:16:57 +02001805 "Wrong addr size(%zu)\n", sizeof(struct in_addr));
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001806 goto reject_due_failure;
1807 }
1808
Holger Hans Peter Freytherb9852342015-06-02 09:38:41 +02001809 /* Get the first addr from the list */
1810 addr = (struct in_addr *) hostent->h_addr_list[0];
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001811 if (!addr) {
1812 LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "No host address.\n");
1813 goto reject_due_failure;
1814 }
1815
1816 ggsn = sgsn_ggsn_ctx_alloc(UINT32_MAX);
1817 if (!ggsn) {
1818 LOGMMCTXP(LOGL_ERROR, lookup->mmctx, "Failed to create ggsn.\n");
1819 goto reject_due_failure;
1820 }
1821 ggsn->remote_addr = *addr;
1822 LOGMMCTXP(LOGL_NOTICE, lookup->mmctx,
1823 "Selected %s as GGSN.\n", inet_ntoa(*addr));
1824
1825 /* forget about the ggsn look-up */
1826 lookup->mmctx->ggsn_lookup = NULL;
1827
1828 activate_ggsn(lookup->mmctx, ggsn, lookup->ti, lookup->nsapi,
1829 lookup->sapi, &lookup->tp, 1);
1830
1831 /* Now free it */
1832 talloc_free(lookup);
1833 return;
1834
1835reject_due_failure:
1836 gsm48_tx_gsm_act_pdp_rej(lookup->mmctx, lookup->ti,
1837 GMM_CAUSE_NET_FAIL, 0, NULL);
1838 lookup->mmctx->ggsn_lookup = NULL;
1839 talloc_free(lookup);
1840}
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08001841
1842static int do_act_pdp_req(struct sgsn_mm_ctx *mmctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08001843{
Harald Weltecf3c4142010-04-30 16:33:12 +02001844 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte75bb8202010-03-14 15:45:01 +08001845 struct gsm48_act_pdp_ctx_req *act_req = (struct gsm48_act_pdp_ctx_req *) gh->data;
Harald Welteb1fd23a2010-05-02 21:07:14 +02001846 uint8_t req_qos_len, req_pdpa_len;
1847 uint8_t *req_qos, *req_pdpa;
1848 struct tlv_parsed tp;
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01001849 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Harald Welte8bf65d02010-07-02 10:17:24 +02001850 struct sgsn_ggsn_ctx *ggsn;
Harald Welte29d838e2010-05-18 10:35:06 +02001851 struct sgsn_pdp_ctx *pdp;
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001852 enum gsm48_gsm_cause gsm_cause;
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001853 char apn_str[GSM_APN_LENGTH] = { 0, };
1854 char *hostname;
1855 int rc;
Harald Welte75bb8202010-03-14 15:45:01 +08001856
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001857 LOGMMCTXP(LOGL_INFO, mmctx, "-> ACTIVATE PDP CONTEXT REQ: SAPI=%u NSAPI=%u ",
Harald Welte29d838e2010-05-18 10:35:06 +02001858 act_req->req_llc_sapi, act_req->req_nsapi);
Harald Welte8a035af2010-05-18 10:57:45 +02001859
Harald Welteb7b0fd72010-07-02 22:52:04 +02001860 /* FIXME: length checks! */
Harald Welteb1fd23a2010-05-02 21:07:14 +02001861 req_qos_len = act_req->data[0];
1862 req_qos = act_req->data + 1; /* 10.5.6.5 */
1863 req_pdpa_len = act_req->data[1 + req_qos_len];
1864 req_pdpa = act_req->data + 1 + req_qos_len + 1; /* 10.5.6.4 */
Harald Welte75bb8202010-03-14 15:45:01 +08001865
Harald Welteb1fd23a2010-05-02 21:07:14 +02001866 switch (req_pdpa[0] & 0xf) {
1867 case 0x0:
1868 DEBUGPC(DMM, "ETSI ");
1869 break;
1870 case 0x1:
1871 DEBUGPC(DMM, "IETF ");
1872 break;
1873 case 0xf:
1874 DEBUGPC(DMM, "Empty ");
1875 break;
1876 }
1877
1878 switch (req_pdpa[1]) {
1879 case 0x21:
1880 DEBUGPC(DMM, "IPv4 ");
1881 if (req_pdpa_len >= 6) {
1882 struct in_addr ia;
1883 ia.s_addr = ntohl(*((uint32_t *) (req_pdpa+2)));
1884 DEBUGPC(DMM, "%s ", inet_ntoa(ia));
1885 }
1886 break;
1887 case 0x57:
1888 DEBUGPC(DMM, "IPv6 ");
1889 if (req_pdpa_len >= 18) {
1890 /* FIXME: print IPv6 address */
1891 }
1892 break;
1893 default:
1894 DEBUGPC(DMM, "0x%02x ", req_pdpa[1]);
1895 break;
1896 }
1897
Daniel Willmannc9ac9732014-09-03 17:46:44 +02001898 LOGPC(DMM, LOGL_INFO, "\n");
Harald Welteeb471c92010-05-18 14:32:29 +02001899
Harald Welte29d838e2010-05-18 10:35:06 +02001900 /* Check if NSAPI is out of range (TS 04.65 / 7.2) */
1901 if (act_req->req_nsapi < 5 || act_req->req_nsapi > 15) {
1902 /* Send reject with GSM_CAUSE_INV_MAND_INFO */
1903 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
1904 GSM_CAUSE_INV_MAND_INFO,
1905 0, NULL);
1906 }
1907
Holger Hans Peter Freyther3f7d46e2015-05-24 12:42:26 +08001908 /* Optional: Access Point Name, Protocol Config Options */
1909 if (req_pdpa + req_pdpa_len < msg->data + msg->len)
1910 tlv_parse(&tp, &gsm48_sm_att_tlvdef, req_pdpa + req_pdpa_len,
1911 (msg->data + msg->len) - (req_pdpa + req_pdpa_len), 0, 0);
1912 else
1913 memset(&tp, 0, sizeof(tp));
1914
1915
1916 /* put the non-TLV elements in the TLV parser structure to
1917 * pass them on to the SGSN / GTP code */
1918 tp.lv[OSMO_IE_GSM_REQ_QOS].len = req_qos_len;
1919 tp.lv[OSMO_IE_GSM_REQ_QOS].val = req_qos;
1920 tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].len = req_pdpa_len;
1921 tp.lv[OSMO_IE_GSM_REQ_PDP_ADDR].val = req_pdpa;
1922
Harald Welte29d838e2010-05-18 10:35:06 +02001923 /* Check if NSAPI is already in use */
Harald Welte5fbac982010-07-02 10:12:58 +02001924 pdp = sgsn_pdp_ctx_by_nsapi(mmctx, act_req->req_nsapi);
1925 if (pdp) {
1926 /* We already have a PDP context for this TLLI + NSAPI tuple */
1927 if (pdp->sapi == act_req->req_llc_sapi &&
1928 pdp->ti == transaction_id) {
1929 /* This apparently is a re-transmission of a PDP CTX
1930 * ACT REQ (our ACT ACK must have got dropped) */
1931 return gsm48_tx_gsm_act_pdp_acc(pdp);
1932 }
1933
1934 /* Send reject with GSM_CAUSE_NSAPI_IN_USE */
Harald Welte29d838e2010-05-18 10:35:06 +02001935 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
1936 GSM_CAUSE_NSAPI_IN_USE,
1937 0, NULL);
1938 }
Harald Welte75bb8202010-03-14 15:45:01 +08001939
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001940 if (mmctx->ggsn_lookup) {
1941 if (mmctx->ggsn_lookup->sapi == act_req->req_llc_sapi &&
1942 mmctx->ggsn_lookup->ti == transaction_id) {
1943 LOGMMCTXP(LOGL_NOTICE, mmctx,
1944 "Re-transmission while doing look-up. Ignoring.\n");
1945 return 0;
1946 }
1947 }
1948
Harald Weltea456a232010-07-02 10:15:49 +02001949 /* Only increment counter for a real activation, after we checked
1950 * for re-transmissions */
1951 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PDP_CTX_ACT]);
1952
Jacob Erlbeck3400f112015-02-02 18:03:05 +01001953 /* Determine GGSN based on APN and subscription options */
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001954 ggsn = sgsn_mm_ctx_find_ggsn_ctx(mmctx, &tp, &gsm_cause, apn_str);
1955 if (ggsn)
1956 return activate_ggsn(mmctx, ggsn, transaction_id,
1957 act_req->req_nsapi, act_req->req_llc_sapi,
1958 &tp, 0);
1959
1960 if (strlen(apn_str) == 0)
1961 goto no_context;
1962 if (!sgsn->cfg.dynamic_lookup)
1963 goto no_context;
1964
1965 /* schedule a dynamic look-up */
1966 mmctx->ggsn_lookup = talloc_zero(tall_bsc_ctx, struct sgsn_ggsn_lookup);
1967 if (!mmctx->ggsn_lookup)
1968 goto no_context;
1969
1970 mmctx->ggsn_lookup->state = SGSN_GGSN_2DIGIT;
1971 mmctx->ggsn_lookup->mmctx = mmctx;
1972 strcpy(mmctx->ggsn_lookup->apn_str, apn_str);
1973
1974 mmctx->ggsn_lookup->orig_msg = msg;
1975 mmctx->ggsn_lookup->tp = tp;
1976
1977 mmctx->ggsn_lookup->ti = transaction_id;
1978 mmctx->ggsn_lookup->nsapi = act_req->req_nsapi;
1979 mmctx->ggsn_lookup->sapi = act_req->req_llc_sapi;
1980
1981 hostname = osmo_apn_qualify_from_imsi(mmctx->imsi,
1982 mmctx->ggsn_lookup->apn_str, 0);
1983
1984 LOGMMCTXP(LOGL_DEBUG, mmctx, "Going to query %s\n", hostname);
1985 rc = sgsn_ares_query(sgsn, hostname,
1986 ggsn_lookup_cb, mmctx->ggsn_lookup);
1987 if (rc != 0) {
1988 LOGMMCTXP(LOGL_ERROR, mmctx, "Failed to start ares query.\n");
1989 goto no_context;
Harald Weltec1f6bfe2010-05-17 22:58:03 +02001990 }
Harald Welte8bf65d02010-07-02 10:17:24 +02001991
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001992 return 0;
1993
1994no_context:
Harald Welte0b8dbb72015-08-16 17:16:28 +02001995 LOGMMCTXP(LOGL_ERROR, mmctx, "No GGSN context found!\n");
Holger Hans Peter Freyther2b1d49a2015-05-25 12:26:49 +08001996 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
1997 gsm_cause, 0, NULL);
Harald Welte75bb8202010-03-14 15:45:01 +08001998}
1999
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002000/* Section 9.5.1: Activate PDP Context Request */
2001static int gsm48_rx_gsm_act_pdp_req(struct sgsn_mm_ctx *mmctx,
2002 struct msgb *_msg)
2003{
2004 struct msgb *msg;
2005 int rc;
2006
Alexander Couzens32fdba02016-07-05 09:52:52 +02002007 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_ACTIVATE_REQUEST]);
2008
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002009 /*
2010 * This is painful. We might not have a static GGSN
2011 * configuration and then would need to copy the msg
2012 * and re-do most of this routine (or call it again
2013 * and make sure it only goes through the dynamic
2014 * resolving. The question is what to optimize for
2015 * and the dynamic resolution will be the right thing
2016 * in the long run.
2017 */
2018 msg = gprs_msgb_copy(_msg, __func__);
2019 if (!msg) {
2020 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(_msg);
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002021 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Holger Hans Peter Freyther2c456b42015-05-24 16:48:22 +08002022
2023 LOGMMCTXP(LOGL_ERROR, mmctx, "-> ACTIVATE PDP CONTEXT REQ failed copy.\n");
2024 /* Send reject with GSM_CAUSE_INV_MAND_INFO */
2025 return gsm48_tx_gsm_act_pdp_rej(mmctx, transaction_id,
2026 GSM_CAUSE_NET_FAIL,
2027 0, NULL);
2028 }
2029
2030 rc = do_act_pdp_req(mmctx, _msg);
2031 msgb_free(msg);
2032 return rc;
2033}
2034
Harald Welte75bb8202010-03-14 15:45:01 +08002035/* Section 9.5.8: Deactivate PDP Context Request */
Harald Welteeb471c92010-05-18 14:32:29 +02002036static int gsm48_rx_gsm_deact_pdp_req(struct sgsn_mm_ctx *mm, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08002037{
Harald Weltecf3c4142010-04-30 16:33:12 +02002038 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002039 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Harald Welteeb471c92010-05-18 14:32:29 +02002040 struct sgsn_pdp_ctx *pdp;
Harald Welte75bb8202010-03-14 15:45:01 +08002041
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002042 LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT REQ (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01002043 get_value_string(gsm48_gsm_cause_names, gh->data[0]));
Alexander Couzens32fdba02016-07-05 09:52:52 +02002044 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_REQUEST]);
Harald Welte75bb8202010-03-14 15:45:01 +08002045
Harald Welteeb471c92010-05-18 14:32:29 +02002046 pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
2047 if (!pdp) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002048 LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Request for "
Harald Welteeb471c92010-05-18 14:32:29 +02002049 "non-existing PDP Context (IMSI=%s, TI=%u)\n",
2050 mm->imsi, transaction_id);
Harald Welte3b807312010-06-08 18:08:59 +02002051 return _gsm48_tx_gsm_deact_pdp_acc(mm, transaction_id);
Harald Welteeb471c92010-05-18 14:32:29 +02002052 }
2053
2054 return sgsn_delete_pdp_ctx(pdp);
Harald Welte75bb8202010-03-14 15:45:01 +08002055}
2056
Harald Welte94ecef32010-12-24 21:13:26 +01002057/* Section 9.5.9: Deactivate PDP Context Accept */
2058static int gsm48_rx_gsm_deact_pdp_ack(struct sgsn_mm_ctx *mm, struct msgb *msg)
2059{
2060 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Neels Hofmeyrf1c283c2016-03-14 16:13:25 +01002061 uint8_t transaction_id = gsm48_hdr_trans_id(gh);
Harald Welte94ecef32010-12-24 21:13:26 +01002062 struct sgsn_pdp_ctx *pdp;
2063
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002064 LOGMMCTXP(LOGL_INFO, mm, "-> DEACTIVATE PDP CONTEXT ACK\n");
Alexander Couzens32fdba02016-07-05 09:52:52 +02002065 rate_ctr_inc(&sgsn->rate_ctrs->ctr[CTR_PDP_UL_DEACTIVATE_ACCEPT]);
Harald Welte94ecef32010-12-24 21:13:26 +01002066
2067 pdp = sgsn_pdp_ctx_by_tid(mm, transaction_id);
2068 if (!pdp) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002069 LOGMMCTXP(LOGL_NOTICE, mm, "Deactivate PDP Context Accept for "
Harald Welte94ecef32010-12-24 21:13:26 +01002070 "non-existing PDP Context (IMSI=%s, TI=%u)\n",
2071 mm->imsi, transaction_id);
2072 return 0;
2073 }
2074
2075 return sgsn_delete_pdp_ctx(pdp);
2076}
2077
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002078static int gsm48_rx_gsm_status(struct sgsn_mm_ctx *ctx, struct msgb *msg)
Harald Welte75bb8202010-03-14 15:45:01 +08002079{
2080 struct gsm48_hdr *gh = msgb_l3(msg);
2081
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002082 LOGMMCTXP(LOGL_INFO, ctx, "-> GPRS SM STATUS (cause: %s)\n",
Jacob Erlbeck9346dad2015-01-05 17:30:02 +01002083 get_value_string(gsm48_gsm_cause_names, gh->data[0]));
Harald Welte75bb8202010-03-14 15:45:01 +08002084
2085 return 0;
2086}
2087
Harald Welte94ecef32010-12-24 21:13:26 +01002088static void pdpctx_timer_cb(void *_pdp)
2089{
2090 struct sgsn_pdp_ctx *pdp = _pdp;
2091
2092 pdp->num_T_exp++;
2093
2094 switch (pdp->T) {
2095 case 3395: /* waiting for PDP CTX DEACT ACK */
2096 if (pdp->num_T_exp >= 4) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002097 LOGPDPCTXP(LOGL_NOTICE, pdp, "T3395 expired >= 5 times\n");
Harald Welte94ecef32010-12-24 21:13:26 +01002098 pdp->state = PDP_STATE_INACTIVE;
2099 sgsn_delete_pdp_ctx(pdp);
2100 break;
2101 }
Alexander Couzens88790b22016-07-19 15:14:03 +02002102 gsm48_tx_gsm_deact_pdp_req(pdp, GSM_CAUSE_NET_FAIL);
Harald Welte94ecef32010-12-24 21:13:26 +01002103 break;
2104 default:
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002105 LOGPDPCTXP(LOGL_ERROR, pdp, "timer expired in unknown mode %u\n",
Harald Welte94ecef32010-12-24 21:13:26 +01002106 pdp->T);
2107 }
2108}
2109
2110
Harald Welte75bb8202010-03-14 15:45:01 +08002111/* GPRS Session Management */
Harald Welte75871c72010-06-01 11:53:01 +02002112static int gsm0408_rcv_gsm(struct sgsn_mm_ctx *mmctx, struct msgb *msg,
2113 struct gprs_llc_llme *llme)
Harald Welte75bb8202010-03-14 15:45:01 +08002114{
Harald Weltecf3c4142010-04-30 16:33:12 +02002115 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002116 int rc;
2117
Harald Welte75871c72010-06-01 11:53:01 +02002118 /* MMCTX can be NULL when called */
2119
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002120 if (!mmctx) {
2121 LOGP(DMM, LOGL_NOTICE, "Cannot handle SM for unknown MM CTX\n");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002122 /* 6.1.3.6 */
2123 if (gh->msg_type == GSM48_MT_GSM_STATUS)
2124 return 0;
2125
Max6d999582016-07-06 15:57:01 +02002126 return gsm0408_gprs_force_reattach_oldmsg(msg, llme);
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002127 }
2128
Harald Welte75bb8202010-03-14 15:45:01 +08002129 switch (gh->msg_type) {
2130 case GSM48_MT_GSM_ACT_PDP_REQ:
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002131 rc = gsm48_rx_gsm_act_pdp_req(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002132 break;
2133 case GSM48_MT_GSM_DEACT_PDP_REQ:
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002134 rc = gsm48_rx_gsm_deact_pdp_req(mmctx, msg);
Harald Welteeb471c92010-05-18 14:32:29 +02002135 break;
Harald Welte94ecef32010-12-24 21:13:26 +01002136 case GSM48_MT_GSM_DEACT_PDP_ACK:
2137 rc = gsm48_rx_gsm_deact_pdp_ack(mmctx, msg);
2138 break;
Harald Welte75bb8202010-03-14 15:45:01 +08002139 case GSM48_MT_GSM_STATUS:
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002140 rc = gsm48_rx_gsm_status(mmctx, msg);
Harald Welte75bb8202010-03-14 15:45:01 +08002141 break;
2142 case GSM48_MT_GSM_REQ_PDP_ACT_REJ:
2143 case GSM48_MT_GSM_ACT_AA_PDP_REQ:
2144 case GSM48_MT_GSM_DEACT_AA_PDP_REQ:
Harald Welte20cbe912015-08-16 12:18:13 +02002145 LOGMMCTXP(LOGL_NOTICE, mmctx, "Unimplemented GSM 04.08 GSM msg type 0x%02x: %s\n",
2146 gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
Harald Welte263edd12010-06-09 10:51:23 +02002147 rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Harald Welte75bb8202010-03-14 15:45:01 +08002148 break;
2149 default:
Harald Welte20cbe912015-08-16 12:18:13 +02002150 LOGMMCTXP(LOGL_NOTICE, mmctx, "Unknown GSM 04.08 GSM msg type 0x%02x: %s\n",
2151 gh->msg_type, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
Harald Welte263edd12010-06-09 10:51:23 +02002152 rc = gsm48_tx_sm_status(mmctx, GSM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Harald Welte75bb8202010-03-14 15:45:01 +08002153 break;
2154
2155 }
2156
2157 return rc;
2158}
2159
Max6d999582016-07-06 15:57:01 +02002160int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
2161 struct gprs_llc_llme *llme)
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002162{
Jacob Erlbeck6e15b732014-10-31 12:20:49 +01002163 int rc;
Max6d999582016-07-06 15:57:01 +02002164 gprs_llgmm_reset_oldmsg(msg, GPRS_SAPI_GMM, llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002165
Jacob Erlbeck6e15b732014-10-31 12:20:49 +01002166 rc = gsm48_tx_gmm_detach_req_oldmsg(
2167 msg, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002168
Jacob Erlbeck6e15b732014-10-31 12:20:49 +01002169 return rc;
2170}
2171
2172int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx)
2173{
2174 int rc;
Harald Welte15487002015-12-25 22:23:27 +01002175 if (mmctx->ran_type == MM_CTX_T_GERAN_Gb)
2176 gprs_llgmm_reset(mmctx->gb.llme);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002177
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01002178 rc = gsm48_tx_gmm_detach_req(
2179 mmctx, GPRS_DET_T_MT_REATT_REQ, GMM_CAUSE_IMPL_DETACHED);
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002180
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01002181 mm_ctx_cleanup_free(mmctx, "forced reattach");
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002182
Jacob Erlbeck0a6a02e2014-10-31 12:27:11 +01002183 return rc;
Jacob Erlbeckccaa22a2014-09-05 14:32:36 +02002184}
2185
Harald Weltebeaf11d2015-12-25 19:14:57 +01002186/* Main entry point for incoming 04.08 GPRS messages from Gb */
Max4bc28212016-07-06 11:59:18 +02002187int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
2188 bool drop_cipherable)
Harald Welte75bb8202010-03-14 15:45:01 +08002189{
Harald Weltecf3c4142010-04-30 16:33:12 +02002190 struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg);
Neels Hofmeyrf94dfd52016-03-14 16:13:24 +01002191 uint8_t pdisc = gsm48_hdr_pdisc(gh);
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002192 struct sgsn_mm_ctx *mmctx;
2193 struct gprs_ra_id ra_id;
Harald Welte75bb8202010-03-14 15:45:01 +08002194 int rc = -EINVAL;
2195
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002196 bssgp_parse_cell_id(&ra_id, msgb_bcid(msg));
2197 mmctx = sgsn_mm_ctx_by_tlli(msgb_tlli(msg), &ra_id);
Harald Welte8a035af2010-05-18 10:57:45 +02002198 if (mmctx) {
Harald Welte29d838e2010-05-18 10:35:06 +02002199 msgid2mmctx(mmctx, msg);
Harald Welte8a035af2010-05-18 10:57:45 +02002200 rate_ctr_inc(&mmctx->ctrg->ctr[GMM_CTR_PKTS_SIG_IN]);
Harald Weltec28dc2f2015-12-25 19:12:21 +01002201 mmctx->gb.llme = llme;
Harald Welte8a035af2010-05-18 10:57:45 +02002202 }
Harald Weltec1f6bfe2010-05-17 22:58:03 +02002203
2204 /* MMCTX can be NULL */
2205
Harald Welte75bb8202010-03-14 15:45:01 +08002206 switch (pdisc) {
2207 case GSM48_PDISC_MM_GPRS:
Max4bc28212016-07-06 11:59:18 +02002208 rc = gsm0408_rcv_gmm(mmctx, msg, llme, drop_cipherable);
Harald Welte75bb8202010-03-14 15:45:01 +08002209 break;
2210 case GSM48_PDISC_SM_GPRS:
Harald Welte75871c72010-06-01 11:53:01 +02002211 rc = gsm0408_rcv_gsm(mmctx, msg, llme);
Harald Welte75bb8202010-03-14 15:45:01 +08002212 break;
2213 default:
Harald Weltebdeaf5f2015-08-16 17:11:32 +02002214 LOGMMCTXP(LOGL_NOTICE, mmctx,
2215 "Unknown GSM 04.08 discriminator 0x%02x: %s\n",
Harald Welte20cbe912015-08-16 12:18:13 +02002216 pdisc, osmo_hexdump((uint8_t *)gh, msgb_l3len(msg)));
Harald Welte29d838e2010-05-18 10:35:06 +02002217 /* FIXME: return status message */
Harald Welte75bb8202010-03-14 15:45:01 +08002218 break;
2219 }
2220
Jacob Erlbeck12396bd2014-09-30 13:51:45 +02002221 /* MMCTX can be invalid */
2222
Harald Welte75bb8202010-03-14 15:45:01 +08002223 return rc;
2224}
Harald Welte50264822010-06-09 11:22:47 +02002225
2226int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli)
2227{
2228 struct sgsn_mm_ctx *mmctx;
2229
2230 mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
2231 if (!mmctx) {
2232 LOGP(DMM, LOGL_NOTICE, "SUSPEND request for unknown "
2233 "TLLI=%08x\n", tlli);
2234 return -EINVAL;
2235 }
2236
Jacob Erlbeck764b8d52014-12-22 17:58:18 +01002237 if (mmctx->mm_state != GMM_REGISTERED_NORMAL &&
2238 mmctx->mm_state != GMM_REGISTERED_SUSPENDED) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002239 LOGMMCTXP(LOGL_NOTICE, mmctx, "SUSPEND request while state "
Harald Welte50264822010-06-09 11:22:47 +02002240 "!= REGISTERED (TLLI=%08x)\n", tlli);
2241 return -EINVAL;
2242 }
2243
2244 /* Transition from REGISTERED_NORMAL to REGISTERED_SUSPENDED */
2245 mmctx->mm_state = GMM_REGISTERED_SUSPENDED;
2246 return 0;
2247}
2248
2249int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
2250 uint8_t suspend_ref)
2251{
2252 struct sgsn_mm_ctx *mmctx;
2253
2254 /* FIXME: make use of suspend reference? */
2255
2256 mmctx = sgsn_mm_ctx_by_tlli(tlli, raid);
2257 if (!mmctx) {
2258 LOGP(DMM, LOGL_NOTICE, "RESUME request for unknown "
2259 "TLLI=%08x\n", tlli);
2260 return -EINVAL;
2261 }
2262
Jacob Erlbeck764b8d52014-12-22 17:58:18 +01002263 if (mmctx->mm_state != GMM_REGISTERED_NORMAL &&
2264 mmctx->mm_state != GMM_REGISTERED_SUSPENDED) {
Daniel Willmannc9ac9732014-09-03 17:46:44 +02002265 LOGMMCTXP(LOGL_NOTICE, mmctx, "RESUME request while state "
Harald Welte50264822010-06-09 11:22:47 +02002266 "!= SUSPENDED (TLLI=%08x)\n", tlli);
2267 /* FIXME: should we not simply ignore it? */
2268 return -EINVAL;
2269 }
2270
2271 /* Transition from SUSPENDED to NORMAL */
2272 mmctx->mm_state = GMM_REGISTERED_NORMAL;
2273 return 0;
2274}