blob: c3dc7baf2486edc1be71ce1295acc516c57d12e8 [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
138static void gbproxy_attach_tlli_info(struct gbproxy_peer *peer, time_t now,
139 struct gbproxy_tlli_info *tlli_info)
140{
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
204static struct gbproxy_tlli_info *gbproxy_tlli_info_alloc(
205 struct gbproxy_peer *peer)
206{
207 struct gbproxy_tlli_info *tlli_info;
208
209 tlli_info = talloc_zero(peer, struct gbproxy_tlli_info);
210 tlli_info->tlli.ptmsi = GSM_RESERVED_TMSI;
211 tlli_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
212
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200213 INIT_LLIST_HEAD(&tlli_info->stored_msgs);
214
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200215 return tlli_info;
216}
217
218static void gbproxy_detach_tlli_info(
219 struct gbproxy_peer *peer,
220 struct gbproxy_tlli_info *tlli_info)
221{
222 struct gbproxy_patch_state *state = &peer->patch_state;
223
224 llist_del(&tlli_info->list);
225 OSMO_ASSERT(state->enabled_tllis_count > 0);
226 state->enabled_tllis_count -= 1;
227
228 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
229 state->enabled_tllis_count;
230}
231
232static void gbproxy_update_tlli_info(struct gbproxy_tlli_info *tlli_info,
233 const uint8_t *imsi, size_t imsi_len)
234{
235 if (!gprs_is_mi_imsi(imsi, imsi_len))
236 return;
237
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200238 tlli_info->imsi_len = imsi_len;
239 tlli_info->imsi =
240 talloc_realloc_size(tlli_info, tlli_info->imsi, imsi_len);
241 OSMO_ASSERT(tlli_info->imsi != NULL);
242 memcpy(tlli_info->imsi, imsi, imsi_len);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200243}
244
245void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
246 struct gbproxy_peer *peer, uint32_t new_tlli)
247{
248 if (new_tlli == tlli_state->current)
249 return;
250
251 LOGP(DGPRS, LOGL_INFO,
252 "The TLLI has been reassigned from %08x to %08x\n",
253 tlli_state->current, new_tlli);
254
255 /* Remember assigned TLLI */
256 tlli_state->assigned = new_tlli;
257 tlli_state->bss_validated = 0;
258 tlli_state->net_validated = 0;
259}
260
261uint32_t gbproxy_map_tlli(uint32_t other_tlli,
262 struct gbproxy_tlli_info *tlli_info, int to_bss)
263{
264 uint32_t tlli = 0;
265 struct gbproxy_tlli_state *src, *dst;
266 if (to_bss) {
267 src = &tlli_info->sgsn_tlli;
268 dst = &tlli_info->tlli;
269 } else {
270 src = &tlli_info->tlli;
271 dst = &tlli_info->sgsn_tlli;
272 }
273 if (src->current == other_tlli)
274 tlli = dst->current;
275 else if (src->assigned == other_tlli)
276 tlli = dst->assigned;
277
278 return tlli;
279}
280
281static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
282 uint32_t tlli, int to_bss)
283{
284 LOGP(DGPRS, LOGL_DEBUG,
285 "%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
286 __func__, tlli_state->current, tlli_state->assigned,
287 tlli_state->net_validated, tlli_state->bss_validated, tlli);
288
289 if (!tlli_state->assigned || tlli_state->assigned != tlli)
290 return;
291
292 /* TODO: Is this ok? Check spec */
293 if (gprs_tlli_type(tlli) != TLLI_LOCAL)
294 return;
295
296 /* See GSM 04.08, 4.7.1.5 */
297 if (to_bss)
298 tlli_state->net_validated = 1;
299 else
300 tlli_state->bss_validated = 1;
301
302 if (!tlli_state->bss_validated || !tlli_state->net_validated)
303 return;
304
305 LOGP(DGPRS, LOGL_INFO,
306 "The TLLI %08x has been validated (was %08x)\n",
307 tlli_state->assigned, tlli_state->current);
308
309 tlli_state->current = tlli;
310 tlli_state->assigned = 0;
311}
312
313void gbproxy_touch_tlli(struct gbproxy_peer *peer,
314 struct gbproxy_tlli_info *tlli_info, time_t now)
315{
316 gbproxy_detach_tlli_info(peer, tlli_info);
317 gbproxy_attach_tlli_info(peer, now, tlli_info);
318}
319
320struct gbproxy_tlli_info *gbproxy_register_tlli(
321 struct gbproxy_peer *peer, uint32_t tlli,
322 const uint8_t *imsi, size_t imsi_len, time_t now)
323{
324 struct gbproxy_tlli_info *tlli_info;
325 int enable_patching = -1;
Jacob Erlbeckecbd56c2014-08-26 10:01:57 +0200326 int tlli_already_known = 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200327
328 /* Check, whether the IMSI matches */
329 if (gprs_is_mi_imsi(imsi, imsi_len)) {
330 enable_patching = gbproxy_check_imsi(peer, imsi, imsi_len);
331 if (enable_patching < 0)
332 return NULL;
333 }
334
335 tlli_info = gbproxy_find_tlli(peer, tlli);
336
337 if (!tlli_info) {
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200338 tlli_info = gbproxy_find_tlli_by_imsi(peer, imsi, imsi_len);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200339
340 if (tlli_info) {
341 /* TLLI has changed somehow, adjust it */
342 LOGP(DGPRS, LOGL_INFO,
343 "The TLLI has changed from %08x to %08x\n",
344 tlli_info->tlli.current, tlli);
345 tlli_info->tlli.current = tlli;
346 }
347 }
348
349 if (!tlli_info) {
350 tlli_info = gbproxy_tlli_info_alloc(peer);
351 tlli_info->tlli.current = tlli;
352 } else {
353 gbproxy_detach_tlli_info(peer, tlli_info);
354 tlli_already_known = 1;
355 }
356
357 OSMO_ASSERT(tlli_info != NULL);
358
359 if (!tlli_already_known)
360 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n", tlli);
361
362 gbproxy_attach_tlli_info(peer, now, tlli_info);
363 gbproxy_update_tlli_info(tlli_info, imsi, imsi_len);
364
365 if (enable_patching >= 0)
366 tlli_info->enable_patching = enable_patching;
367
368 return tlli_info;
369}
370
371static void gbproxy_unregister_tlli(struct gbproxy_peer *peer, uint32_t tlli)
372{
373 struct gbproxy_tlli_info *tlli_info;
374
375 tlli_info = gbproxy_find_tlli(peer, tlli);
376 if (tlli_info) {
377 LOGP(DGPRS, LOGL_INFO,
378 "Removing TLLI %08x from list\n",
379 tlli);
380 gbproxy_delete_tlli(peer, tlli_info);
381 }
382}
383
Jacob Erlbeck18a37872014-09-08 09:59:16 +0200384int gbproxy_check_tlli(struct gbproxy_peer *peer,
385 struct gbproxy_tlli_info *tlli_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200386{
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200387 if (!peer->cfg->check_imsi)
388 return 1;
389
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200390 return tlli_info != NULL && tlli_info->enable_patching;
391}
392
393struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
394 struct gbproxy_peer *peer,
395 time_t now,
396 struct gprs_gb_parse_context *parse_ctx)
397{
398 struct gbproxy_tlli_info *tlli_info = NULL;
399
400 if (parse_ctx->tlli_enc)
401 tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
402
403 if (parse_ctx->tlli_enc && parse_ctx->llc) {
404 uint32_t sgsn_tlli;
405 if (!tlli_info) {
406 tlli_info =
407 gbproxy_register_tlli(peer, parse_ctx->tlli,
408 parse_ctx->imsi,
409 parse_ctx->imsi_len, now);
410 /* Setup TLLIs */
411 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
412 parse_ctx->tlli);
413 tlli_info->sgsn_tlli.current = sgsn_tlli;
414 } else {
415 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
416 if (!sgsn_tlli)
417 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
418 parse_ctx->tlli);
419
420 gbproxy_validate_tlli(&tlli_info->tlli,
421 parse_ctx->tlli, 0);
422 gbproxy_validate_tlli(&tlli_info->sgsn_tlli,
423 sgsn_tlli, 0);
424 gbproxy_touch_tlli(peer, tlli_info, now);
425 }
426 } else if (tlli_info) {
427 gbproxy_touch_tlli(peer, tlli_info, now);
428 }
429
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200430 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200431 int enable_patching;
432 gbproxy_update_tlli_info(tlli_info,
433 parse_ctx->imsi, parse_ctx->imsi_len);
434
435 /* Check, whether the IMSI matches */
436 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
437 parse_ctx->imsi_len);
438 if (enable_patching >= 0)
439 tlli_info->enable_patching = enable_patching;
440 }
441
442 return tlli_info;
443}
444
445struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
446 struct gbproxy_peer *peer,
447 time_t now,
448 struct gprs_gb_parse_context *parse_ctx)
449{
450 struct gbproxy_tlli_info *tlli_info = NULL;
451
452 if (parse_ctx->tlli_enc)
453 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
454
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200455 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && tlli_info) {
456 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200457 * register new TLLI */
458 uint32_t new_sgsn_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200459 uint32_t new_bss_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200460 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
461 &new_sgsn_ptmsi)) {
462 LOGP(DGPRS, LOGL_ERROR,
463 "Failed to parse new TLLI/PTMSI (current is %08x)\n",
464 parse_ctx->tlli);
465 return tlli_info;
466 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200467 new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200468
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200469 LOGP(DGPRS, LOGL_INFO,
470 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
471 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200472 /* Setup PTMSIs */
473 tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
474 tlli_info->tlli.ptmsi = new_bss_ptmsi;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200475 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !tlli_info &&
476 !peer->cfg->patch_ptmsi) {
477 /* A new P-TMSI has been signalled in the message with an unknown
478 * TLLI, create a new tlli_info */
479 uint32_t new_ptmsi;
480 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
481 &new_ptmsi)) {
482 LOGP(DGPRS, LOGL_ERROR,
483 "Failed to parse new PTMSI (TLLI is %08x)\n",
484 parse_ctx->tlli);
485 return tlli_info;
486 }
487
488 LOGP(DGPRS, LOGL_INFO,
489 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
490 parse_ctx->tlli, new_ptmsi);
491
492 tlli_info = gbproxy_tlli_info_alloc(peer);
493 tlli_info->sgsn_tlli.current = parse_ctx->tlli;;
494 tlli_info->tlli.current = parse_ctx->tlli;;
495 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
496 tlli_info->tlli.ptmsi = new_ptmsi;
497 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info &&
498 !peer->cfg->patch_ptmsi) {
499 /* Unknown SGSN TLLI, create a new tlli_info */
500 uint32_t new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200501 tlli_info = gbproxy_tlli_info_alloc(peer);
502 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
503 parse_ctx->tlli);
504
505 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200506
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200507 /* Setup TLLIs */
508 tlli_info->sgsn_tlli.current = parse_ctx->tlli;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200509 tlli_info->tlli.current = parse_ctx->tlli;
510
511 if (!parse_ctx->new_ptmsi_enc)
512 return tlli_info;
513 /* A new P-TMSI has been signalled in the message */
514
515 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc,
516 GSM48_TMSI_LEN, &new_ptmsi)) {
517 LOGP(DGPRS, LOGL_ERROR,
518 "Failed to parse new PTMSI (TLLI is %08x)\n",
519 parse_ctx->tlli);
520 return tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200521 }
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200522 LOGP(DGPRS, LOGL_INFO,
523 "Assigning new P-TMSI %08x\n", new_ptmsi);
524 /* Setup P-TMSIs */
525 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
526 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200527 } else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
528 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
529 tlli_info, 1);
530 gbproxy_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
531 gbproxy_validate_tlli(&tlli_info->tlli, bss_tlli, 1);
532 gbproxy_touch_tlli(peer, tlli_info, now);
533 } else if (tlli_info) {
534 gbproxy_touch_tlli(peer, tlli_info, now);
535 }
536
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200537 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200538 int enable_patching;
539 gbproxy_update_tlli_info(tlli_info,
540 parse_ctx->imsi, parse_ctx->imsi_len);
541
542 /* Check, whether the IMSI matches */
543 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
544 parse_ctx->imsi_len);
545 if (enable_patching >= 0)
546 tlli_info->enable_patching = enable_patching;
547 }
548
549 return tlli_info;
550}
551
552void gbproxy_update_tlli_state_after(
553 struct gbproxy_peer *peer,
554 struct gbproxy_tlli_info *tlli_info,
555 time_t now,
556 struct gprs_gb_parse_context *parse_ctx)
557{
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200558 if (parse_ctx->invalidate_tlli) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200559 gbproxy_unregister_tlli(peer, parse_ctx->tlli);
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200560 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
561 parse_ctx->new_ptmsi_enc && tlli_info) {
562 /* A new PTMSI has been signaled in the message,
563 * register new TLLI */
564 uint32_t new_sgsn_ptmsi = tlli_info->sgsn_tlli.ptmsi;
565 uint32_t new_bss_ptmsi = tlli_info->tlli.ptmsi;
566 uint32_t new_sgsn_tlli;
567 uint32_t new_bss_tlli = 0;
568
569 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
570 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
571 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
572 LOGP(DGPRS, LOGL_INFO,
573 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
574 new_sgsn_tlli, new_bss_tlli);
575
576 gbproxy_reassign_tlli(&tlli_info->sgsn_tlli,
577 peer, new_sgsn_tlli);
578 gbproxy_reassign_tlli(&tlli_info->tlli,
579 peer, new_bss_tlli);
580 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200581
582 gbproxy_remove_stale_tllis(peer, now);
583}
584
585