blob: beab9bb194bc2cdad9d380c93d921aa947589b5e [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 Erlbeck7430da62014-09-12 15:09:56 +0200385struct gbproxy_tlli_info *gbproxy_get_tlli_info_ul(
386 struct gbproxy_peer *peer,
387 struct gprs_gb_parse_context *parse_ctx)
388{
389 struct gbproxy_tlli_info *tlli_info = NULL;
390
391 if (parse_ctx->tlli_enc)
392 tlli_info = gbproxy_find_tlli(peer, parse_ctx->tlli);
393
394 if (!tlli_info && parse_ctx->imsi)
395 tlli_info = gbproxy_find_tlli_by_imsi(
396 peer, parse_ctx->imsi, parse_ctx->imsi_len);
397
398 if (!tlli_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
399 uint32_t bss_ptmsi;
400 if (!gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
401 &bss_ptmsi))
402 LOGP(DGPRS, LOGL_ERROR,
403 "Failed to parse P-TMSI (TLLI is %08x)\n",
404 parse_ctx->tlli);
405 else
406 tlli_info = gbproxy_find_tlli_by_ptmsi(peer, bss_ptmsi);
407 }
408
409 if (tlli_info)
410 tlli_info->is_deregistered = 0;
411
412 return tlli_info;
413}
414
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200415struct gbproxy_tlli_info *gbproxy_update_tlli_state_ul(
416 struct gbproxy_peer *peer,
417 time_t now,
418 struct gprs_gb_parse_context *parse_ctx)
419{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200420 struct gbproxy_tlli_info *tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200421
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200422 tlli_info = gbproxy_get_tlli_info_ul(peer, parse_ctx);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200423
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200424 if (parse_ctx->tlli_enc && parse_ctx->llc) {
425 uint32_t sgsn_tlli;
426 if (!tlli_info) {
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200427 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
428 parse_ctx->tlli);
429 tlli_info = gbproxy_tlli_info_alloc(peer);
430 gbproxy_attach_tlli_info(peer, now, tlli_info);
431
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200432 /* Setup TLLIs */
433 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
434 parse_ctx->tlli);
435 tlli_info->sgsn_tlli.current = sgsn_tlli;
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200436 tlli_info->tlli.current = parse_ctx->tlli;;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200437 } else if (!tlli_info->tlli.current) {
438 /* New TLLI (info found by IMSI or P-TMSI) */
439 tlli_info->tlli.current = parse_ctx->tlli;
440 tlli_info->sgsn_tlli.current =
441 gbproxy_make_sgsn_tlli(peer, tlli_info,
442 parse_ctx->tlli);
443 gbproxy_touch_tlli(peer, tlli_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200444 } else {
445 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, tlli_info, 0);
446 if (!sgsn_tlli)
447 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, tlli_info,
448 parse_ctx->tlli);
449
450 gbproxy_validate_tlli(&tlli_info->tlli,
451 parse_ctx->tlli, 0);
452 gbproxy_validate_tlli(&tlli_info->sgsn_tlli,
453 sgsn_tlli, 0);
454 gbproxy_touch_tlli(peer, tlli_info, now);
455 }
456 } else if (tlli_info) {
457 gbproxy_touch_tlli(peer, tlli_info, now);
458 }
459
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200460 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0)
461 gbproxy_assign_imsi(peer, tlli_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200462
463 return tlli_info;
464}
465
466struct gbproxy_tlli_info *gbproxy_update_tlli_state_dl(
467 struct gbproxy_peer *peer,
468 time_t now,
469 struct gprs_gb_parse_context *parse_ctx)
470{
471 struct gbproxy_tlli_info *tlli_info = NULL;
472
473 if (parse_ctx->tlli_enc)
474 tlli_info = gbproxy_find_tlli_by_sgsn_tlli(peer, parse_ctx->tlli);
475
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200476 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && tlli_info) {
477 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200478 * register new TLLI */
479 uint32_t new_sgsn_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200480 uint32_t new_bss_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200481 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
482 &new_sgsn_ptmsi)) {
483 LOGP(DGPRS, LOGL_ERROR,
484 "Failed to parse new TLLI/PTMSI (current is %08x)\n",
485 parse_ctx->tlli);
486 return tlli_info;
487 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200488 new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200489
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200490 LOGP(DGPRS, LOGL_INFO,
491 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
492 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200493 /* Setup PTMSIs */
494 tlli_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
495 tlli_info->tlli.ptmsi = new_bss_ptmsi;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200496 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !tlli_info &&
497 !peer->cfg->patch_ptmsi) {
498 /* A new P-TMSI has been signalled in the message with an unknown
499 * TLLI, create a new tlli_info */
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200500 /* TODO: Add a test case for this branch */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200501 uint32_t new_ptmsi;
502 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
503 &new_ptmsi)) {
504 LOGP(DGPRS, LOGL_ERROR,
505 "Failed to parse new PTMSI (TLLI is %08x)\n",
506 parse_ctx->tlli);
507 return tlli_info;
508 }
509
510 LOGP(DGPRS, LOGL_INFO,
511 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
512 parse_ctx->tlli, new_ptmsi);
513
514 tlli_info = gbproxy_tlli_info_alloc(peer);
515 tlli_info->sgsn_tlli.current = parse_ctx->tlli;;
516 tlli_info->tlli.current = parse_ctx->tlli;;
517 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
518 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200519 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200520 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !tlli_info &&
521 !peer->cfg->patch_ptmsi) {
522 /* Unknown SGSN TLLI, create a new tlli_info */
523 uint32_t new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200524 tlli_info = gbproxy_tlli_info_alloc(peer);
525 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
526 parse_ctx->tlli);
527
528 gbproxy_attach_tlli_info(peer, now, tlli_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200529
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200530 /* Setup TLLIs */
531 tlli_info->sgsn_tlli.current = parse_ctx->tlli;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200532 tlli_info->tlli.current = parse_ctx->tlli;
533
534 if (!parse_ctx->new_ptmsi_enc)
535 return tlli_info;
536 /* A new P-TMSI has been signalled in the message */
537
538 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc,
539 GSM48_TMSI_LEN, &new_ptmsi)) {
540 LOGP(DGPRS, LOGL_ERROR,
541 "Failed to parse new PTMSI (TLLI is %08x)\n",
542 parse_ctx->tlli);
543 return tlli_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200544 }
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200545 LOGP(DGPRS, LOGL_INFO,
546 "Assigning new P-TMSI %08x\n", new_ptmsi);
547 /* Setup P-TMSIs */
548 tlli_info->sgsn_tlli.ptmsi = new_ptmsi;
549 tlli_info->tlli.ptmsi = new_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200550 } else if (parse_ctx->tlli_enc && parse_ctx->llc && tlli_info) {
551 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
552 tlli_info, 1);
553 gbproxy_validate_tlli(&tlli_info->sgsn_tlli, parse_ctx->tlli, 1);
554 gbproxy_validate_tlli(&tlli_info->tlli, bss_tlli, 1);
555 gbproxy_touch_tlli(peer, tlli_info, now);
556 } else if (tlli_info) {
557 gbproxy_touch_tlli(peer, tlli_info, now);
558 }
559
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200560 if (parse_ctx->imsi && tlli_info && tlli_info->imsi_len == 0)
561 gbproxy_assign_imsi(peer, tlli_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200562
563 return tlli_info;
564}
565
566void gbproxy_update_tlli_state_after(
567 struct gbproxy_peer *peer,
568 struct gbproxy_tlli_info *tlli_info,
569 time_t now,
570 struct gprs_gb_parse_context *parse_ctx)
571{
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200572 if (parse_ctx->invalidate_tlli && tlli_info) {
573 int keep_info =
574 peer->cfg->keep_tlli_infos == GBPROX_KEEP_ALWAYS ||
575 (peer->cfg->keep_tlli_infos == GBPROX_KEEP_REATTACH &&
576 parse_ctx->await_reattach) ||
577 (peer->cfg->keep_tlli_infos == GBPROX_KEEP_IDENTIFIED &&
578 tlli_info->imsi_len > 0);
579 if (keep_info) {
580 LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
581 tlli_info->tlli.current);
582 gbproxy_unregister_tlli(peer, tlli_info);
583 } else {
584 LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
585 tlli_info->tlli.current);
586 gbproxy_delete_tlli(peer, tlli_info);
587 }
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200588 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
589 parse_ctx->new_ptmsi_enc && tlli_info) {
590 /* A new PTMSI has been signaled in the message,
591 * register new TLLI */
592 uint32_t new_sgsn_ptmsi = tlli_info->sgsn_tlli.ptmsi;
593 uint32_t new_bss_ptmsi = tlli_info->tlli.ptmsi;
594 uint32_t new_sgsn_tlli;
595 uint32_t new_bss_tlli = 0;
596
597 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
598 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
599 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
600 LOGP(DGPRS, LOGL_INFO,
601 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
602 new_sgsn_tlli, new_bss_tlli);
603
604 gbproxy_reassign_tlli(&tlli_info->sgsn_tlli,
605 peer, new_sgsn_tlli);
606 gbproxy_reassign_tlli(&tlli_info->tlli,
607 peer, new_bss_tlli);
608 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200609
610 gbproxy_remove_stale_tllis(peer, now);
611}
612
613