blob: fd16fa3ef1bb0135f247d13a67b1997155aa705f [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 Erlbeck33b6dad2014-11-12 10:12:11 +010035extern void *tall_bsc_ctx;
36
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010037static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg);
38
39/* TODO: Some functions are specific to the SGSN, but this file is more general
40 * (it has gprs_* name). Either move these functions elsewhere, split them and
41 * move a part, or replace the gprs_ prefix by sgsn_. The applies to
42 * gprs_subscr_init, gsup_read_cb, and gprs_subscr_tx_gsup_message.
43 */
44
45int gprs_subscr_init(struct sgsn_instance *sgi)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010046{
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010047 const char *addr_str;
48
49 if (!sgi->cfg.gsup_server_addr.sin_addr.s_addr)
50 return 0;
51
52 addr_str = inet_ntoa(sgi->cfg.gsup_server_addr.sin_addr);
53
54 sgi->gsup_client = gprs_gsup_client_create(
55 addr_str, sgi->cfg.gsup_server_port,
56 &gsup_read_cb);
57
58 if (!sgi->gsup_client)
59 return -1;
60
61 return 1;
62}
63
64static int gsup_read_cb(struct gprs_gsup_client *gsupc, struct msgb *msg)
65{
66 int rc;
67
68 rc = gprs_subscr_rx_gsup_message(msg);
Jacob Erlbecke154d8b2014-12-19 19:15:55 +010069 msgb_free(msg);
Jacob Erlbeck39f040d2014-12-18 12:46:47 +010070 if (rc < 0)
71 return -1;
72
73 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010074}
75
Jacob Erlbecka1e03732014-12-02 11:28:38 +010076static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
77{
78 struct sgsn_subscriber_data *sdata;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +010079 int idx;
Jacob Erlbecka1e03732014-12-02 11:28:38 +010080
81 sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
82
Jacob Erlbeck7921ab12014-12-08 15:52:00 +010083 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
84 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
85
Jacob Erlbecka1e03732014-12-02 11:28:38 +010086 return sdata;
87}
88
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010089struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
90{
91 struct gsm_subscriber *subscr;
92
93 subscr = subscr_get_or_create(NULL, imsi);
94 if (!subscr)
95 return NULL;
96
Jacob Erlbecka1e03732014-12-02 11:28:38 +010097 if (!subscr->sgsn_data)
98 subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
99
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100100 subscr->keep_in_ram = 1;
101
102 return subscr;
103}
104
105struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi)
106{
107 return subscr_active_by_imsi(NULL, imsi);
108}
109
110void gprs_subscr_delete(struct gsm_subscriber *subscr)
111{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100112 if (subscr->sgsn_data->mm) {
113 subscr_put(subscr->sgsn_data->mm->subscr);
114 subscr->sgsn_data->mm->subscr = NULL;
115 subscr->sgsn_data->mm = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100116 }
117
118 if ((subscr->flags & GPRS_SUBSCRIBER_CANCELLED) ||
119 (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT))
120 subscr->keep_in_ram = 0;
121
122 subscr_put(subscr);
123}
124
125void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr)
126{
127 subscr->authorized = 0;
128 subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
129
130 gprs_subscr_update(subscr);
131
132 gprs_subscr_delete(subscr);
133}
134
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100135static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
136 struct gprs_gsup_message *gsup_msg)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100137{
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100138 struct msgb *msg = gprs_gsup_msgb_alloc();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100139
140 strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1);
141
142 gprs_gsup_encode(msg, gsup_msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100143
144 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100145 "Sending GSUP, will send: %s\n", msgb_hexdump(msg));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100146
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100147 if (!sgsn->gsup_client) {
148 msgb_free(msg);
149 return -ENOTSUP;
150 }
151
152 return gprs_gsup_client_send(sgsn->gsup_client, msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100153}
154
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100155static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
156 struct gprs_gsup_message *gsup_msg)
157{
158 unsigned idx;
159 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
160
161 LOGP(DGPRS, LOGL_INFO,
162 "Got SendAuthenticationInfoResult, num_auth_tuples = %d\n",
163 gsup_msg->num_auth_tuples);
164
165 if (gsup_msg->num_auth_tuples > 0) {
166 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
167
168 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
169 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
170 }
171
172 for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) {
173 size_t key_seq = gsup_msg->auth_tuples[idx].key_seq;
174 LOGP(DGPRS, LOGL_DEBUG, "Adding auth tuple, cksn = %d\n", key_seq);
175 if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) {
176 LOGP(DGPRS, LOGL_NOTICE,
177 "Skipping auth triplet with invalid cksn %d\n",
178 key_seq);
179 continue;
180 }
181 sdata->auth_triplets[key_seq] = gsup_msg->auth_tuples[idx];
182 }
183
184 sdata->auth_triplets_updated = 1;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100185 sdata->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100186
187 gprs_subscr_update_auth_info(subscr);
188
189 return 0;
190}
191
192static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
193 struct gprs_gsup_message *gsup_msg)
194{
195 unsigned idx;
196
197 if (gsup_msg->pdp_info_compl) {
198 LOGP(DGPRS, LOGL_INFO, "Would clear existing PDP info\n");
199
200 /* TODO: clear existing PDP info entries */
201 }
202
203 for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
204 struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
205 size_t ctx_id = pdp_info->context_id;
206
207 LOGP(DGPRS, LOGL_INFO,
208 "Would set PDP info, context id = %d, APN = %s\n",
209 ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
210
211 /* TODO: set PDP info [ctx_id] */
212 }
213
214 subscr->authorized = 1;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100215 subscr->sgsn_data->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100216
217 gprs_subscr_update(subscr);
218 return 0;
219}
220
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100221static int check_cause(int cause)
222{
223 switch (cause) {
224 case GMM_CAUSE_IMSI_UNKNOWN ... GMM_CAUSE_ILLEGAL_ME:
225 case GMM_CAUSE_GPRS_NOTALLOWED ... GMM_CAUSE_NO_GPRS_PLMN:
226 return EACCES;
227
228 case GMM_CAUSE_MSC_TEMP_NOTREACH ... GMM_CAUSE_CONGESTION:
229 return EAGAIN;
230
231 case GMM_CAUSE_SEM_INCORR_MSG ... GMM_CAUSE_PROTO_ERR_UNSPEC:
232 default:
233 return EINVAL;
234 }
235}
236
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100237static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
238 struct gprs_gsup_message *gsup_msg)
239{
240 unsigned idx;
241 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100242 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100243
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100244 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100245
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100246 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
247 "Send authentication info has failed with cause %d, "
248 "handled as: %s\n",
249 gsup_msg->cause, strerror(cause_err));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100250
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100251 switch (cause_err) {
252 case EACCES:
253 LOGMMCTXP(LOGL_NOTICE, subscr->sgsn_data->mm,
254 "GPRS send auth info req failed, access denied, "
255 "GMM cause = '%s' (%d)\n",
256 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
257 gsup_msg->cause);
258 /* Clear auth tuples */
259 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
260 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
261 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100262
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100263 subscr->authorized = 0;
264 sdata->error_cause = gsup_msg->cause;
265 gprs_subscr_update_auth_info(subscr);
266 break;
267
268 case EAGAIN:
269 LOGMMCTXP(LOGL_NOTICE, subscr->sgsn_data->mm,
270 "GPRS send auth info req failed, GMM cause = '%s' (%d)\n",
271 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
272 gsup_msg->cause);
273 break;
274
275 default:
276 case EINVAL:
277 LOGMMCTXP(LOGL_ERROR, subscr->sgsn_data->mm,
278 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
279 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
280 gsup_msg->cause);
281 break;
282 }
283
284 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100285}
286
287static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
288 struct gprs_gsup_message *gsup_msg)
289{
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100290 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100291
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100292 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100293
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100294 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
295 "Update location has failed with cause %d, handled as: %s\n",
296 gsup_msg->cause, strerror(cause_err));
297
298 switch (cause_err) {
299 case EACCES:
300 LOGMMCTXP(LOGL_NOTICE, subscr->sgsn_data->mm,
301 "GPRS update location failed, access denied, "
302 "GMM cause = '%s' (%d)\n",
303 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
304 gsup_msg->cause);
305
306 subscr->authorized = 0;
307 subscr->sgsn_data->error_cause = gsup_msg->cause;
308 gprs_subscr_update_auth_info(subscr);
309 break;
310
311 case EAGAIN:
312 LOGMMCTXP(LOGL_NOTICE, subscr->sgsn_data->mm,
313 "GPRS update location failed, GMM cause = '%s' (%d)\n",
314 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
315 gsup_msg->cause);
316 break;
317
318 default:
319 case EINVAL:
320 LOGMMCTXP(LOGL_ERROR, subscr->sgsn_data->mm,
321 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
322 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
323 gsup_msg->cause);
324 break;
325 }
326
327 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100328}
329
330int gprs_subscr_rx_gsup_message(struct msgb *msg)
331{
332 uint8_t *data = msgb_l2(msg);
333 size_t data_len = msgb_l2len(msg);
334 int rc = 0;
335
336 struct gprs_gsup_message gsup_msg = {0};
337 struct gsm_subscriber *subscr;
338
339 rc = gprs_gsup_decode(data, data_len, &gsup_msg);
340 if (rc < 0) {
341 LOGP(DGPRS, LOGL_ERROR,
342 "decoding GSUP message fails with error code %d\n", -rc);
343 return rc;
344 }
345
346 if (!gsup_msg.imsi[0])
347 return -GMM_CAUSE_INV_MAND_INFO;
348
349 if (gsup_msg.message_type == GPRS_GSUP_MSGT_INSERT_DATA_REQUEST)
350 subscr = gprs_subscr_get_or_create(gsup_msg.imsi);
351 else
352 subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
353
354 if (!subscr) {
355 LOGP(DGPRS, LOGL_NOTICE,
356 "Unknown IMSI %s, discarding GSUP message\n", gsup_msg.imsi);
357 return -GMM_CAUSE_IMSI_UNKNOWN;
358 }
359
360 LOGP(DGPRS, LOGL_INFO,
361 "Received GSUP message of type 0x%02x for IMSI %s\n",
362 gsup_msg.message_type, gsup_msg.imsi);
363
364 switch (gsup_msg.message_type) {
365 case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100366 subscr->sgsn_data->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100367 gprs_subscr_put_and_cancel(subscr);
368 subscr = NULL;
369 break;
370
371 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
372 gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
373 break;
374
375 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
376 gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
377 break;
378
379 case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
380 gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
381 break;
382
383 case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
384 gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
385 break;
386
387 case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
388 case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
389 case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
390 case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
391 LOGP(DGPRS, LOGL_ERROR,
392 "Rx GSUP message type %d not yet implemented\n",
393 gsup_msg.message_type);
394 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
395 break;
396
397 default:
398 LOGP(DGPRS, LOGL_ERROR,
399 "Rx GSUP message type %d not valid at SGSN\n",
400 gsup_msg.message_type);
401 rc = -GMM_CAUSE_MSGT_INCOMP_P_STATE;
402 break;
403 };
404
405 if (subscr)
406 subscr_put(subscr);
407
408 return rc;
409}
410
411int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
412{
413 struct gprs_gsup_message gsup_msg = {0};
414
415 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
416 "subscriber auth info is not available\n");
417
418 gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
419 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
420}
421
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100422int gprs_subscr_location_update(struct gsm_subscriber *subscr)
423{
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100424 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100425
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100426 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100427 "subscriber data is not available\n");
428
429 gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
430 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100431}
432
433void gprs_subscr_update(struct gsm_subscriber *subscr)
434{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100435 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100436
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100437 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100438 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
439
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100440 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100441}
442
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100443void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
444{
445 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
446 "Updating subscriber authentication info\n");
447
448 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
449 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
450
451 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
452}
453
454struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100455{
456 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100457
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100458 if (mmctx->subscr)
459 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100460
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100461 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100462 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100463
464 if (!subscr) {
465 subscr = gprs_subscr_get_or_create(mmctx->imsi);
466 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100467 }
468
469 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
470 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
471 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100472 }
473
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100474 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100475 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100476
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100477 subscr->sgsn_data->mm = mmctx;
478 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100479
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100480 return subscr;
481}
482
483int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
484{
485 struct gsm_subscriber *subscr = NULL;
486 int rc;
487
488 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
489
490 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
491
492 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
493
494 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100495 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100496 return rc;
497}
498
499int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
500{
501 struct gsm_subscriber *subscr = NULL;
502 int rc;
503
504 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
505
506 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
507
508 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
509
510 rc = gprs_subscr_query_auth_info(subscr);
511 subscr_put(subscr);
512 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100513}