blob: 94db74259bd60f4dc751a2687ce7440f1c89d6b9 [file] [log] [blame]
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +01001/* MS subscriber data handling */
2
3/* (C) 2014 by sysmocom s.f.m.c. GmbH
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <openbsc/gsm_subscriber.h>
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010023#include <openbsc/gprs_gsup_client.h>
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010024
25#include <openbsc/sgsn.h>
26#include <openbsc/gprs_sgsn.h>
27#include <openbsc/gprs_gmm.h>
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +010028#include <openbsc/gprs_gsup_messages.h>
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010029
30#include <openbsc/debug.h>
31
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010032#include <netinet/in.h>
33#include <arpa/inet.h>
34
Jacob Erlbeck743dec42015-01-08 15:18:39 +010035#define SGSN_SUBSCR_MAX_RETRIES 3
36#define SGSN_SUBSCR_RETRY_INTERVAL 10
37
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010038extern void *tall_bsc_ctx;
39
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010040static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg);
41
42/* TODO: Some functions are specific to the SGSN, but this file is more general
43 * (it has gprs_* name). Either move these functions elsewhere, split them and
44 * move a part, or replace the gprs_ prefix by sgsn_. The applies to
45 * gprs_subscr_init, gsup_read_cb, and gprs_subscr_tx_gsup_message.
46 */
47
48int gprs_subscr_init(struct sgsn_instance *sgi)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010049{
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010050 const char *addr_str;
51
52 if (!sgi->cfg.gsup_server_addr.sin_addr.s_addr)
53 return 0;
54
55 addr_str = inet_ntoa(sgi->cfg.gsup_server_addr.sin_addr);
56
57 sgi->gsup_client = gprs_gsup_client_create(
58 addr_str, sgi->cfg.gsup_server_port,
59 &gsup_read_cb);
60
61 if (!sgi->gsup_client)
62 return -1;
63
64 return 1;
65}
66
67static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg)
68{
69 int rc;
70
71 rc = gprs_subscr_rx_gsup_message(msg);
Jacob Erlbecke154d8b2014-12-19 19:15:55 +010072 msgb_free(msg);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010073 if (rc < 0)
74 return -1;
75
76 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010077}
78
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +010079static int check_blocking(
80 struct gsm_subscriber *subscr,
81 enum sgsn_subscriber_proc what)
82{
83 if (subscr->sgsn_data->blocked_by == SGSN_SUBSCR_PROC_NONE ||
84 subscr->sgsn_data->blocked_by == what)
85 return 1;
86
87 return 0;
88}
89
90static void abort_blocking_procedure(struct gsm_subscriber *subscr)
91{
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +010092 /* reset something */
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +010093}
94
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +010095int gprs_subscr_purge(struct gsm_subscriber *subscr);
96
Jacob Erlbecka1e03732014-12-02 11:28:38 +010097static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
98{
99 struct sgsn_subscriber_data *sdata;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100100 int idx;
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100101
102 sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
103
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100104 sdata->error_cause = SGSN_ERROR_CAUSE_NONE;
105
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100106 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
107 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
108
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100109 return sdata;
110}
111
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100112struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
113{
114 struct gsm_subscriber *subscr;
115
116 subscr = subscr_get_or_create(NULL, imsi);
117 if (!subscr)
118 return NULL;
119
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100120 if (!subscr->sgsn_data)
121 subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100122 return subscr;
123}
124
125struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi)
126{
127 return subscr_active_by_imsi(NULL, imsi);
128}
129
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100130void gprs_subscr_cleanup(struct gsm_subscriber *subscr)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100131{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100132 if (subscr->sgsn_data->mm) {
133 subscr_put(subscr->sgsn_data->mm->subscr);
134 subscr->sgsn_data->mm->subscr = NULL;
135 subscr->sgsn_data->mm = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100136 }
137
Holger Hans Peter Freyther1d778fd2015-01-20 21:14:03 +0100138 if (subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE) {
139 gprs_subscr_purge(subscr);
140 subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100141 }
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100142}
143
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100144void gprs_subscr_cancel(struct gsm_subscriber *subscr)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100145{
146 subscr->authorized = 0;
147 subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100148 subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100149
150 gprs_subscr_update(subscr);
Jacob Erlbeck3e4e58f2015-01-26 11:07:24 +0100151 gprs_subscr_cleanup(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100152}
153
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100154static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
155 struct gprs_gsup_message *gsup_msg)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100156{
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100157 struct msgb *msg = gprs_gsup_msgb_alloc();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100158
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100159 if (strlen(gsup_msg->imsi) == 0 && subscr)
160 strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100161
162 gprs_gsup_encode(msg, gsup_msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100163
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100164 LOGGSUBSCRP(LOGL_INFO, subscr,
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100165 "Sending GSUP, will send: %s\n", msgb_hexdump(msg));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100166
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100167 if (!sgsn->gsup_client) {
168 msgb_free(msg);
169 return -ENOTSUP;
170 }
171
172 return gprs_gsup_client_send(sgsn->gsup_client, msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100173}
174
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100175static int gprs_subscr_tx_gsup_error_reply(struct gsm_subscriber *subscr,
176 struct gprs_gsup_message *gsup_orig,
177 enum gsm48_gmm_cause cause)
178{
179 struct gprs_gsup_message gsup_reply = {0};
180
181 strncpy(gsup_reply.imsi, gsup_orig->imsi, sizeof(gsup_reply.imsi) - 1);
182 gsup_reply.cause = cause;
183 gsup_reply.message_type =
184 GPRS_GSUP_TO_MSGT_ERROR(gsup_orig->message_type);
185
186 return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
187}
188
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100189static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
190 struct gprs_gsup_message *gsup_msg)
191{
192 unsigned idx;
193 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
194
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100195 LOGGSUBSCRP(LOGL_INFO, subscr,
196 "Got SendAuthenticationInfoResult, num_auth_tuples = %d\n",
197 gsup_msg->num_auth_tuples);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100198
199 if (gsup_msg->num_auth_tuples > 0) {
200 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
201
202 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
203 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
204 }
205
206 for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) {
207 size_t key_seq = gsup_msg->auth_tuples[idx].key_seq;
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100208 LOGGSUBSCRP(LOGL_DEBUG, subscr,
209 "Adding auth tuple, cksn = %d\n", key_seq);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100210 if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) {
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100211 LOGGSUBSCRP(LOGL_NOTICE, subscr,
212 "Skipping auth triplet with invalid cksn %d\n",
213 key_seq);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100214 continue;
215 }
216 sdata->auth_triplets[key_seq] = gsup_msg->auth_tuples[idx];
217 }
218
219 sdata->auth_triplets_updated = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100220 sdata->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100221
222 gprs_subscr_update_auth_info(subscr);
223
224 return 0;
225}
226
227static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
228 struct gprs_gsup_message *gsup_msg)
229{
230 unsigned idx;
231
232 if (gsup_msg->pdp_info_compl) {
233 LOGP(DGPRS, LOGL_INFO, "Would clear existing PDP info\n");
234
235 /* TODO: clear existing PDP info entries */
236 }
237
238 for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
239 struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
240 size_t ctx_id = pdp_info->context_id;
241
242 LOGP(DGPRS, LOGL_INFO,
243 "Would set PDP info, context id = %d, APN = %s\n",
244 ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
245
246 /* TODO: set PDP info [ctx_id] */
247 }
248
249 subscr->authorized = 1;
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100250 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100251
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100252 subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE;
253
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100254 gprs_subscr_update(subscr);
255 return 0;
256}
257
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100258static int check_cause(int cause)
259{
260 switch (cause) {
261 case GMM_CAUSE_IMSI_UNKNOWN ... GMM_CAUSE_ILLEGAL_ME:
262 case GMM_CAUSE_GPRS_NOTALLOWED ... GMM_CAUSE_NO_GPRS_PLMN:
263 return EACCES;
264
265 case GMM_CAUSE_MSC_TEMP_NOTREACH ... GMM_CAUSE_CONGESTION:
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100266 return EHOSTUNREACH;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100267
268 case GMM_CAUSE_SEM_INCORR_MSG ... GMM_CAUSE_PROTO_ERR_UNSPEC:
269 default:
270 return EINVAL;
271 }
272}
273
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100274static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
275 struct gprs_gsup_message *gsup_msg)
276{
277 unsigned idx;
278 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100279 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100280
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100281 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100282
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100283 LOGGSUBSCRP(LOGL_DEBUG, subscr,
284 "Send authentication info has failed with cause %d, "
285 "handled as: %s\n",
286 gsup_msg->cause, strerror(cause_err));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100287
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100288 switch (cause_err) {
289 case EACCES:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100290 LOGGSUBSCRP(LOGL_NOTICE, subscr,
291 "GPRS send auth info req failed, access denied, "
292 "GMM cause = '%s' (%d)\n",
293 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
294 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100295 /* Clear auth tuples */
296 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
297 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
298 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100299
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100300 subscr->authorized = 0;
301 sdata->error_cause = gsup_msg->cause;
302 gprs_subscr_update_auth_info(subscr);
303 break;
304
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100305 case EHOSTUNREACH:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100306 LOGGSUBSCRP(LOGL_NOTICE, subscr,
307 "GPRS send auth info req failed, GMM cause = '%s' (%d)\n",
308 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
309 gsup_msg->cause);
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100310
311 sdata->error_cause = gsup_msg->cause;
312 gprs_subscr_update_auth_info(subscr);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100313 break;
314
315 default:
316 case EINVAL:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100317 LOGGSUBSCRP(LOGL_ERROR, subscr,
318 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
319 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
320 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100321 break;
322 }
323
324 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100325}
326
327static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
328 struct gprs_gsup_message *gsup_msg)
329{
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100330 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100331
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100332 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100333
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100334 LOGGSUBSCRP(LOGL_DEBUG, subscr,
335 "Update location has failed with cause %d, handled as: %s\n",
336 gsup_msg->cause, strerror(cause_err));
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100337
338 switch (cause_err) {
339 case EACCES:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100340 LOGGSUBSCRP(LOGL_NOTICE, subscr,
341 "GPRS update location failed, access denied, "
342 "GMM cause = '%s' (%d)\n",
343 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
344 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100345
346 subscr->authorized = 0;
347 subscr->sgsn_data->error_cause = gsup_msg->cause;
348 gprs_subscr_update_auth_info(subscr);
349 break;
350
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100351 case EHOSTUNREACH:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100352 LOGGSUBSCRP(LOGL_NOTICE, subscr,
353 "GPRS update location failed, GMM cause = '%s' (%d)\n",
354 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
355 gsup_msg->cause);
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100356
357 subscr->sgsn_data->error_cause = gsup_msg->cause;
358 gprs_subscr_update_auth_info(subscr);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100359 break;
360
361 default:
362 case EINVAL:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100363 LOGGSUBSCRP(LOGL_ERROR, subscr,
364 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
365 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
366 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100367 break;
368 }
369
370 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100371}
372
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100373static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr,
374 struct gprs_gsup_message *gsup_msg)
375{
376 LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n");
377
378 /* Force silent cancellation */
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100379 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100380 gprs_subscr_cancel(subscr);
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100381
382 return 0;
383}
384
385static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr,
386 struct gprs_gsup_message *gsup_msg)
387{
388 LOGGSUBSCRP(LOGL_NOTICE, subscr,
389 "Purge MS has failed with cause '%s' (%d)\n",
390 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
391 gsup_msg->cause);
392
393 /* In GSM 09.02, 19.1.4.4, the text and the SDL diagram imply that
394 * the subscriber data is not removed if the request has failed. On the
395 * other hand, keeping the subscriber data in either error case
396 * (subscriber unknown, syntactical message error, connection error)
397 * doesn't seem to give any advantage, since the data will be restored
398 * on the next Attach Request anyway.
399 * This approach ensures, that the subscriber record will not stick if
400 * an error happens.
401 */
402
403 /* TODO: Check whether this behaviour is acceptable and either just
404 * remove this TODO-notice or change the implementation to not delete
405 * the subscriber data (eventually resetting the ENABLE_PURGE flag and
406 * restarting the expiry timer based on the cause).
407 *
408 * Subscriber Unknown: cancel subscr
409 * Temporary network problems: do nothing (handled by timer based retry)
410 * Message problems (syntax, nyi, ...): cancel subscr (retry won't help)
411 */
412
413 gprs_subscr_handle_gsup_purge_res(subscr, gsup_msg);
414
415 return -gsup_msg->cause;
416}
417
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100418static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr,
419 struct gprs_gsup_message *gsup_msg)
420{
421 struct gprs_gsup_message gsup_reply = {0};
422
423 LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
424
425 gsup_reply.message_type = GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT;
426 gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
427
Jacob Erlbeckd6267d12015-01-19 11:10:04 +0100428 subscr->sgsn_data->error_cause = SGSN_ERROR_CAUSE_NONE;
Jacob Erlbeck37139e52015-01-23 13:52:55 +0100429 gprs_subscr_cancel(subscr);
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100430
431 return 0;
432}
433
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100434static int gprs_subscr_handle_unknown_imsi(struct gprs_gsup_message *gsup_msg)
435{
436 if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) {
437 gprs_subscr_tx_gsup_error_reply(NULL, gsup_msg,
438 GMM_CAUSE_IMSI_UNKNOWN);
439 LOGP(DGPRS, LOGL_NOTICE,
440 "Unknown IMSI %s, discarding GSUP request "
441 "of type 0x%02x\n",
442 gsup_msg->imsi, gsup_msg->message_type);
443 } else if (GPRS_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
444 LOGP(DGPRS, LOGL_NOTICE,
445 "Unknown IMSI %s, discarding GSUP error "
446 "of type 0x%02x, cause '%s' (%d)\n",
447 gsup_msg->imsi, gsup_msg->message_type,
448 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
449 gsup_msg->cause);
450 } else {
451 LOGP(DGPRS, LOGL_NOTICE,
452 "Unknown IMSI %s, discarding GSUP response "
453 "of type 0x%02x\n",
454 gsup_msg->imsi, gsup_msg->message_type);
455 }
456
457 return -GMM_CAUSE_IMSI_UNKNOWN;
458}
459
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100460int gprs_subscr_rx_gsup_message(struct msgb *msg)
461{
462 uint8_t *data = msgb_l2(msg);
463 size_t data_len = msgb_l2len(msg);
464 int rc = 0;
465
466 struct gprs_gsup_message gsup_msg = {0};
467 struct gsm_subscriber *subscr;
468
469 rc = gprs_gsup_decode(data, data_len, &gsup_msg);
470 if (rc < 0) {
471 LOGP(DGPRS, LOGL_ERROR,
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100472 "decoding GSUP message fails with error '%s' (%d)\n",
473 get_value_string(gsm48_gmm_cause_names, -rc), -rc);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100474 return rc;
475 }
476
477 if (!gsup_msg.imsi[0])
478 return -GMM_CAUSE_INV_MAND_INFO;
479
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100480 subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100481
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100482 if (!subscr)
483 return gprs_subscr_handle_unknown_imsi(&gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100484
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100485 LOGGSUBSCRP(LOGL_INFO, subscr,
486 "Received GSUP message of type 0x%02x\n", gsup_msg.message_type);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100487
488 switch (gsup_msg.message_type) {
489 case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100490 rc = gprs_subscr_handle_loc_cancel_req(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100491 break;
492
493 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100494 rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100495 break;
496
497 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100498 rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100499 break;
500
501 case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100502 rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100503 break;
504
505 case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100506 rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100507 break;
508
509 case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100510 rc = gprs_subscr_handle_gsup_purge_err(subscr, &gsup_msg);
511 break;
512
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100513 case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100514 rc = gprs_subscr_handle_gsup_purge_res(subscr, &gsup_msg);
515 break;
516
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100517 case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
518 case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100519 LOGGSUBSCRP(LOGL_ERROR, subscr,
520 "Rx GSUP message type %d not yet implemented\n",
521 gsup_msg.message_type);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100522 gprs_subscr_tx_gsup_error_reply(subscr, &gsup_msg,
523 GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100524 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
525 break;
526
527 default:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100528 LOGGSUBSCRP(LOGL_ERROR, subscr,
529 "Rx GSUP message type %d not valid at SGSN\n",
530 gsup_msg.message_type);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100531 if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
532 gprs_subscr_tx_gsup_error_reply(
533 subscr, &gsup_msg, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
534 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100535 break;
536 };
537
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100538 subscr_put(subscr);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100539
540 return rc;
541}
542
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100543int gprs_subscr_purge(struct gsm_subscriber *subscr)
544{
545 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100546 int rc;
547
548 if (!check_blocking(subscr, SGSN_SUBSCR_PROC_PURGE)) {
549 LOGGSUBSCRP(
550 LOGL_NOTICE, subscr,
551 "Cannot purge MS subscriber, blocked\n");
552 return -EAGAIN;
553 }
554
555 /* GSM 09.02, 19.4.1.4 requires other MAP requests to be blocked until
556 * this procedure is completed
557 */
558 subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_PURGE;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100559
560 LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
561
562 gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST;
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100563 rc = gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
564 if (rc < 0)
565 subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_NONE;
566
567 return rc;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100568}
569
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100570int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
571{
572 struct gprs_gsup_message gsup_msg = {0};
573
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100574 if (!check_blocking(subscr, SGSN_SUBSCR_PROC_UPD_AUTH)) {
575 LOGGSUBSCRP(
576 LOGL_NOTICE, subscr,
577 "Cannot start update auth info request procedure, blocked\n");
578 abort_blocking_procedure(subscr);
579 return -EAGAIN;
580 }
581
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100582 LOGGSUBSCRP(LOGL_INFO, subscr,
583 "subscriber auth info is not available\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100584
585 gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
586 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
587}
588
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100589int gprs_subscr_location_update(struct gsm_subscriber *subscr)
590{
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100591 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100592
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100593 if (!check_blocking(subscr, SGSN_SUBSCR_PROC_UPD_LOC)) {
594 LOGGSUBSCRP(
595 LOGL_NOTICE, subscr,
596 "Cannot start update location procedure, blocked\n");
597 abort_blocking_procedure(subscr);
598 return -EAGAIN;
599 }
600
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100601 LOGGSUBSCRP(LOGL_INFO, subscr,
602 "subscriber data is not available\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100603
604 gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
605 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100606}
607
608void gprs_subscr_update(struct gsm_subscriber *subscr)
609{
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100610 LOGGSUBSCRP(LOGL_DEBUG, subscr, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100611
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100612 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100613 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
614
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100615 if (subscr->sgsn_data->mm)
616 sgsn_update_subscriber_data(subscr->sgsn_data->mm);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100617}
618
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100619void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
620{
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100621 LOGGSUBSCRP(LOGL_DEBUG, subscr,
622 "Updating subscriber authentication info\n");
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100623
624 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
625 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
626
Jacob Erlbeck555b2e52015-01-26 13:52:42 +0100627 if (subscr->sgsn_data->mm)
628 sgsn_update_subscriber_data(subscr->sgsn_data->mm);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100629}
630
631struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100632{
633 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100634
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100635 if (mmctx->subscr)
636 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100637
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100638 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100639 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100640
641 if (!subscr) {
642 subscr = gprs_subscr_get_or_create(mmctx->imsi);
643 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100644 subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100645 }
646
647 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
648 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
649 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100650 }
651
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100652 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100653 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100654
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100655 subscr->sgsn_data->mm = mmctx;
656 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100657
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100658 return subscr;
659}
660
661int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
662{
663 struct gsm_subscriber *subscr = NULL;
664 int rc;
665
666 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
667
668 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
669
670 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
671
672 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100673 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100674 return rc;
675}
676
677int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
678{
679 struct gsm_subscriber *subscr = NULL;
680 int rc;
681
682 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
683
684 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
685
686 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
687
688 rc = gprs_subscr_query_auth_info(subscr);
689 subscr_put(subscr);
690 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100691}