blob: 16753315c8c9604843a3b6c68f7b6700b475aa9e [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>
23
24#include <openbsc/sgsn.h>
25#include <openbsc/gprs_sgsn.h>
26#include <openbsc/gprs_gmm.h>
27
28#include <openbsc/debug.h>
29
30extern void *tall_bsc_ctx;
31
32void gprs_subscr_init(struct sgsn_instance *sgi)
33{
34}
35
Jacob Erlbecka1e03732014-12-02 11:28:38 +010036static struct sgsn_subscriber_data *sgsn_subscriber_data_alloc(void *ctx)
37{
38 struct sgsn_subscriber_data *sdata;
Jacob Erlbeck7921ab12014-12-08 15:52:00 +010039 int idx;
Jacob Erlbecka1e03732014-12-02 11:28:38 +010040
41 sdata = talloc_zero(ctx, struct sgsn_subscriber_data);
42
Jacob Erlbeck7921ab12014-12-08 15:52:00 +010043 for (idx = 0; idx < ARRAY_SIZE(sdata->auth_triplets); idx++)
44 sdata->auth_triplets[idx].key_seq = GSM_KEY_SEQ_INVAL;
45
Jacob Erlbecka1e03732014-12-02 11:28:38 +010046 return sdata;
47}
48
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010049struct gsm_subscriber *gprs_subscr_get_or_create(const char *imsi)
50{
51 struct gsm_subscriber *subscr;
52
53 subscr = subscr_get_or_create(NULL, imsi);
54 if (!subscr)
55 return NULL;
56
Jacob Erlbecka1e03732014-12-02 11:28:38 +010057 if (!subscr->sgsn_data)
58 subscr->sgsn_data = sgsn_subscriber_data_alloc(subscr);
59
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010060 subscr->keep_in_ram = 1;
61
62 return subscr;
63}
64
65struct gsm_subscriber *gprs_subscr_get_by_imsi(const char *imsi)
66{
67 return subscr_active_by_imsi(NULL, imsi);
68}
69
70void gprs_subscr_delete(struct gsm_subscriber *subscr)
71{
Jacob Erlbecka1e03732014-12-02 11:28:38 +010072 if (subscr->sgsn_data->mm) {
73 subscr_put(subscr->sgsn_data->mm->subscr);
74 subscr->sgsn_data->mm->subscr = NULL;
75 subscr->sgsn_data->mm = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010076 }
77
78 if ((subscr->flags & GPRS_SUBSCRIBER_CANCELLED) ||
79 (subscr->flags & GSM_SUBSCRIBER_FIRST_CONTACT))
80 subscr->keep_in_ram = 0;
81
82 subscr_put(subscr);
83}
84
85void gprs_subscr_put_and_cancel(struct gsm_subscriber *subscr)
86{
87 subscr->authorized = 0;
88 subscr->flags |= GPRS_SUBSCRIBER_CANCELLED;
89
90 gprs_subscr_update(subscr);
91
92 gprs_subscr_delete(subscr);
93}
94
95int gprs_subscr_query(struct gsm_subscriber *subscr)
96{
97 /* TODO: Implement remote query to MSC, ... */
98
Jacob Erlbecka1e03732014-12-02 11:28:38 +010099 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100100 "subscriber data is not available (remote query NYI)\n");
101 return -ENOTSUP;
102}
103
104void gprs_subscr_update(struct gsm_subscriber *subscr)
105{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100106 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100107
108 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_PENDING;
109 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
110
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100111 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100112}
113
114int gprs_subscr_request_update(struct sgsn_mm_ctx *mmctx)
115{
116 struct gsm_subscriber *subscr = NULL;
117 int need_update = 0;
118 int rc;
119
120 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
121
122 if (mmctx->subscr) {
123 subscr = subscr_get(mmctx->subscr);
124 } else if (mmctx->imsi[0]) {
125 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
126 need_update = 1;
127 }
128
129 if (!subscr) {
130 subscr = gprs_subscr_get_or_create(mmctx->imsi);
131 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
132 need_update = 1;
133 }
134
135 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
136 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
137 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
138 need_update = 1;
139 }
140
141 if (subscr->lac != mmctx->ra.lac) {
142 subscr->lac = mmctx->ra.lac;
143 need_update = 1;
144 }
145
146 if (need_update) {
147 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_PENDING;
148 if (!mmctx->subscr) {
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100149 subscr->sgsn_data->mm = mmctx;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100150 mmctx->subscr = subscr_get(subscr);
151 }
152
153 rc = gprs_subscr_query(subscr);
154 subscr_put(subscr);
155 return rc;
156 }
157 gprs_subscr_update(subscr);
158 subscr_put(subscr);
159 return 0;
160}