blob: 9d79f000687efa8e119856cf474bef904a7505c6 [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 Erlbeck0f47b8f2015-01-06 16:32:41 +010076static void sgsn_subscriber_timeout_cb(void *subscr_);
77int gprs_subscr_purge(struct gsm_subscriber *subscr);
78
79void gprs_subscr_stop_timer(struct gsm_subscriber *subscr)
80{
81 if (subscr->sgsn_data->timer.data) {
82 osmo_timer_del(&subscr->sgsn_data->timer);
83 subscr->sgsn_data->timer.cb = NULL;
84 OSMO_ASSERT(subscr->sgsn_data->timer.data == subscr);
85 subscr->sgsn_data->timer.data = NULL;
86 subscr_put(subscr);
87 }
88}
89
90void gprs_subscr_start_timer(struct gsm_subscriber *subscr, unsigned seconds)
91{
92 if (!subscr->sgsn_data->timer.data) {
93 subscr->sgsn_data->timer.cb = sgsn_subscriber_timeout_cb;
94 subscr->sgsn_data->timer.data = subscr_get(subscr);
95 }
96
97 osmo_timer_schedule(&subscr->sgsn_data->timer, seconds, 0);
98}
99
100static void sgsn_subscriber_timeout_cb(void *subscr_)
101{
102 struct gsm_subscriber *subscr = subscr_;
103
104 LOGGSUBSCRP(LOGL_INFO, subscr,
105 "Expired, deleting subscriber entry\n");
106
107 /* Make sure, the timer is cleaned up */
108 subscr->keep_in_ram = 0;
109 gprs_subscr_stop_timer(subscr);
110 /* The subscr is freed now, if the timer was the last user */
111}
112
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100113static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
114{
115 struct sgsn_subscriber_data *sdata;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100116 int idx;
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100117
118 sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
119
Jacob Erlbeck7921ab12014-12-08 15:52:00 +0100120 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
121 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
122
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100123 return sdata;
124}
125
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100126struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
127{
128 struct gsm_subscriber *subscr;
129
130 subscr = subscr_get_or_create(NULL, imsi);
131 if (!subscr)
132 return NULL;
133
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100134 if (!subscr->sgsn_data)
135 subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
136
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100137 gprs_subscr_stop_timer(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100138
139 return subscr;
140}
141
142struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi)
143{
144 return subscr_active_by_imsi(NULL, imsi);
145}
146
147void gprs_subscr_delete(struct gsm_subscriber *subscr)
148{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100149 if (subscr->sgsn_data->mm) {
150 subscr_put(subscr->sgsn_data->mm->subscr);
151 subscr->sgsn_data->mm->subscr = NULL;
152 subscr->sgsn_data->mm = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100153 }
154
155 if ((subscr->flags & GPRS_SUBSCRIBER_CANCELLED) ||
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100156 (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT)) {
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100157 subscr->keep_in_ram = 0;
Jacob Erlbeck0f47b8f2015-01-06 16:32:41 +0100158 gprs_subscr_stop_timer(subscr);
159 } else if (sgsn->cfg.subscriber_expiry_timeout != SGSN_TIMEOUT_NEVER) {
160 gprs_subscr_start_timer(subscr, sgsn->cfg.subscriber_expiry_timeout);
161 } else {
162 subscr->keep_in_ram = 1;
163 }
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100164
165 subscr_put(subscr);
166}
167
168void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr)
169{
170 subscr->authorized = 0;
171 subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
172
173 gprs_subscr_update(subscr);
174
175 gprs_subscr_delete(subscr);
176}
177
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100178static int gprs_subscr_tx_gsup_message(struct gsm_subscriber *subscr,
179 struct gprs_gsup_message *gsup_msg)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100180{
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100181 struct msgb *msg = gprs_gsup_msgb_alloc();
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100182
183 strncpy(gsup_msg->imsi, subscr->imsi, sizeof(gsup_msg->imsi) - 1);
184
185 gprs_gsup_encode(msg, gsup_msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100186
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100187 LOGGSUBSCRP(LOGL_INFO, subscr,
188 "Sending GSUP, will send: %s\n", msgb_hexdump(msg));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100189
Jacob Erlbeck39f040d2014-12-18 12:46:47 +0100190 if (!sgsn->gsup_client) {
191 msgb_free(msg);
192 return -ENOTSUP;
193 }
194
195 return gprs_gsup_client_send(sgsn->gsup_client, msg);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100196}
197
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100198static int gprs_subscr_handle_gsup_auth_res(struct gsm_subscriber *subscr,
199 struct gprs_gsup_message *gsup_msg)
200{
201 unsigned idx;
202 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
203
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100204 LOGGSUBSCRP(LOGL_INFO, subscr,
205 "Got SendAuthenticationInfoResult, num_auth_tuples = %d\n",
206 gsup_msg->num_auth_tuples);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100207
208 if (gsup_msg->num_auth_tuples > 0) {
209 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
210
211 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
212 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
213 }
214
215 for (idx = 0; idx < gsup_msg->num_auth_tuples; idx++) {
216 size_t key_seq = gsup_msg->auth_tuples[idx].key_seq;
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100217 LOGGSUBSCRP(LOGL_DEBUG, subscr,
218 "Adding auth tuple, cksn = %d\n", key_seq);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100219 if (key_seq >= ARRAY_SIZE(sdata->auth_triplets)) {
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100220 LOGGSUBSCRP(LOGL_NOTICE, subscr,
221 "Skipping auth triplet with invalid cksn %d\n",
222 key_seq);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100223 continue;
224 }
225 sdata->auth_triplets[key_seq] = gsup_msg->auth_tuples[idx];
226 }
227
228 sdata->auth_triplets_updated = 1;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100229 sdata->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100230
231 gprs_subscr_update_auth_info(subscr);
232
233 return 0;
234}
235
236static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
237 struct gprs_gsup_message *gsup_msg)
238{
239 unsigned idx;
240
241 if (gsup_msg->pdp_info_compl) {
242 LOGP(DGPRS, LOGL_INFO, "Would clear existing PDP info\n");
243
244 /* TODO: clear existing PDP info entries */
245 }
246
247 for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
248 struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
249 size_t ctx_id = pdp_info->context_id;
250
251 LOGP(DGPRS, LOGL_INFO,
252 "Would set PDP info, context id = %d, APN = %s\n",
253 ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
254
255 /* TODO: set PDP info [ctx_id] */
256 }
257
258 subscr->authorized = 1;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100259 subscr->sgsn_data->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100260
261 gprs_subscr_update(subscr);
262 return 0;
263}
264
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100265static int check_cause(int cause)
266{
267 switch (cause) {
268 case GMM_CAUSE_IMSI_UNKNOWN ... GMM_CAUSE_ILLEGAL_ME:
269 case GMM_CAUSE_GPRS_NOTALLOWED ... GMM_CAUSE_NO_GPRS_PLMN:
270 return EACCES;
271
272 case GMM_CAUSE_MSC_TEMP_NOTREACH ... GMM_CAUSE_CONGESTION:
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100273 return EHOSTUNREACH;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100274
275 case GMM_CAUSE_SEM_INCORR_MSG ... GMM_CAUSE_PROTO_ERR_UNSPEC:
276 default:
277 return EINVAL;
278 }
279}
280
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100281static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
282 struct gprs_gsup_message *gsup_msg)
283{
284 unsigned idx;
285 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100286 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100287
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100288 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100289
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100290 LOGGSUBSCRP(LOGL_DEBUG, subscr,
291 "Send authentication info has failed with cause %d, "
292 "handled as: %s\n",
293 gsup_msg->cause, strerror(cause_err));
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100294
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100295 switch (cause_err) {
296 case EACCES:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100297 LOGGSUBSCRP(LOGL_NOTICE, subscr,
298 "GPRS send auth info req failed, access denied, "
299 "GMM cause = '%s' (%d)\n",
300 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
301 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100302 /* Clear auth tuples */
303 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
304 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
305 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100306
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100307 subscr->authorized = 0;
308 sdata->error_cause = gsup_msg->cause;
309 gprs_subscr_update_auth_info(subscr);
310 break;
311
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100312 case EHOSTUNREACH:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100313 LOGGSUBSCRP(LOGL_NOTICE, subscr,
314 "GPRS send auth info req failed, GMM cause = '%s' (%d)\n",
315 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
316 gsup_msg->cause);
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100317
318 sdata->error_cause = gsup_msg->cause;
319 gprs_subscr_update_auth_info(subscr);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100320 break;
321
322 default:
323 case EINVAL:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100324 LOGGSUBSCRP(LOGL_ERROR, subscr,
325 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
326 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
327 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100328 break;
329 }
330
331 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100332}
333
334static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
335 struct gprs_gsup_message *gsup_msg)
336{
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100337 int cause_err;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100338
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100339 cause_err = check_cause(gsup_msg->cause);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100340
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100341 LOGGSUBSCRP(LOGL_DEBUG, subscr,
342 "Update location has failed with cause %d, handled as: %s\n",
343 gsup_msg->cause, strerror(cause_err));
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100344
345 switch (cause_err) {
346 case EACCES:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100347 LOGGSUBSCRP(LOGL_NOTICE, subscr,
348 "GPRS update location failed, access denied, "
349 "GMM cause = '%s' (%d)\n",
350 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
351 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100352
353 subscr->authorized = 0;
354 subscr->sgsn_data->error_cause = gsup_msg->cause;
355 gprs_subscr_update_auth_info(subscr);
356 break;
357
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100358 case EHOSTUNREACH:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100359 LOGGSUBSCRP(LOGL_NOTICE, subscr,
360 "GPRS update location failed, GMM cause = '%s' (%d)\n",
361 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
362 gsup_msg->cause);
Jacob Erlbeckf06fe292015-01-05 16:20:47 +0100363
364 subscr->sgsn_data->error_cause = gsup_msg->cause;
365 gprs_subscr_update_auth_info(subscr);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100366 break;
367
368 default:
369 case EINVAL:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100370 LOGGSUBSCRP(LOGL_ERROR, subscr,
371 "GSUP protocol remote error, GMM cause = '%s' (%d)\n",
372 get_value_string(gsm48_gmm_cause_names, gsup_msg->cause),
373 gsup_msg->cause);
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100374 break;
375 }
376
377 return -gsup_msg->cause;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100378}
379
380int gprs_subscr_rx_gsup_message(struct msgb *msg)
381{
382 uint8_t *data = msgb_l2(msg);
383 size_t data_len = msgb_l2len(msg);
384 int rc = 0;
385
386 struct gprs_gsup_message gsup_msg = {0};
387 struct gsm_subscriber *subscr;
388
389 rc = gprs_gsup_decode(data, data_len, &gsup_msg);
390 if (rc < 0) {
391 LOGP(DGPRS, LOGL_ERROR,
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100392 "decoding GSUP message fails with error '%s' (%d)\n",
393 get_value_string(gsm48_gmm_cause_names, -rc), -rc);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100394 return rc;
395 }
396
397 if (!gsup_msg.imsi[0])
398 return -GMM_CAUSE_INV_MAND_INFO;
399
400 if (gsup_msg.message_type == GPRS_GSUP_MSGT_INSERT_DATA_REQUEST)
401 subscr = gprs_subscr_get_or_create(gsup_msg.imsi);
402 else
403 subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
404
405 if (!subscr) {
406 LOGP(DGPRS, LOGL_NOTICE,
407 "Unknown IMSI %s, discarding GSUP message\n", gsup_msg.imsi);
408 return -GMM_CAUSE_IMSI_UNKNOWN;
409 }
410
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100411 LOGGSUBSCRP(LOGL_INFO, subscr,
412 "Received GSUP message of type 0x%02x\n", gsup_msg.message_type);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100413
414 switch (gsup_msg.message_type) {
415 case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
Jacob Erlbeck9aa99912015-01-05 18:38:41 +0100416 subscr->sgsn_data->error_cause = 0;
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100417 gprs_subscr_put_and_cancel(subscr);
418 subscr = NULL;
419 break;
420
421 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100422 rc = gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100423 break;
424
425 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100426 rc = gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100427 break;
428
429 case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100430 rc = gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100431 break;
432
433 case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
Jacob Erlbeckbce20612015-01-05 18:57:32 +0100434 rc = gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100435 break;
436
437 case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
438 case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
439 case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
440 case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100441 LOGGSUBSCRP(LOGL_ERROR, subscr,
442 "Rx GSUP message type %d not yet implemented\n",
443 gsup_msg.message_type);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100444 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
445 break;
446
447 default:
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100448 LOGGSUBSCRP(LOGL_ERROR, subscr,
449 "Rx GSUP message type %d not valid at SGSN\n",
450 gsup_msg.message_type);
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100451 rc = -GMM_CAUSE_MSGT_INCOMP_P_STATE;
452 break;
453 };
454
455 if (subscr)
456 subscr_put(subscr);
457
458 return rc;
459}
460
461int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
462{
463 struct gprs_gsup_message gsup_msg = {0};
464
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100465 LOGGSUBSCRP(LOGL_INFO, subscr,
466 "subscriber auth info is not available\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100467
468 gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
469 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
470}
471
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100472int gprs_subscr_location_update(struct gsm_subscriber *subscr)
473{
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100474 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100475
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100476 LOGGSUBSCRP(LOGL_INFO, subscr,
477 "subscriber data is not available\n");
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100478
479 gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
480 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100481}
482
483void gprs_subscr_update(struct gsm_subscriber *subscr)
484{
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100485 LOGGSUBSCRP(LOGL_DEBUG, subscr, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100486
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100487 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100488 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
489
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100490 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100491}
492
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100493void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
494{
Jacob Erlbeckbf34c672014-12-23 14:24:16 +0100495 LOGGSUBSCRP(LOGL_DEBUG, subscr,
496 "Updating subscriber authentication info\n");
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100497
498 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
499 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
500
501 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
502}
503
504struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100505{
506 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100507
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100508 if (mmctx->subscr)
509 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100510
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100511 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100512 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100513
514 if (!subscr) {
515 subscr = gprs_subscr_get_or_create(mmctx->imsi);
516 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100517 }
518
519 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
520 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
521 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100522 }
523
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100524 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100525 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100526
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100527 subscr->sgsn_data->mm = mmctx;
528 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100529
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100530 return subscr;
531}
532
533int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
534{
535 struct gsm_subscriber *subscr = NULL;
536 int rc;
537
538 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
539
540 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
541
542 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
543
544 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100545 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100546 return rc;
547}
548
549int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
550{
551 struct gsm_subscriber *subscr = NULL;
552 int rc;
553
554 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
555
556 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
557
558 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
559
560 rc = gprs_subscr_query_auth_info(subscr);
561 subscr_put(subscr);
562 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100563}