blob: c4140f7e8adfc15c0a6b96e7c85a4998726b1efd [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 Erlbeck16a3cd32014-09-15 11:46:42 +0200352void gbproxy_assign_imsi(struct gbproxy_peer *peer,
353 struct gbproxy_tlli_info *tlli_info,
354 struct gprs_gb_parse_context *parse_ctx)
355{
356 int enable_patching;
357 struct gbproxy_tlli_info *other_tlli_info;
358
359 /* Make sure that there is a second entry with the same IMSI */
360 other_tlli_info = gbproxy_find_tlli_by_imsi(
361 peer, parse_ctx->imsi, parse_ctx->imsi_len);
362
363 if (other_tlli_info && other_tlli_info != tlli_info) {
364 char mi_buf[200];
365 mi_buf[0] = '\0';
366 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
367 parse_ctx->imsi, parse_ctx->imsi_len);
368 LOGP(DGPRS, LOGL_INFO,
369 "Removing TLLI %08x from list (IMSI %s re-used)\n",
370 other_tlli_info->tlli.current, mi_buf);
371 gbproxy_delete_tlli(peer, other_tlli_info);
372 }
373
374 /* Update the IMSI field */
375 gbproxy_update_tlli_info(tlli_info,
376 parse_ctx->imsi, parse_ctx->imsi_len);
377
378 /* Check, whether the IMSI matches */
379 enable_patching = gbproxy_check_imsi(peer, parse_ctx->imsi,
380 parse_ctx->imsi_len);
381 if (enable_patching >= 0)
382 tlli_info->enable_patching = enable_patching;
383}
384
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200385static int gbproxy_tlli_match(const struct gbproxy_tlli_state *a,
386 const struct gbproxy_tlli_state *b)
387{
388 if (a->current && a->current == b->current)
389 return 1;
390
391 if (a->assigned && a->assigned == b->assigned)
392 return 1;
393
394 if (a->ptmsi != GSM_RESERVED_TMSI && a->ptmsi == b->ptmsi)
395 return 1;
396
397 return 0;
398}
399
400static void gbproxy_remove_matching_tllis(struct gbproxy_peer *peer,
401 struct gbproxy_tlli_info *tlli_info)
402{
403 struct gbproxy_tlli_info *info, *nxt;
404 struct gbproxy_patch_state *state = &peer->patch_state;
405
406 /* Make sure that there is no second entry with the same P-TMSI or TLLI */
407 llist_for_each_entry_safe(info, nxt, &state->enabled_tllis, list) {
408 if (info == tlli_info)
409 continue;
410
411 if (!gbproxy_tlli_match(&tlli_info->tlli, &info->tlli) &&
412 !gbproxy_tlli_match(&tlli_info->sgsn_tlli, &info->sgsn_tlli))
413 continue;
414
415 LOGP(DGPRS, LOGL_INFO,
416 "Removing TLLI %08x from list (P-TMSI/TLLI re-used)\n",
417 info->tlli.current);
418 gbproxy_delete_tlli(peer, info);
419 }
420}
421
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200422struct gbproxy_tlli_info *gbproxy_get_tlli_info_ul(
423 struct gbproxy_peer *peer,
424 struct gprs_gb_parse_context *parse_ctx)
425{
426 struct gbproxy_tlli_info *tlli_info = NULL;
427
428 if (parse_ctx->tlli_enc)
429 tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
430
431 if (!tlli_info && parse_ctx->imsi)
432 tlli_info = gbproxy_find_tlli_by_imsi(
433 peer, parse_ctx->imsi, parse_ctx->imsi_len);
434
435 if (!tlli_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
436 uint32_t bss_ptmsi;
437 if (!gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
438 &bss_ptmsi))
439 LOGP(DGPRS, LOGL_ERROR,
440 "Failed to parse P-TMSI (TLLI is %08x)\n",
441 parse_ctx->tlli);
442 else
443 tlli_info = gbproxy_find_tlli_by_ptmsi(peer, bss_ptmsi);
444 }
445
446 if (tlli_info)
447 tlli_info->is_deregistered = 0;
448
449 return tlli_info;
450}
451
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200452struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
453 struct gbproxy_peer *peer,
454 time_t now,
455 struct gprs_gb_parse_context *parse_ctx)
456{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200457 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200458
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200459 tlli_info = gbproxy_get_tlli_info_ul(peer, parse_ctx);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200460
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200461 if (parse_ctx->tlli_enc && parse_ctx->llc) {
462 uint32_t sgsn_tlli;
463 if (!tlli_info) {
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200464 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
465 parse_ctx->tlli);
466 tlli_info = gbproxy_tlli_info_alloc(peer);
467 gbproxy_attach_tlli_info(peer, now, tlli_info);
468
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200469 /* Setup TLLIs */
470 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
471 parse_ctx->tlli);
472 tlli_info->sgsn_tlli.current = sgsn_tlli;
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200473 tlli_info->tlli.current = parse_ctx->tlli;;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200474 } else if (!tlli_info->tlli.current) {
475 /* New TLLI (info found by IMSI or P-TMSI) */
476 tlli_info->tlli.current = parse_ctx->tlli;
477 tlli_info->sgsn_tlli.current =
478 gbproxy_make_sgsn_tlli(peer, tlli_info,
479 parse_ctx->tlli);
480 gbproxy_touch_tlli(peer, tlli_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200481 } else {
482 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
483 if (!sgsn_tlli)
484 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
485 parse_ctx->tlli);
486
487 gbproxy_validate_tlli(&tlli_info->tlli,
488 parse_ctx->tlli, 0);
489 gbproxy_validate_tlli(&tlli_info->sgsn_tlli,
490 sgsn_tlli, 0);
491 gbproxy_touch_tlli(peer, tlli_info, now);
492 }
493 } else if (tlli_info) {
494 gbproxy_touch_tlli(peer, tlli_info, now);
495 }
496
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200497 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0)
498 gbproxy_assign_imsi(peer, tlli_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200499
500 return tlli_info;
501}
502
503struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
504 struct gbproxy_peer *peer,
505 time_t now,
506 struct gprs_gb_parse_context *parse_ctx)
507{
508 struct gbproxy_tlli_info *tlli_info = NULL;
509
510 if (parse_ctx->tlli_enc)
511 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
512
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200513 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && tlli_info) {
514 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200515 * register new TLLI */
516 uint32_t new_sgsn_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200517 uint32_t new_bss_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200518 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
519 &new_sgsn_ptmsi)) {
520 LOGP(DGPRS, LOGL_ERROR,
521 "Failed to parse new TLLI/PTMSI (current is %08x)\n",
522 parse_ctx->tlli);
523 return tlli_info;
524 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200525 new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200526
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200527 LOGP(DGPRS, LOGL_INFO,
528 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
529 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200530 /* Setup PTMSIs */
531 tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
532 tlli_info->tlli.ptmsi = new_bss_ptmsi;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200533 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !tlli_info &&
534 !peer->cfg->patch_ptmsi) {
535 /* A new P-TMSI has been signalled in the message with an unknown
536 * TLLI, create a new tlli_info */
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200537 /* TODO: Add a test case for this branch */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200538 uint32_t new_ptmsi;
539 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
540 &new_ptmsi)) {
541 LOGP(DGPRS, LOGL_ERROR,
542 "Failed to parse new PTMSI (TLLI is %08x)\n",
543 parse_ctx->tlli);
544 return tlli_info;
545 }
546
547 LOGP(DGPRS, LOGL_INFO,
548 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
549 parse_ctx->tlli, new_ptmsi);
550
551 tlli_info = gbproxy_tlli_info_alloc(peer);
552 tlli_info->sgsn_tlli.current = parse_ctx->tlli;;
553 tlli_info->tlli.current = parse_ctx->tlli;;
554 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
555 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200556 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200557 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info &&
558 !peer->cfg->patch_ptmsi) {
559 /* Unknown SGSN TLLI, create a new tlli_info */
560 uint32_t new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200561 tlli_info = gbproxy_tlli_info_alloc(peer);
562 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
563 parse_ctx->tlli);
564
565 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200566
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200567 /* Setup TLLIs */
568 tlli_info->sgsn_tlli.current = parse_ctx->tlli;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200569 tlli_info->tlli.current = parse_ctx->tlli;
570
571 if (!parse_ctx->new_ptmsi_enc)
572 return tlli_info;
573 /* A new P-TMSI has been signalled in the message */
574
575 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc,
576 GSM48_TMSI_LEN, &new_ptmsi)) {
577 LOGP(DGPRS, LOGL_ERROR,
578 "Failed to parse new PTMSI (TLLI is %08x)\n",
579 parse_ctx->tlli);
580 return tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200581 }
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200582 LOGP(DGPRS, LOGL_INFO,
583 "Assigning new P-TMSI %08x\n", new_ptmsi);
584 /* Setup P-TMSIs */
585 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
586 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200587 } else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
588 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
589 tlli_info, 1);
590 gbproxy_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
591 gbproxy_validate_tlli(&tlli_info->tlli, bss_tlli, 1);
592 gbproxy_touch_tlli(peer, tlli_info, now);
593 } else if (tlli_info) {
594 gbproxy_touch_tlli(peer, tlli_info, now);
595 }
596
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200597 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0)
598 gbproxy_assign_imsi(peer, tlli_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200599
600 return tlli_info;
601}
602
603void gbproxy_update_tlli_state_after(
604 struct gbproxy_peer *peer,
605 struct gbproxy_tlli_info *tlli_info,
606 time_t now,
607 struct gprs_gb_parse_context *parse_ctx)
608{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200609 if (parse_ctx->invalidate_tlli && tlli_info) {
610 int keep_info =
611 peer->cfg->keep_tlli_infos == GBPROX_KEEP_ALWAYS ||
612 (peer->cfg->keep_tlli_infos == GBPROX_KEEP_REATTACH &&
613 parse_ctx->await_reattach) ||
614 (peer->cfg->keep_tlli_infos == GBPROX_KEEP_IDENTIFIED &&
615 tlli_info->imsi_len > 0);
616 if (keep_info) {
617 LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
618 tlli_info->tlli.current);
619 gbproxy_unregister_tlli(peer, tlli_info);
620 } else {
621 LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
622 tlli_info->tlli.current);
623 gbproxy_delete_tlli(peer, tlli_info);
624 }
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200625 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
626 parse_ctx->new_ptmsi_enc && tlli_info) {
627 /* A new PTMSI has been signaled in the message,
628 * register new TLLI */
629 uint32_t new_sgsn_ptmsi = tlli_info->sgsn_tlli.ptmsi;
630 uint32_t new_bss_ptmsi = tlli_info->tlli.ptmsi;
631 uint32_t new_sgsn_tlli;
632 uint32_t new_bss_tlli = 0;
633
634 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
635 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
636 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
637 LOGP(DGPRS, LOGL_INFO,
638 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
639 new_sgsn_tlli, new_bss_tlli);
640
641 gbproxy_reassign_tlli(&tlli_info->sgsn_tlli,
642 peer, new_sgsn_tlli);
643 gbproxy_reassign_tlli(&tlli_info->tlli,
644 peer, new_bss_tlli);
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200645 gbproxy_remove_matching_tllis(peer, tlli_info);
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200646 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200647
648 gbproxy_remove_stale_tllis(peer, now);
649}
650
651