blob: a30729d4d231990a878d1cd6f95ac5942a03ea15 [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{
92 /* Best effort, stop retries at least */
93 subscr->sgsn_data->retries = SGSN_SUBSCR_MAX_RETRIES;
94}
95
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +010096static void sgsn_subscriber_timeout_cb(void *subscr_);
97int gprs_subscr_purge(struct gsm_subscriber *subscr);
98
99void gprs_subscr_stop_timer(struct gsm_subscriber *subscr)
100{
101 if (subscr->sgsn_data->timer.data) {
102 osmo_timer_del(&subscr->sgsn_data->timer);
103 subscr->sgsn_data->timer.cb = NULL;
104 OSMO_ASSERT(subscr->sgsn_data->timer.data == subscr);
105 subscr->sgsn_data->timer.data = NULL;
106 subscr_put(subscr);
107 }
108}
109
110void gprs_subscr_start_timer(struct gsm_subscriber *subscr, unsigned seconds)
111{
112 if (!subscr->sgsn_data->timer.data) {
113 subscr->sgsn_data->timer.cb = sgsn_subscriber_timeout_cb;
114 subscr->sgsn_data->timer.data = subscr_get(subscr);
Jacob Erlbeck743dec42015-01-08 15:18:39 +0100115 subscr->sgsn_data->retries = 0;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100116 }
117
118 osmo_timer_schedule(&subscr->sgsn_data->timer, seconds, 0);
119}
120
121static void sgsn_subscriber_timeout_cb(void *subscr_)
122{
123 struct gsm_subscriber *subscr = subscr_;
124
125 LOGGSUBSCRP(LOGL_INFO, subscr,
126 "Expired, deleting subscriber entry\n");
127
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100128 subscr_get(subscr);
129
130 /* Check, whether to cleanup immediately */
Jacob Erlbeck743dec42015-01-08 15:18:39 +0100131 if (!(subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE) ||
132 subscr->sgsn_data->retries >= SGSN_SUBSCR_MAX_RETRIES)
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100133 goto force_cleanup;
134
135 /* Send a 'purge MS' message to the HLR */
136 if (gprs_subscr_purge(subscr) < 0)
137 goto force_cleanup;
138
139 /* Purge request has been sent */
140
Jacob Erlbeck743dec42015-01-08 15:18:39 +0100141 /* Check, whether purge is still enabled */
142 if (!(subscr->flags & GPRS_SUBSCRIBER_ENABLE_PURGE))
143 goto force_cleanup;
144
145 /* Make sure this will be tried again if there is no response in time */
146 subscr->sgsn_data->retries += 1;
147 gprs_subscr_start_timer(subscr, SGSN_SUBSCR_RETRY_INTERVAL);
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100148 subscr_put(subscr);
149 return;
150
151force_cleanup:
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100152 /* Make sure to clear blocking */
153 if (check_blocking(subscr, SGSN_SUBSCR_PROC_PURGE))
154 subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_NONE;
155
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100156 /* Make sure, the timer is cleaned up */
157 subscr->keep_in_ram = 0;
158 gprs_subscr_stop_timer(subscr);
159 /* The subscr is freed now, if the timer was the last user */
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100160 subscr_put(subscr);
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100161}
162
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100163static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
164{
165 struct sgsn_subscriber_data *sdata;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100166 int idx;
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100167
168 sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
169
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100170 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
171 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
172
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100173 return sdata;
174}
175
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100176struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
177{
178 struct gsm_subscriber *subscr;
179
180 subscr = subscr_get_or_create(NULL, imsi);
181 if (!subscr)
182 return NULL;
183
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100184 if (!subscr->sgsn_data)
185 subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
186
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100187 gprs_subscr_stop_timer(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100188
189 return subscr;
190}
191
192struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi)
193{
194 return subscr_active_by_imsi(NULL, imsi);
195}
196
197void gprs_subscr_delete(struct gsm_subscriber *subscr)
198{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100199 if (subscr->sgsn_data->mm) {
200 subscr_put(subscr->sgsn_data->mm->subscr);
201 subscr->sgsn_data->mm->subscr = NULL;
202 subscr->sgsn_data->mm = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100203 }
204
205 if ((subscr->flags & GPRS_SUBSCRIBER_CANCELLED) ||
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100206 (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT)) {
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100207 subscr->keep_in_ram = 0;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100208 gprs_subscr_stop_timer(subscr);
209 } else if (sgsn->cfg.subscriber_expiry_timeout != SGSN_TIMEOUT_NEVER) {
210 gprs_subscr_start_timer(subscr, sgsn->cfg.subscriber_expiry_timeout);
211 } else {
212 subscr->keep_in_ram = 1;
213 }
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100214
215 subscr_put(subscr);
216}
217
218void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr)
219{
220 subscr->authorized = 0;
221 subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100222 subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100223
224 gprs_subscr_update(subscr);
225
226 gprs_subscr_delete(subscr);
227}
228
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100229static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
230 struct gprs_gsup_message *gsup_msg)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100231{
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100232 struct msgb *msg = gprs_gsup_msgb_alloc();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100233
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100234 if (strlen(gsup_msg->imsi) == 0 && subscr)
235 strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100236
237 gprs_gsup_encode(msg, gsup_msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100238
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100239 LOGGSUBSCRP(LOGL_INFO, subscr,
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100240 "Sending GSUP, will send: %s\n", msgb_hexdump(msg));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100241
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100242 if (!sgsn->gsup_client) {
243 msgb_free(msg);
244 return -ENOTSUP;
245 }
246
247 return gprs_gsup_client_send(sgsn->gsup_client, msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100248}
249
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100250static int gprs_subscr_tx_gsup_error_reply(struct gsm_subscriber *subscr,
251 struct gprs_gsup_message *gsup_orig,
252 enum gsm48_gmm_cause cause)
253{
254 struct gprs_gsup_message gsup_reply = {0};
255
256 strncpy(gsup_reply.imsi, gsup_orig->imsi, sizeof(gsup_reply.imsi) - 1);
257 gsup_reply.cause = cause;
258 gsup_reply.message_type =
259 GPRS_GSUP_TO_MSGT_ERROR(gsup_orig->message_type);
260
261 return gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
262}
263
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100264static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
265 struct gprs_gsup_message *gsup_msg)
266{
267 unsigned idx;
268 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
269
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100270 LOGGSUBSCRP(LOGL_INFO, subscr,
271 "Got SendAuthenticationInfoResult, num_auth_tuples = %d\n",
272 gsup_msg->num_auth_tuples);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100273
274 if (gsup_msg->num_auth_tuples > 0) {
275 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
276
277 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
278 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
279 }
280
281 for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) {
282 size_t key_seq = gsup_msg->auth_tuples[idx].key_seq;
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100283 LOGGSUBSCRP(LOGL_DEBUG, subscr,
284 "Adding auth tuple, cksn = %d\n", key_seq);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100285 if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) {
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100286 LOGGSUBSCRP(LOGL_NOTICE, subscr,
287 "Skipping auth triplet with invalid cksn %d\n",
288 key_seq);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100289 continue;
290 }
291 sdata->auth_triplets[key_seq] = gsup_msg->auth_tuples[idx];
292 }
293
294 sdata->auth_triplets_updated = 1;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100295 sdata->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100296
297 gprs_subscr_update_auth_info(subscr);
298
299 return 0;
300}
301
302static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
303 struct gprs_gsup_message *gsup_msg)
304{
305 unsigned idx;
306
307 if (gsup_msg->pdp_info_compl) {
308 LOGP(DGPRS, LOGL_INFO, "Would clear existing PDP info\n");
309
310 /* TODO: clear existing PDP info entries */
311 }
312
313 for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
314 struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
315 size_t ctx_id = pdp_info->context_id;
316
317 LOGP(DGPRS, LOGL_INFO,
318 "Would set PDP info, context id = %d, APN = %s\n",
319 ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
320
321 /* TODO: set PDP info [ctx_id] */
322 }
323
324 subscr->authorized = 1;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100325 subscr->sgsn_data->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100326
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100327 subscr->flags |= GPRS_SUBSCRIBER_ENABLE_PURGE;
328
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100329 gprs_subscr_update(subscr);
330 return 0;
331}
332
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100333static int check_cause(int cause)
334{
335 switch (cause) {
336 case GMM_CAUSE_IMSI_UNKNOWN ... GMM_CAUSE_ILLEGAL_ME:
337 case GMM_CAUSE_GPRS_NOTALLOWED ... GMM_CAUSE_NO_GPRS_PLMN:
338 return EACCES;
339
340 case GMM_CAUSE_MSC_TEMP_NOTREACH ... GMM_CAUSE_CONGESTION:
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100341 return EHOSTUNREACH;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100342
343 case GMM_CAUSE_SEM_INCORR_MSG ... GMM_CAUSE_PROTO_ERR_UNSPEC:
344 default:
345 return EINVAL;
346 }
347}
348
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100349static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
350 struct gprs_gsup_message *gsup_msg)
351{
352 unsigned idx;
353 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100354 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100355
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100356 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100357
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100358 LOGGSUBSCRP(LOGL_DEBUG, subscr,
359 "Send authentication info has failed with cause %d, "
360 "handled as: %s\n",
361 gsup_msg->cause, strerror(cause_err));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100362
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100363 switch (cause_err) {
364 case EACCES:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100365 LOGGSUBSCRP(LOGL_NOTICE, subscr,
366 "GPRS send auth info req failed, access denied, "
367 "GMM cause = '%s' (%d)\n",
368 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
369 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100370 /* Clear auth tuples */
371 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
372 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
373 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100374
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100375 subscr->authorized = 0;
376 sdata->error_cause = gsup_msg->cause;
377 gprs_subscr_update_auth_info(subscr);
378 break;
379
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100380 case EHOSTUNREACH:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100381 LOGGSUBSCRP(LOGL_NOTICE, subscr,
382 "GPRS send auth info req failed, GMM cause = '%s' (%d)\n",
383 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
384 gsup_msg->cause);
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100385
386 sdata->error_cause = gsup_msg->cause;
387 gprs_subscr_update_auth_info(subscr);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100388 break;
389
390 default:
391 case EINVAL:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100392 LOGGSUBSCRP(LOGL_ERROR, subscr,
393 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
394 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
395 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100396 break;
397 }
398
399 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100400}
401
402static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
403 struct gprs_gsup_message *gsup_msg)
404{
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100405 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100406
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100407 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100408
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100409 LOGGSUBSCRP(LOGL_DEBUG, subscr,
410 "Update location has failed with cause %d, handled as: %s\n",
411 gsup_msg->cause, strerror(cause_err));
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100412
413 switch (cause_err) {
414 case EACCES:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100415 LOGGSUBSCRP(LOGL_NOTICE, subscr,
416 "GPRS update location failed, access denied, "
417 "GMM cause = '%s' (%d)\n",
418 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
419 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100420
421 subscr->authorized = 0;
422 subscr->sgsn_data->error_cause = gsup_msg->cause;
423 gprs_subscr_update_auth_info(subscr);
424 break;
425
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100426 case EHOSTUNREACH:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100427 LOGGSUBSCRP(LOGL_NOTICE, subscr,
428 "GPRS update location failed, GMM cause = '%s' (%d)\n",
429 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
430 gsup_msg->cause);
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100431
432 subscr->sgsn_data->error_cause = gsup_msg->cause;
433 gprs_subscr_update_auth_info(subscr);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100434 break;
435
436 default:
437 case EINVAL:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100438 LOGGSUBSCRP(LOGL_ERROR, subscr,
439 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
440 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
441 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100442 break;
443 }
444
445 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100446}
447
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100448static int gprs_subscr_handle_gsup_purge_res(struct gsm_subscriber *subscr,
449 struct gprs_gsup_message *gsup_msg)
450{
451 LOGGSUBSCRP(LOGL_INFO, subscr, "Completing purge MS\n");
452
453 /* Force silent cancellation */
454 subscr->sgsn_data->error_cause = 0;
455 gprs_subscr_put_and_cancel(subscr_get(subscr));
456
457 return 0;
458}
459
460static int gprs_subscr_handle_gsup_purge_err(struct gsm_subscriber *subscr,
461 struct gprs_gsup_message *gsup_msg)
462{
463 LOGGSUBSCRP(LOGL_NOTICE, subscr,
464 "Purge MS has failed with cause '%s' (%d)\n",
465 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
466 gsup_msg->cause);
467
468 /* In GSM 09.02, 19.1.4.4, the text and the SDL diagram imply that
469 * the subscriber data is not removed if the request has failed. On the
470 * other hand, keeping the subscriber data in either error case
471 * (subscriber unknown, syntactical message error, connection error)
472 * doesn't seem to give any advantage, since the data will be restored
473 * on the next Attach Request anyway.
474 * This approach ensures, that the subscriber record will not stick if
475 * an error happens.
476 */
477
478 /* TODO: Check whether this behaviour is acceptable and either just
479 * remove this TODO-notice or change the implementation to not delete
480 * the subscriber data (eventually resetting the ENABLE_PURGE flag and
481 * restarting the expiry timer based on the cause).
482 *
483 * Subscriber Unknown: cancel subscr
484 * Temporary network problems: do nothing (handled by timer based retry)
485 * Message problems (syntax, nyi, ...): cancel subscr (retry won't help)
486 */
487
488 gprs_subscr_handle_gsup_purge_res(subscr, gsup_msg);
489
490 return -gsup_msg->cause;
491}
492
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100493static int gprs_subscr_handle_loc_cancel_req(struct gsm_subscriber *subscr,
494 struct gprs_gsup_message *gsup_msg)
495{
496 struct gprs_gsup_message gsup_reply = {0};
497
498 LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
499
500 gsup_reply.message_type = GPRS_GSUP_MSGT_LOCATION_CANCEL_RESULT;
501 gprs_subscr_tx_gsup_message(subscr, &gsup_reply);
502
503 subscr->sgsn_data->error_cause = 0;
504 gprs_subscr_put_and_cancel(subscr_get(subscr));
505
506 return 0;
507}
508
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100509static int gprs_subscr_handle_unknown_imsi(struct gprs_gsup_message *gsup_msg)
510{
511 if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg->message_type)) {
512 gprs_subscr_tx_gsup_error_reply(NULL, gsup_msg,
513 GMM_CAUSE_IMSI_UNKNOWN);
514 LOGP(DGPRS, LOGL_NOTICE,
515 "Unknown IMSI %s, discarding GSUP request "
516 "of type 0x%02x\n",
517 gsup_msg->imsi, gsup_msg->message_type);
518 } else if (GPRS_GSUP_IS_MSGT_ERROR(gsup_msg->message_type)) {
519 LOGP(DGPRS, LOGL_NOTICE,
520 "Unknown IMSI %s, discarding GSUP error "
521 "of type 0x%02x, cause '%s' (%d)\n",
522 gsup_msg->imsi, gsup_msg->message_type,
523 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
524 gsup_msg->cause);
525 } else {
526 LOGP(DGPRS, LOGL_NOTICE,
527 "Unknown IMSI %s, discarding GSUP response "
528 "of type 0x%02x\n",
529 gsup_msg->imsi, gsup_msg->message_type);
530 }
531
532 return -GMM_CAUSE_IMSI_UNKNOWN;
533}
534
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100535int gprs_subscr_rx_gsup_message(struct msgb *msg)
536{
537 uint8_t *data = msgb_l2(msg);
538 size_t data_len = msgb_l2len(msg);
539 int rc = 0;
540
541 struct gprs_gsup_message gsup_msg = {0};
542 struct gsm_subscriber *subscr;
543
544 rc = gprs_gsup_decode(data, data_len, &gsup_msg);
545 if (rc < 0) {
546 LOGP(DGPRS, LOGL_ERROR,
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100547 "decoding GSUP message fails with error '%s' (%d)\n",
548 get_value_string(gsm48_gmm_cause_names, -rc), -rc);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100549 return rc;
550 }
551
552 if (!gsup_msg.imsi[0])
553 return -GMM_CAUSE_INV_MAND_INFO;
554
Jacob Erlbeck4dedb272015-01-15 17:50:16 +0100555 subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100556
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100557 if (!subscr)
558 return gprs_subscr_handle_unknown_imsi(&gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100559
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100560 LOGGSUBSCRP(LOGL_INFO, subscr,
561 "Received GSUP message of type 0x%02x\n", gsup_msg.message_type);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100562
563 switch (gsup_msg.message_type) {
564 case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100565 rc = gprs_subscr_handle_loc_cancel_req(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100566 break;
567
568 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100569 rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100570 break;
571
572 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100573 rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100574 break;
575
576 case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100577 rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100578 break;
579
580 case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100581 rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100582 break;
583
584 case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100585 rc = gprs_subscr_handle_gsup_purge_err(subscr, &gsup_msg);
586 break;
587
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100588 case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100589 rc = gprs_subscr_handle_gsup_purge_res(subscr, &gsup_msg);
590 break;
591
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100592 case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
593 case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100594 LOGGSUBSCRP(LOGL_ERROR, subscr,
595 "Rx GSUP message type %d not yet implemented\n",
596 gsup_msg.message_type);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100597 gprs_subscr_tx_gsup_error_reply(subscr, &gsup_msg,
598 GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100599 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
600 break;
601
602 default:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100603 LOGGSUBSCRP(LOGL_ERROR, subscr,
604 "Rx GSUP message type %d not valid at SGSN\n",
605 gsup_msg.message_type);
Jacob Erlbeck9999fd92015-01-15 17:08:30 +0100606 if (GPRS_GSUP_IS_MSGT_REQUEST(gsup_msg.message_type))
607 gprs_subscr_tx_gsup_error_reply(
608 subscr, &gsup_msg, GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL);
609 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100610 break;
611 };
612
Jacob Erlbeck87c7ffc2015-01-08 15:29:01 +0100613 subscr_put(subscr);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100614
615 return rc;
616}
617
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100618int gprs_subscr_purge(struct gsm_subscriber *subscr)
619{
620 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100621 int rc;
622
623 if (!check_blocking(subscr, SGSN_SUBSCR_PROC_PURGE)) {
624 LOGGSUBSCRP(
625 LOGL_NOTICE, subscr,
626 "Cannot purge MS subscriber, blocked\n");
627 return -EAGAIN;
628 }
629
630 /* GSM 09.02, 19.4.1.4 requires other MAP requests to be blocked until
631 * this procedure is completed
632 */
633 subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_PURGE;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100634
635 LOGGSUBSCRP(LOGL_INFO, subscr, "purging MS subscriber\n");
636
637 gsup_msg.message_type = GPRS_GSUP_MSGT_PURGE_MS_REQUEST;
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100638 rc = gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
639 if (rc < 0)
640 subscr->sgsn_data->blocked_by = SGSN_SUBSCR_PROC_NONE;
641
642 return rc;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100643}
644
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100645int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
646{
647 struct gprs_gsup_message gsup_msg = {0};
648
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100649 if (!check_blocking(subscr, SGSN_SUBSCR_PROC_UPD_AUTH)) {
650 LOGGSUBSCRP(
651 LOGL_NOTICE, subscr,
652 "Cannot start update auth info request procedure, blocked\n");
653 abort_blocking_procedure(subscr);
654 return -EAGAIN;
655 }
656
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100657 LOGGSUBSCRP(LOGL_INFO, subscr,
658 "subscriber auth info is not available\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100659
660 gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
661 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
662}
663
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100664int gprs_subscr_location_update(struct gsm_subscriber *subscr)
665{
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100666 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100667
Jacob Erlbeckf81cacc2015-01-08 16:23:25 +0100668 if (!check_blocking(subscr, SGSN_SUBSCR_PROC_UPD_LOC)) {
669 LOGGSUBSCRP(
670 LOGL_NOTICE, subscr,
671 "Cannot start update location procedure, blocked\n");
672 abort_blocking_procedure(subscr);
673 return -EAGAIN;
674 }
675
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100676 LOGGSUBSCRP(LOGL_INFO, subscr,
677 "subscriber data is not available\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100678
679 gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
680 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100681}
682
683void gprs_subscr_update(struct gsm_subscriber *subscr)
684{
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100685 LOGGSUBSCRP(LOGL_DEBUG, subscr, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100686
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100687 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100688 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
689
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100690 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100691}
692
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100693void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
694{
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100695 LOGGSUBSCRP(LOGL_DEBUG, subscr,
696 "Updating subscriber authentication info\n");
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100697
698 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
699 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
700
701 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
702}
703
704struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100705{
706 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100707
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100708 if (mmctx->subscr)
709 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100710
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100711 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100712 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100713
714 if (!subscr) {
715 subscr = gprs_subscr_get_or_create(mmctx->imsi);
716 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck65fa3f72015-01-06 16:32:41 +0100717 subscr->flags &= ~GPRS_SUBSCRIBER_ENABLE_PURGE;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100718 }
719
720 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
721 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
722 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100723 }
724
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100725 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100726 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100727
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100728 subscr->sgsn_data->mm = mmctx;
729 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100730
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100731 return subscr;
732}
733
734int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
735{
736 struct gsm_subscriber *subscr = NULL;
737 int rc;
738
739 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
740
741 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
742
743 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
744
745 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100746 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100747 return rc;
748}
749
750int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
751{
752 struct gsm_subscriber *subscr = NULL;
753 int rc;
754
755 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
756
757 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
758
759 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
760
761 rc = gprs_subscr_query_auth_info(subscr);
762 subscr_put(subscr);
763 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100764}