blob: 2f3ae96dee1ec3195b5d63a28204a5324da195a1 [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;
185
186 gprs_subscr_update_auth_info(subscr);
187
188 return 0;
189}
190
191static int gprs_subscr_handle_gsup_upd_loc_res(struct gsm_subscriber *subscr,
192 struct gprs_gsup_message *gsup_msg)
193{
194 unsigned idx;
195
196 if (gsup_msg->pdp_info_compl) {
197 LOGP(DGPRS, LOGL_INFO, "Would clear existing PDP info\n");
198
199 /* TODO: clear existing PDP info entries */
200 }
201
202 for (idx = 0; idx < gsup_msg->num_pdp_infos; idx++) {
203 struct gprs_gsup_pdp_info *pdp_info = &gsup_msg->pdp_infos[idx];
204 size_t ctx_id = pdp_info->context_id;
205
206 LOGP(DGPRS, LOGL_INFO,
207 "Would set PDP info, context id = %d, APN = %s\n",
208 ctx_id, osmo_hexdump(pdp_info->apn_enc, pdp_info->apn_enc_len));
209
210 /* TODO: set PDP info [ctx_id] */
211 }
212
213 subscr->authorized = 1;
214
215 gprs_subscr_update(subscr);
216 return 0;
217}
218
219static int gprs_subscr_handle_gsup_auth_err(struct gsm_subscriber *subscr,
220 struct gprs_gsup_message *gsup_msg)
221{
222 unsigned idx;
223 struct sgsn_subscriber_data *sdata = subscr->sgsn_data;
224
225 LOGP(DGPRS, LOGL_INFO,
226 "Send authentication info has failed for IMSI %s with cause %d\n",
227 gsup_msg->imsi, gsup_msg->cause);
228
229 /* Clear auth tuples */
230 memset(sdata->auth_triplets, 0, sizeof(sdata->auth_triplets));
231 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
232 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
233
234 subscr->authorized = 0;
235
236 gprs_subscr_update_auth_info(subscr);
237 return 0;
238}
239
240static int gprs_subscr_handle_gsup_upd_loc_err(struct gsm_subscriber *subscr,
241 struct gprs_gsup_message *gsup_msg)
242{
243 LOGP(DGPRS, LOGL_INFO,
244 "Update location has failed for IMSI %s with cause %d\n",
245 gsup_msg->imsi, gsup_msg->cause);
246
247 subscr->authorized = 0;
248
249 gprs_subscr_update(subscr);
250 return 0;
251}
252
253int gprs_subscr_rx_gsup_message(struct msgb *msg)
254{
255 uint8_t *data = msgb_l2(msg);
256 size_t data_len = msgb_l2len(msg);
257 int rc = 0;
258
259 struct gprs_gsup_message gsup_msg = {0};
260 struct gsm_subscriber *subscr;
261
262 rc = gprs_gsup_decode(data, data_len, &gsup_msg);
263 if (rc < 0) {
264 LOGP(DGPRS, LOGL_ERROR,
265 "decoding GSUP message fails with error code %d\n", -rc);
266 return rc;
267 }
268
269 if (!gsup_msg.imsi[0])
270 return -GMM_CAUSE_INV_MAND_INFO;
271
272 if (gsup_msg.message_type == GPRS_GSUP_MSGT_INSERT_DATA_REQUEST)
273 subscr = gprs_subscr_get_or_create(gsup_msg.imsi);
274 else
275 subscr = gprs_subscr_get_by_imsi(gsup_msg.imsi);
276
277 if (!subscr) {
278 LOGP(DGPRS, LOGL_NOTICE,
279 "Unknown IMSI %s, discarding GSUP message\n", gsup_msg.imsi);
280 return -GMM_CAUSE_IMSI_UNKNOWN;
281 }
282
283 LOGP(DGPRS, LOGL_INFO,
284 "Received GSUP message of type 0x%02x for IMSI %s\n",
285 gsup_msg.message_type, gsup_msg.imsi);
286
287 switch (gsup_msg.message_type) {
288 case GPRS_GSUP_MSGT_LOCATION_CANCEL_REQUEST:
289 gprs_subscr_put_and_cancel(subscr);
290 subscr = NULL;
291 break;
292
293 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_RESULT:
294 gprs_subscr_handle_gsup_auth_res(subscr, &gsup_msg);
295 break;
296
297 case GPRS_GSUP_MSGT_SEND_AUTH_INFO_ERROR:
298 gprs_subscr_handle_gsup_auth_err(subscr, &gsup_msg);
299 break;
300
301 case GPRS_GSUP_MSGT_UPDATE_LOCATION_RESULT:
302 gprs_subscr_handle_gsup_upd_loc_res(subscr, &gsup_msg);
303 break;
304
305 case GPRS_GSUP_MSGT_UPDATE_LOCATION_ERROR:
306 gprs_subscr_handle_gsup_upd_loc_err(subscr, &gsup_msg);
307 break;
308
309 case GPRS_GSUP_MSGT_PURGE_MS_ERROR:
310 case GPRS_GSUP_MSGT_PURGE_MS_RESULT:
311 case GPRS_GSUP_MSGT_INSERT_DATA_REQUEST:
312 case GPRS_GSUP_MSGT_DELETE_DATA_REQUEST:
313 LOGP(DGPRS, LOGL_ERROR,
314 "Rx GSUP message type %d not yet implemented\n",
315 gsup_msg.message_type);
316 rc = -GMM_CAUSE_MSGT_NOTEXIST_NOTIMPL;
317 break;
318
319 default:
320 LOGP(DGPRS, LOGL_ERROR,
321 "Rx GSUP message type %d not valid at SGSN\n",
322 gsup_msg.message_type);
323 rc = -GMM_CAUSE_MSGT_INCOMP_P_STATE;
324 break;
325 };
326
327 if (subscr)
328 subscr_put(subscr);
329
330 return rc;
331}
332
333int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
334{
335 struct gprs_gsup_message gsup_msg = {0};
336
337 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
338 "subscriber auth info is not available\n");
339
340 gsup_msg.message_type = GPRS_GSUP_MSGT_SEND_AUTH_INFO_REQUEST;
341 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
342}
343
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100344int gprs_subscr_location_update(struct gsm_subscriber *subscr)
345{
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100346 struct gprs_gsup_message gsup_msg = {0};
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100347
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100348 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
Jacob Erlbecka6ddc2d2014-12-12 15:01:37 +0100349 "subscriber data is not available\n");
350
351 gsup_msg.message_type = GPRS_GSUP_MSGT_UPDATE_LOCATION_REQUEST;
352 return gprs_subscr_tx_gsup_message(subscr, &gsup_msg);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100353}
354
355void gprs_subscr_update(struct gsm_subscriber *subscr)
356{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100357 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100358
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100359 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100360 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
361
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100362 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100363}
364
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100365void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
366{
367 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
368 "Updating subscriber authentication info\n");
369
370 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
371 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
372
373 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
374}
375
376struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100377{
378 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100379
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100380 if (mmctx->subscr)
381 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100382
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100383 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100384 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100385
386 if (!subscr) {
387 subscr = gprs_subscr_get_or_create(mmctx->imsi);
388 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100389 }
390
391 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
392 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
393 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100394 }
395
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100396 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100397 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100398
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100399 subscr->sgsn_data->mm = mmctx;
400 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100401
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100402 return subscr;
403}
404
405int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
406{
407 struct gsm_subscriber *subscr = NULL;
408 int rc;
409
410 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
411
412 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
413
414 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
415
416 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100417 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100418 return rc;
419}
420
421int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
422{
423 struct gsm_subscriber *subscr = NULL;
424 int rc;
425
426 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
427
428 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
429
430 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
431
432 rc = gprs_subscr_query_auth_info(subscr);
433 subscr_put(subscr);
434 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100435}