blob: 509e4899137009c8f13962f2a2fc29f1d9e80300 [file] [log] [blame]
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001/* Gb-proxy TLLI state handling */
2
3/* (C) 2014 by On-Waves
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
Harald Welte6e688082014-08-24 17:38:18 +020021#include <osmocom/gsm/gsm48.h>
22
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020023#include <openbsc/gb_proxy.h>
24
25#include <openbsc/gprs_utils.h>
26#include <openbsc/gprs_gb_parse.h>
27
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020028#include <openbsc/debug.h>
29
30#include <osmocom/gsm/gsm_utils.h>
31
32#include <osmocom/core/rate_ctr.h>
33#include <osmocom/core/talloc.h>
34
35struct gbproxy_tlli_info *gbproxy_find_tlli(struct gbproxy_peer *peer,
36 uint32_t tlli)
37{
38 struct gbproxy_tlli_info *tlli_info;
39 struct gbproxy_patch_state *state = &peer->patch_state;
40
41 llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
42 if (tlli_info->tlli.current == tlli ||
43 tlli_info->tlli.assigned == tlli)
44 return tlli_info;
45
46 return NULL;
47}
48
49struct gbproxy_tlli_info *gbproxy_find_tlli_by_ptmsi(
50 struct gbproxy_peer *peer,
51 uint32_t ptmsi)
52{
53 struct gbproxy_tlli_info *tlli_info;
54 struct gbproxy_patch_state *state = &peer->patch_state;
55
56 llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
57 if (tlli_info->tlli.ptmsi == ptmsi)
58 return tlli_info;
59
60 return NULL;
61}
62
63struct gbproxy_tlli_info *gbproxy_find_tlli_by_sgsn_tlli(
64 struct gbproxy_peer *peer,
65 uint32_t tlli)
66{
67 struct gbproxy_tlli_info *tlli_info;
68 struct gbproxy_patch_state *state = &peer->patch_state;
69
70 llist_for_each_entry(tlli_info, &state->enabled_tllis, list)
71 if (tlli_info->sgsn_tlli.current == tlli ||
72 tlli_info->sgsn_tlli.assigned == tlli)
73 return tlli_info;
74
75 return NULL;
76}
77
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +020078struct gbproxy_tlli_info *gbproxy_find_tlli_by_imsi(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020079 struct gbproxy_peer *peer,
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +020080 const uint8_t *imsi,
81 size_t imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020082{
83 struct gbproxy_tlli_info *tlli_info;
84 struct gbproxy_patch_state *state = &peer->patch_state;
85
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +020086 if (!gprs_is_mi_imsi(imsi, imsi_len))
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020087 return NULL;
88
89 llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +020090 if (tlli_info->imsi_len != imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020091 continue;
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +020092 if (memcmp(tlli_info->imsi, imsi, imsi_len) != 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020093 continue;
94
95 return tlli_info;
96 }
97
98 return NULL;
99}
100
Jacob Erlbeck31591142014-09-03 11:59:48 +0200101void gbproxy_tlli_info_discard_messages(struct gbproxy_tlli_info *tlli_info)
102{
103 struct msgb *msg, *nxt;
104
105 llist_for_each_entry_safe(msg, nxt, &tlli_info->stored_msgs, list) {
106 llist_del(&msg->list);
107 msgb_free(msg);
108 }
109}
110
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200111void gbproxy_delete_tlli(struct gbproxy_peer *peer,
112 struct gbproxy_tlli_info *tlli_info)
113{
114 struct gbproxy_patch_state *state = &peer->patch_state;
115
Jacob Erlbeck31591142014-09-03 11:59:48 +0200116 gbproxy_tlli_info_discard_messages(tlli_info);
117
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200118 llist_del(&tlli_info->list);
119 talloc_free(tlli_info);
120 state->enabled_tllis_count -= 1;
121
122 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
123 state->enabled_tllis_count;
124}
125
126void gbproxy_delete_tllis(struct gbproxy_peer *peer)
127{
128 struct gbproxy_tlli_info *tlli_info, *nxt;
129 struct gbproxy_patch_state *state = &peer->patch_state;
130
131 llist_for_each_entry_safe(tlli_info, nxt, &state->enabled_tllis, list)
132 gbproxy_delete_tlli(peer, tlli_info);
133
134 OSMO_ASSERT(state->enabled_tllis_count == 0);
135 OSMO_ASSERT(llist_empty(&state->enabled_tllis));
136}
137
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200138void gbproxy_attach_tlli_info(struct gbproxy_peer *peer, time_t now,
139 struct gbproxy_tlli_info *tlli_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200140{
141 struct gbproxy_patch_state *state = &peer->patch_state;
142
143 tlli_info->timestamp = now;
144 llist_add(&tlli_info->list, &state->enabled_tllis);
145 state->enabled_tllis_count += 1;
146
147 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
148 state->enabled_tllis_count;
149}
150
151int gbproxy_remove_stale_tllis(struct gbproxy_peer *peer, time_t now)
152{
153 struct gbproxy_patch_state *state = &peer->patch_state;
154 int exceeded_max_len = 0;
155 int deleted_count = 0;
156 int check_for_age;
157
158 if (peer->cfg->tlli_max_len > 0)
159 exceeded_max_len =
160 state->enabled_tllis_count - peer->cfg->tlli_max_len;
161
162 check_for_age = peer->cfg->tlli_max_age > 0;
163
164 for (; exceeded_max_len > 0; exceeded_max_len--) {
165 struct gbproxy_tlli_info *tlli_info;
166 OSMO_ASSERT(!llist_empty(&state->enabled_tllis));
167 tlli_info = llist_entry(state->enabled_tllis.prev,
168 struct gbproxy_tlli_info,
169 list);
170 LOGP(DGPRS, LOGL_INFO,
171 "Removing TLLI %08x from list "
172 "(stale, length %d, max_len exceeded)\n",
173 tlli_info->tlli.current, state->enabled_tllis_count);
174
175 gbproxy_delete_tlli(peer, tlli_info);
176 deleted_count += 1;
177 }
178
179 while (check_for_age && !llist_empty(&state->enabled_tllis)) {
180 time_t age;
181 struct gbproxy_tlli_info *tlli_info;
182 tlli_info = llist_entry(state->enabled_tllis.prev,
183 struct gbproxy_tlli_info,
184 list);
185 age = now - tlli_info->timestamp;
186 /* age < 0 only happens after system time jumps, discard entry */
187 if (age <= peer->cfg->tlli_max_age && age >= 0) {
188 check_for_age = 0;
189 continue;
190 }
191
192 LOGP(DGPRS, LOGL_INFO,
193 "Removing TLLI %08x from list "
194 "(stale, age %d, max_age exceeded)\n",
195 tlli_info->tlli.current, (int)age);
196
197 gbproxy_delete_tlli(peer, tlli_info);
198 deleted_count += 1;
199 }
200
201 return deleted_count;
202}
203
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200204struct gbproxy_tlli_info *gbproxy_tlli_info_alloc( struct gbproxy_peer *peer)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200205{
206 struct gbproxy_tlli_info *tlli_info;
207
208 tlli_info = talloc_zero(peer, struct gbproxy_tlli_info);
209 tlli_info->tlli.ptmsi = GSM_RESERVED_TMSI;
210 tlli_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
211
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200212 INIT_LLIST_HEAD(&tlli_info->stored_msgs);
213
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200214 return tlli_info;
215}
216
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200217void gbproxy_detach_tlli_info(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200218 struct gbproxy_peer *peer,
219 struct gbproxy_tlli_info *tlli_info)
220{
221 struct gbproxy_patch_state *state = &peer->patch_state;
222
223 llist_del(&tlli_info->list);
224 OSMO_ASSERT(state->enabled_tllis_count > 0);
225 state->enabled_tllis_count -= 1;
226
227 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
228 state->enabled_tllis_count;
229}
230
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200231void gbproxy_update_tlli_info(struct gbproxy_tlli_info *tlli_info,
232 const uint8_t *imsi, size_t imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200233{
234 if (!gprs_is_mi_imsi(imsi, imsi_len))
235 return;
236
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200237 tlli_info->imsi_len = imsi_len;
238 tlli_info->imsi =
239 talloc_realloc_size(tlli_info, tlli_info->imsi, imsi_len);
240 OSMO_ASSERT(tlli_info->imsi != NULL);
241 memcpy(tlli_info->imsi, imsi, imsi_len);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200242}
243
244void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
245 struct gbproxy_peer *peer, uint32_t new_tlli)
246{
247 if (new_tlli == tlli_state->current)
248 return;
249
250 LOGP(DGPRS, LOGL_INFO,
251 "The TLLI has been reassigned from %08x to %08x\n",
252 tlli_state->current, new_tlli);
253
254 /* Remember assigned TLLI */
255 tlli_state->assigned = new_tlli;
256 tlli_state->bss_validated = 0;
257 tlli_state->net_validated = 0;
258}
259
260uint32_t gbproxy_map_tlli(uint32_t other_tlli,
261 struct gbproxy_tlli_info *tlli_info, int to_bss)
262{
263 uint32_t tlli = 0;
264 struct gbproxy_tlli_state *src, *dst;
265 if (to_bss) {
266 src = &tlli_info->sgsn_tlli;
267 dst = &tlli_info->tlli;
268 } else {
269 src = &tlli_info->tlli;
270 dst = &tlli_info->sgsn_tlli;
271 }
272 if (src->current == other_tlli)
273 tlli = dst->current;
274 else if (src->assigned == other_tlli)
275 tlli = dst->assigned;
276
277 return tlli;
278}
279
280static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
281 uint32_t tlli, int to_bss)
282{
283 LOGP(DGPRS, LOGL_DEBUG,
284 "%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
285 __func__, tlli_state->current, tlli_state->assigned,
286 tlli_state->net_validated, tlli_state->bss_validated, tlli);
287
288 if (!tlli_state->assigned || tlli_state->assigned != tlli)
289 return;
290
291 /* TODO: Is this ok? Check spec */
292 if (gprs_tlli_type(tlli) != TLLI_LOCAL)
293 return;
294
295 /* See GSM 04.08, 4.7.1.5 */
296 if (to_bss)
297 tlli_state->net_validated = 1;
298 else
299 tlli_state->bss_validated = 1;
300
301 if (!tlli_state->bss_validated || !tlli_state->net_validated)
302 return;
303
304 LOGP(DGPRS, LOGL_INFO,
305 "The TLLI %08x has been validated (was %08x)\n",
306 tlli_state->assigned, tlli_state->current);
307
308 tlli_state->current = tlli;
309 tlli_state->assigned = 0;
310}
311
312void gbproxy_touch_tlli(struct gbproxy_peer *peer,
313 struct gbproxy_tlli_info *tlli_info, time_t now)
314{
315 gbproxy_detach_tlli_info(peer, tlli_info);
316 gbproxy_attach_tlli_info(peer, now, tlli_info);
317}
318
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200319static void gbproxy_unregister_tlli(struct gbproxy_peer *peer,
320 struct gbproxy_tlli_info *tlli_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200321{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200322 if (!tlli_info)
323 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200324
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200325 if (tlli_info->tlli.ptmsi == GSM_RESERVED_TMSI && !tlli_info->imsi_len) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200326 LOGP(DGPRS, LOGL_INFO,
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200327 "Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
328 tlli_info->tlli.current);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200329 gbproxy_delete_tlli(peer, tlli_info);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200330 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200331 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200332
333 tlli_info->tlli.current = 0;
334 tlli_info->tlli.assigned = 0;
335 tlli_info->sgsn_tlli.current = 0;
336 tlli_info->sgsn_tlli.assigned = 0;
337
338 tlli_info->is_deregistered = 1;
339
340 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200341}
342
Jacob Erlbeck18a37872014-09-08 09:59:16 +0200343int gbproxy_check_tlli(struct gbproxy_peer *peer,
344 struct gbproxy_tlli_info *tlli_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200345{
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200346 if (!peer->cfg->check_imsi)
347 return 1;
348
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200349 return tlli_info != NULL && tlli_info->enable_patching;
350}
351
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200352struct gbproxy_tlli_info *gbproxy_get_tlli_info_ul(
353 struct gbproxy_peer *peer,
354 struct gprs_gb_parse_context *parse_ctx)
355{
356 struct gbproxy_tlli_info *tlli_info = NULL;
357
358 if (parse_ctx->tlli_enc)
359 tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
360
361 if (!tlli_info && parse_ctx->imsi)
362 tlli_info = gbproxy_find_tlli_by_imsi(
363 peer, parse_ctx->imsi, parse_ctx->imsi_len);
364
365 if (!tlli_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
366 uint32_t bss_ptmsi;
367 if (!gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
368 &bss_ptmsi))
369 LOGP(DGPRS, LOGL_ERROR,
370 "Failed to parse P-TMSI (TLLI is %08x)\n",
371 parse_ctx->tlli);
372 else
373 tlli_info = gbproxy_find_tlli_by_ptmsi(peer, bss_ptmsi);
374 }
375
376 if (tlli_info)
377 tlli_info->is_deregistered = 0;
378
379 return tlli_info;
380}
381
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200382struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
383 struct gbproxy_peer *peer,
384 time_t now,
385 struct gprs_gb_parse_context *parse_ctx)
386{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200387 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200388
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200389 tlli_info = gbproxy_get_tlli_info_ul(peer, parse_ctx);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200390
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200391 if (parse_ctx->tlli_enc && parse_ctx->llc) {
392 uint32_t sgsn_tlli;
393 if (!tlli_info) {
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200394 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
395 parse_ctx->tlli);
396 tlli_info = gbproxy_tlli_info_alloc(peer);
397 gbproxy_attach_tlli_info(peer, now, tlli_info);
398
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200399 /* Setup TLLIs */
400 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
401 parse_ctx->tlli);
402 tlli_info->sgsn_tlli.current = sgsn_tlli;
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200403 tlli_info->tlli.current = parse_ctx->tlli;;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200404 } else if (!tlli_info->tlli.current) {
405 /* New TLLI (info found by IMSI or P-TMSI) */
406 tlli_info->tlli.current = parse_ctx->tlli;
407 tlli_info->sgsn_tlli.current =
408 gbproxy_make_sgsn_tlli(peer, tlli_info,
409 parse_ctx->tlli);
410 gbproxy_touch_tlli(peer, tlli_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200411 } else {
412 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
413 if (!sgsn_tlli)
414 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
415 parse_ctx->tlli);
416
417 gbproxy_validate_tlli(&tlli_info->tlli,
418 parse_ctx->tlli, 0);
419 gbproxy_validate_tlli(&tlli_info->sgsn_tlli,
420 sgsn_tlli, 0);
421 gbproxy_touch_tlli(peer, tlli_info, now);
422 }
423 } else if (tlli_info) {
424 gbproxy_touch_tlli(peer, tlli_info, now);
425 }
426
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200427 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200428 int enable_patching;
429 gbproxy_update_tlli_info(tlli_info,
430 parse_ctx->imsi, parse_ctx->imsi_len);
431
432 /* Check, whether the IMSI matches */
433 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
434 parse_ctx->imsi_len);
435 if (enable_patching >= 0)
436 tlli_info->enable_patching = enable_patching;
437 }
438
439 return tlli_info;
440}
441
442struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
443 struct gbproxy_peer *peer,
444 time_t now,
445 struct gprs_gb_parse_context *parse_ctx)
446{
447 struct gbproxy_tlli_info *tlli_info = NULL;
448
449 if (parse_ctx->tlli_enc)
450 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
451
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200452 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && tlli_info) {
453 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200454 * register new TLLI */
455 uint32_t new_sgsn_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200456 uint32_t new_bss_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200457 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
458 &new_sgsn_ptmsi)) {
459 LOGP(DGPRS, LOGL_ERROR,
460 "Failed to parse new TLLI/PTMSI (current is %08x)\n",
461 parse_ctx->tlli);
462 return tlli_info;
463 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200464 new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200465
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200466 LOGP(DGPRS, LOGL_INFO,
467 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
468 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200469 /* Setup PTMSIs */
470 tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
471 tlli_info->tlli.ptmsi = new_bss_ptmsi;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200472 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !tlli_info &&
473 !peer->cfg->patch_ptmsi) {
474 /* A new P-TMSI has been signalled in the message with an unknown
475 * TLLI, create a new tlli_info */
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200476 /* TODO: Add a test case for this branch */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200477 uint32_t new_ptmsi;
478 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
479 &new_ptmsi)) {
480 LOGP(DGPRS, LOGL_ERROR,
481 "Failed to parse new PTMSI (TLLI is %08x)\n",
482 parse_ctx->tlli);
483 return tlli_info;
484 }
485
486 LOGP(DGPRS, LOGL_INFO,
487 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
488 parse_ctx->tlli, new_ptmsi);
489
490 tlli_info = gbproxy_tlli_info_alloc(peer);
491 tlli_info->sgsn_tlli.current = parse_ctx->tlli;;
492 tlli_info->tlli.current = parse_ctx->tlli;;
493 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
494 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200495 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200496 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info &&
497 !peer->cfg->patch_ptmsi) {
498 /* Unknown SGSN TLLI, create a new tlli_info */
499 uint32_t new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200500 tlli_info = gbproxy_tlli_info_alloc(peer);
501 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
502 parse_ctx->tlli);
503
504 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200505
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200506 /* Setup TLLIs */
507 tlli_info->sgsn_tlli.current = parse_ctx->tlli;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200508 tlli_info->tlli.current = parse_ctx->tlli;
509
510 if (!parse_ctx->new_ptmsi_enc)
511 return tlli_info;
512 /* A new P-TMSI has been signalled in the message */
513
514 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc,
515 GSM48_TMSI_LEN, &new_ptmsi)) {
516 LOGP(DGPRS, LOGL_ERROR,
517 "Failed to parse new PTMSI (TLLI is %08x)\n",
518 parse_ctx->tlli);
519 return tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200520 }
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200521 LOGP(DGPRS, LOGL_INFO,
522 "Assigning new P-TMSI %08x\n", new_ptmsi);
523 /* Setup P-TMSIs */
524 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
525 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200526 } else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
527 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
528 tlli_info, 1);
529 gbproxy_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
530 gbproxy_validate_tlli(&tlli_info->tlli, bss_tlli, 1);
531 gbproxy_touch_tlli(peer, tlli_info, now);
532 } else if (tlli_info) {
533 gbproxy_touch_tlli(peer, tlli_info, now);
534 }
535
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200536 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200537 int enable_patching;
538 gbproxy_update_tlli_info(tlli_info,
539 parse_ctx->imsi, parse_ctx->imsi_len);
540
541 /* Check, whether the IMSI matches */
542 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
543 parse_ctx->imsi_len);
544 if (enable_patching >= 0)
545 tlli_info->enable_patching = enable_patching;
546 }
547
548 return tlli_info;
549}
550
551void gbproxy_update_tlli_state_after(
552 struct gbproxy_peer *peer,
553 struct gbproxy_tlli_info *tlli_info,
554 time_t now,
555 struct gprs_gb_parse_context *parse_ctx)
556{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200557 if (parse_ctx->invalidate_tlli && tlli_info) {
558 int keep_info =
559 peer->cfg->keep_tlli_infos == GBPROX_KEEP_ALWAYS ||
560 (peer->cfg->keep_tlli_infos == GBPROX_KEEP_REATTACH &&
561 parse_ctx->await_reattach) ||
562 (peer->cfg->keep_tlli_infos == GBPROX_KEEP_IDENTIFIED &&
563 tlli_info->imsi_len > 0);
564 if (keep_info) {
565 LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
566 tlli_info->tlli.current);
567 gbproxy_unregister_tlli(peer, tlli_info);
568 } else {
569 LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
570 tlli_info->tlli.current);
571 gbproxy_delete_tlli(peer, tlli_info);
572 }
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200573 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
574 parse_ctx->new_ptmsi_enc && tlli_info) {
575 /* A new PTMSI has been signaled in the message,
576 * register new TLLI */
577 uint32_t new_sgsn_ptmsi = tlli_info->sgsn_tlli.ptmsi;
578 uint32_t new_bss_ptmsi = tlli_info->tlli.ptmsi;
579 uint32_t new_sgsn_tlli;
580 uint32_t new_bss_tlli = 0;
581
582 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
583 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
584 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
585 LOGP(DGPRS, LOGL_INFO,
586 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
587 new_sgsn_tlli, new_bss_tlli);
588
589 gbproxy_reassign_tlli(&tlli_info->sgsn_tlli,
590 peer, new_sgsn_tlli);
591 gbproxy_reassign_tlli(&tlli_info->tlli,
592 peer, new_bss_tlli);
593 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200594
595 gbproxy_remove_stale_tllis(peer, now);
596}
597
598