blob: 1f210298f5fa3208517bcd69c420c79a7cea4519 [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
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010095int gprs_subscr_query_auth_info(struct gsm_subscriber *subscr)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +010096{
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +010097 /* TODO: Implement remote query to HLR, ... */
98
99 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
100 "subscriber auth info is not available (remote query NYI)\n");
101 return -ENOTSUP;
102}
103
104int gprs_subscr_location_update(struct gsm_subscriber *subscr)
105{
106 /* TODO: Implement remote query to HLR, ... */
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100107
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100108 LOGMMCTXP(LOGL_INFO, subscr->sgsn_data->mm,
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100109 "subscriber data is not available (remote query NYI)\n");
110 return -ENOTSUP;
111}
112
113void gprs_subscr_update(struct gsm_subscriber *subscr)
114{
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100115 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm, "Updating subscriber data\n");
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100116
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100117 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100118 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
119
Jacob Erlbecka1e03732014-12-02 11:28:38 +0100120 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100121}
122
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100123void gprs_subscr_update_auth_info(struct gsm_subscriber *subscr)
124{
125 LOGMMCTXP(LOGL_DEBUG, subscr->sgsn_data->mm,
126 "Updating subscriber authentication info\n");
127
128 subscr->flags &= ~GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
129 subscr->flags &= ~GSM_SUBSCRIBER_FIRST_CONTACT;
130
131 sgsn_update_subscriber_data(subscr->sgsn_data->mm, subscr);
132}
133
134struct gsm_subscriber *gprs_subscr_get_or_create_by_mmctx(struct sgsn_mm_ctx *mmctx)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100135{
136 struct gsm_subscriber *subscr = NULL;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100137
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100138 if (mmctx->subscr)
139 return subscr_get(mmctx->subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100140
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100141 if (mmctx->imsi[0])
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100142 subscr = gprs_subscr_get_by_imsi(mmctx->imsi);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100143
144 if (!subscr) {
145 subscr = gprs_subscr_get_or_create(mmctx->imsi);
146 subscr->flags |= GSM_SUBSCRIBER_FIRST_CONTACT;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100147 }
148
149 if (strcpy(subscr->equipment.imei, mmctx->imei) != 0) {
150 strncpy(subscr->equipment.imei, mmctx->imei, GSM_IMEI_LENGTH-1);
151 subscr->equipment.imei[GSM_IMEI_LENGTH-1] = 0;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100152 }
153
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100154 if (subscr->lac != mmctx->ra.lac)
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100155 subscr->lac = mmctx->ra.lac;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100156
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100157 subscr->sgsn_data->mm = mmctx;
158 mmctx->subscr = subscr_get(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100159
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100160 return subscr;
161}
162
163int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx)
164{
165 struct gsm_subscriber *subscr = NULL;
166 int rc;
167
168 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber data update\n");
169
170 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
171
172 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING;
173
174 rc = gprs_subscr_location_update(subscr);
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100175 subscr_put(subscr);
Jacob Erlbeck98a95ac2014-11-28 14:55:25 +0100176 return rc;
177}
178
179int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx)
180{
181 struct gsm_subscriber *subscr = NULL;
182 int rc;
183
184 LOGMMCTXP(LOGL_DEBUG, mmctx, "Requesting subscriber authentication info\n");
185
186 subscr = gprs_subscr_get_or_create_by_mmctx(mmctx);
187
188 subscr->flags |= GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING;
189
190 rc = gprs_subscr_query_auth_info(subscr);
191 subscr_put(subscr);
192 return rc;
Jacob Erlbeck33b6dad2014-11-12 10:12:11 +0100193}