blob: 78459b75daf2407412a9cceb410529d2d74a45b7 [file] [log] [blame]
Jacob Erlbeckcf11e932014-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 Welte642b5c42014-08-24 17:38:18 +020021#include <osmocom/gsm/gsm48.h>
22
Jacob Erlbeckcf11e932014-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 Erlbeckcf11e932014-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 Erlbeck155dc9c2014-09-11 14:57:03 +020078struct gbproxy_tlli_info *gbproxy_find_tlli_by_imsi(
Jacob Erlbeckcf11e932014-08-19 12:21:01 +020079 struct gbproxy_peer *peer,
Jacob Erlbeck155dc9c2014-09-11 14:57:03 +020080 const uint8_t *imsi,
81 size_t imsi_len)
Jacob Erlbeckcf11e932014-08-19 12:21:01 +020082{
83 struct gbproxy_tlli_info *tlli_info;
84 struct gbproxy_patch_state *state = &peer->patch_state;
85
Jacob Erlbeck155dc9c2014-09-11 14:57:03 +020086 if (!gprs_is_mi_imsi(imsi, imsi_len))
Jacob Erlbeckcf11e932014-08-19 12:21:01 +020087 return NULL;
88
89 llist_for_each_entry(tlli_info, &state->enabled_tllis, list) {
Jacob Erlbeck155dc9c2014-09-11 14:57:03 +020090 if (tlli_info->imsi_len != imsi_len)
Jacob Erlbeckcf11e932014-08-19 12:21:01 +020091 continue;
Jacob Erlbeck155dc9c2014-09-11 14:57:03 +020092 if (memcmp(tlli_info->imsi, imsi, imsi_len) != 0)
Jacob Erlbeckcf11e932014-08-19 12:21:01 +020093 continue;
94
95 return tlli_info;
96 }
97
98 return NULL;
99}
100
Jacob Erlbeck6e291e02014-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 Erlbeckcf11e932014-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 Erlbeck6e291e02014-09-03 11:59:48 +0200116 gbproxy_tlli_info_discard_messages(tlli_info);
117
Jacob Erlbeckcf11e932014-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 Erlbeckc68f66c2014-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 Erlbeckcf11e932014-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 Erlbeckc68f66c2014-09-12 14:15:02 +0200204struct gbproxy_tlli_info *gbproxy_tlli_info_alloc( struct gbproxy_peer *peer)
Jacob Erlbeckcf11e932014-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 Erlbeck4c0f6982014-08-22 17:10:01 +0200212 INIT_LLIST_HEAD(&tlli_info->stored_msgs);
213
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200214 return tlli_info;
215}
216
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200217void gbproxy_detach_tlli_info(
Jacob Erlbeckcf11e932014-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 Erlbeckc68f66c2014-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 Erlbeckcf11e932014-08-19 12:21:01 +0200233{
234 if (!gprs_is_mi_imsi(imsi, imsi_len))
235 return;
236
Jacob Erlbeck155dc9c2014-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 Erlbeckcf11e932014-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 Erlbeckcf11e932014-08-19 12:21:01 +0200319static void gbproxy_unregister_tlli(struct gbproxy_peer *peer, uint32_t tlli)
320{
321 struct gbproxy_tlli_info *tlli_info;
322
323 tlli_info = gbproxy_find_tlli(peer, tlli);
324 if (tlli_info) {
325 LOGP(DGPRS, LOGL_INFO,
326 "Removing TLLI %08x from list\n",
327 tlli);
328 gbproxy_delete_tlli(peer, tlli_info);
329 }
330}
331
Jacob Erlbeck6ea6b602014-09-08 09:59:16 +0200332int gbproxy_check_tlli(struct gbproxy_peer *peer,
333 struct gbproxy_tlli_info *tlli_info)
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200334{
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200335 if (!peer->cfg->check_imsi)
336 return 1;
337
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200338 return tlli_info != NULL && tlli_info->enable_patching;
339}
340
341struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
342 struct gbproxy_peer *peer,
343 time_t now,
344 struct gprs_gb_parse_context *parse_ctx)
345{
346 struct gbproxy_tlli_info *tlli_info = NULL;
347
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200348 if (parse_ctx->tlli_enc) {
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200349 tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
350
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200351 if (!tlli_info && parse_ctx->imsi)
352 tlli_info = gbproxy_find_tlli_by_imsi(
353 peer, parse_ctx->imsi, parse_ctx->imsi_len);
354 }
355
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200356 if (parse_ctx->tlli_enc && parse_ctx->llc) {
357 uint32_t sgsn_tlli;
358 if (!tlli_info) {
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200359 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
360 parse_ctx->tlli);
361 tlli_info = gbproxy_tlli_info_alloc(peer);
362 gbproxy_attach_tlli_info(peer, now, tlli_info);
363
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200364 /* Setup TLLIs */
365 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
366 parse_ctx->tlli);
367 tlli_info->sgsn_tlli.current = sgsn_tlli;
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200368 tlli_info->tlli.current = parse_ctx->tlli;;
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200369 } else {
370 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
371 if (!sgsn_tlli)
372 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
373 parse_ctx->tlli);
374
375 gbproxy_validate_tlli(&tlli_info->tlli,
376 parse_ctx->tlli, 0);
377 gbproxy_validate_tlli(&tlli_info->sgsn_tlli,
378 sgsn_tlli, 0);
379 gbproxy_touch_tlli(peer, tlli_info, now);
380 }
381 } else if (tlli_info) {
382 gbproxy_touch_tlli(peer, tlli_info, now);
383 }
384
Jacob Erlbeck155dc9c2014-09-11 14:57:03 +0200385 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0) {
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200386 int enable_patching;
387 gbproxy_update_tlli_info(tlli_info,
388 parse_ctx->imsi, parse_ctx->imsi_len);
389
390 /* Check, whether the IMSI matches */
391 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
392 parse_ctx->imsi_len);
393 if (enable_patching >= 0)
394 tlli_info->enable_patching = enable_patching;
395 }
396
397 return tlli_info;
398}
399
400struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
401 struct gbproxy_peer *peer,
402 time_t now,
403 struct gprs_gb_parse_context *parse_ctx)
404{
405 struct gbproxy_tlli_info *tlli_info = NULL;
406
407 if (parse_ctx->tlli_enc)
408 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
409
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200410 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && tlli_info) {
411 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200412 * register new TLLI */
413 uint32_t new_sgsn_ptmsi;
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200414 uint32_t new_bss_ptmsi;
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200415 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
416 &new_sgsn_ptmsi)) {
417 LOGP(DGPRS, LOGL_ERROR,
418 "Failed to parse new TLLI/PTMSI (current is %08x)\n",
419 parse_ctx->tlli);
420 return tlli_info;
421 }
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200422 new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200423
Jacob Erlbeckd7c923a2014-09-04 14:53:30 +0200424 LOGP(DGPRS, LOGL_INFO,
425 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
426 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200427 /* Setup PTMSIs */
428 tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
429 tlli_info->tlli.ptmsi = new_bss_ptmsi;
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200430 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !tlli_info &&
431 !peer->cfg->patch_ptmsi) {
432 /* A new P-TMSI has been signalled in the message with an unknown
433 * TLLI, create a new tlli_info */
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200434 /* TODO: Add a test case for this branch */
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200435 uint32_t new_ptmsi;
436 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
437 &new_ptmsi)) {
438 LOGP(DGPRS, LOGL_ERROR,
439 "Failed to parse new PTMSI (TLLI is %08x)\n",
440 parse_ctx->tlli);
441 return tlli_info;
442 }
443
444 LOGP(DGPRS, LOGL_INFO,
445 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
446 parse_ctx->tlli, new_ptmsi);
447
448 tlli_info = gbproxy_tlli_info_alloc(peer);
449 tlli_info->sgsn_tlli.current = parse_ctx->tlli;;
450 tlli_info->tlli.current = parse_ctx->tlli;;
451 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
452 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbeckc68f66c2014-09-12 14:15:02 +0200453 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200454 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info &&
455 !peer->cfg->patch_ptmsi) {
456 /* Unknown SGSN TLLI, create a new tlli_info */
457 uint32_t new_ptmsi;
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200458 tlli_info = gbproxy_tlli_info_alloc(peer);
459 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
460 parse_ctx->tlli);
461
462 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200463
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200464 /* Setup TLLIs */
465 tlli_info->sgsn_tlli.current = parse_ctx->tlli;
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200466 tlli_info->tlli.current = parse_ctx->tlli;
467
468 if (!parse_ctx->new_ptmsi_enc)
469 return tlli_info;
470 /* A new P-TMSI has been signalled in the message */
471
472 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc,
473 GSM48_TMSI_LEN, &new_ptmsi)) {
474 LOGP(DGPRS, LOGL_ERROR,
475 "Failed to parse new PTMSI (TLLI is %08x)\n",
476 parse_ctx->tlli);
477 return tlli_info;
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200478 }
Jacob Erlbeck38f1fa52014-09-05 10:22:27 +0200479 LOGP(DGPRS, LOGL_INFO,
480 "Assigning new P-TMSI %08x\n", new_ptmsi);
481 /* Setup P-TMSIs */
482 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
483 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200484 } else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
485 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
486 tlli_info, 1);
487 gbproxy_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
488 gbproxy_validate_tlli(&tlli_info->tlli, bss_tlli, 1);
489 gbproxy_touch_tlli(peer, tlli_info, now);
490 } else if (tlli_info) {
491 gbproxy_touch_tlli(peer, tlli_info, now);
492 }
493
Jacob Erlbeck155dc9c2014-09-11 14:57:03 +0200494 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0) {
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200495 int enable_patching;
496 gbproxy_update_tlli_info(tlli_info,
497 parse_ctx->imsi, parse_ctx->imsi_len);
498
499 /* Check, whether the IMSI matches */
500 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
501 parse_ctx->imsi_len);
502 if (enable_patching >= 0)
503 tlli_info->enable_patching = enable_patching;
504 }
505
506 return tlli_info;
507}
508
509void gbproxy_update_tlli_state_after(
510 struct gbproxy_peer *peer,
511 struct gbproxy_tlli_info *tlli_info,
512 time_t now,
513 struct gprs_gb_parse_context *parse_ctx)
514{
Jacob Erlbeckd7c923a2014-09-04 14:53:30 +0200515 if (parse_ctx->invalidate_tlli) {
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200516 gbproxy_unregister_tlli(peer, parse_ctx->tlli);
Jacob Erlbeckd7c923a2014-09-04 14:53:30 +0200517 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
518 parse_ctx->new_ptmsi_enc && tlli_info) {
519 /* A new PTMSI has been signaled in the message,
520 * register new TLLI */
521 uint32_t new_sgsn_ptmsi = tlli_info->sgsn_tlli.ptmsi;
522 uint32_t new_bss_ptmsi = tlli_info->tlli.ptmsi;
523 uint32_t new_sgsn_tlli;
524 uint32_t new_bss_tlli = 0;
525
526 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
527 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
528 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
529 LOGP(DGPRS, LOGL_INFO,
530 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
531 new_sgsn_tlli, new_bss_tlli);
532
533 gbproxy_reassign_tlli(&tlli_info->sgsn_tlli,
534 peer, new_sgsn_tlli);
535 gbproxy_reassign_tlli(&tlli_info->tlli,
536 peer, new_bss_tlli);
537 }
Jacob Erlbeckcf11e932014-08-19 12:21:01 +0200538
539 gbproxy_remove_stale_tllis(peer, now);
540}
541
542