blob: 136ac28fbd8b5ac66083aab0f7f9b89e41141acf [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,
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100342 "decoding GSUP message fails with error '%s' (%d)\n",
343 get_value_string(gsm48_gmm_cause_names, -rc), -rc);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100344 return rc;
345 }
346
347 if (!gsup_msg.imsi[0])
348 return -GMM_CAUSE_INV_MAND_INFO;
349
350 if (gsup_msg.message_type == GPRS_GSUP_MSGT_INSERT_DATA_REQUEST)
351 subscr = gprs_subscr_get_or_create(gsup_msg.imsi);
352 else
353 subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
354
355 if (!subscr) {
356 LOGP(DGPRS, LOGL_NOTICE,
357 "Unknown IMSI %s, discarding GSUP message\n", gsup_msg.imsi);
358 return -GMM_CAUSE_IMSI_UNKNOWN;
359 }
360
361 LOGP(DGPRS, LOGL_INFO,
362 "Received GSUP message of type 0x%02x for IMSI %s\n",
363 gsup_msg.message_type, gsup_msg.imsi);
364
365 switch (gsup_msg.message_type) {
366 case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100367 subscr->sgsn_data->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100368 gprs_subscr_put_and_cancel(subscr);
369 subscr = NULL;
370 break;
371
372 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100373 rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100374 break;
375
376 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100377 rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100378 break;
379
380 case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100381 rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100382 break;
383
384 case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100385 rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100386 break;
387
388 case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
389 case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
390 case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
391 case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
392 LOGP(DGPRS, LOGL_ERROR,
393 "Rx GSUP message type %d not yet implemented\n",
394 gsup_msg.message_type);
395 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
396 break;
397
398 default:
399 LOGP(DGPRS, LOGL_ERROR,
400 "Rx GSUP message type %d not valid at SGSN\n",
401 gsup_msg.message_type);
402 rc = -GMM_CAUSE_MSGT_INCOMP_P_STATE;
403 break;
404 };
405
406 if (subscr)
407 subscr_put(subscr);
408
409 return rc;
410}
411
412int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
413{
414 struct gprs_gsup_message gsup_msg = {0};
415
416 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
417 "subscriber auth info is not available\n");
418
419 gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
420 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
421}
422
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100423int gprs_subscr_location_update(struct gsm_subscriber *subscr)
424{
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100425 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100426
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100427 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100428 "subscriber data is not available\n");
429
430 gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
431 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100432}
433
434void gprs_subscr_update(struct gsm_subscriber *subscr)
435{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100436 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100437
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100438 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100439 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
440
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100441 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100442}
443
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100444void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
445{
446 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
447 "Updating subscriber authentication info\n");
448
449 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
450 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
451
452 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
453}
454
455struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100456{
457 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100458
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100459 if (mmctx->subscr)
460 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100461
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100462 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100463 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100464
465 if (!subscr) {
466 subscr = gprs_subscr_get_or_create(mmctx->imsi);
467 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100468 }
469
470 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
471 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
472 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100473 }
474
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100475 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100476 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100477
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100478 subscr->sgsn_data->mm = mmctx;
479 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100480
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100481 return subscr;
482}
483
484int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
485{
486 struct gsm_subscriber *subscr = NULL;
487 int rc;
488
489 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
490
491 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
492
493 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
494
495 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100496 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100497 return rc;
498}
499
500int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
501{
502 struct gsm_subscriber *subscr = NULL;
503 int rc;
504
505 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
506
507 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
508
509 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
510
511 rc = gprs_subscr_query_auth_info(subscr);
512 subscr_put(subscr);
513 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100514}