blob: fae05edf8aca86190ec449ea4cbf4608db5717c0 [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
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020035struct gbproxy_link_info *gbproxy_link_info_by_tlli(struct gbproxy_peer *peer,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020036 uint32_t tlli)
37{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020038 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020039 struct gbproxy_patch_state *state = &peer->patch_state;
40
Jacob Erlbeckba6267f2014-09-19 16:14:14 +020041 if (!tlli)
42 return NULL;
43
Jacob Erlbeckf8562e32014-09-19 16:03:07 +020044 llist_for_each_entry(link_info, &state->logical_links, list)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020045 if (link_info->tlli.current == tlli ||
46 link_info->tlli.assigned == tlli)
47 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020048
49 return NULL;
50}
51
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020052struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020053 struct gbproxy_peer *peer,
54 uint32_t ptmsi)
55{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020056 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020057 struct gbproxy_patch_state *state = &peer->patch_state;
58
Jacob Erlbeckba6267f2014-09-19 16:14:14 +020059 if (ptmsi == GSM_RESERVED_TMSI)
60 return NULL;
61
Jacob Erlbeckf8562e32014-09-19 16:03:07 +020062 llist_for_each_entry(link_info, &state->logical_links, list)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020063 if (link_info->tlli.ptmsi == ptmsi)
64 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020065
66 return NULL;
67}
68
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020069struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020070 struct gbproxy_peer *peer,
71 uint32_t tlli)
72{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020073 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020074 struct gbproxy_patch_state *state = &peer->patch_state;
75
Jacob Erlbeckba6267f2014-09-19 16:14:14 +020076 if (!tlli)
77 return NULL;
78
Jacob Erlbeck91a0e862014-09-17 10:56:38 +020079 /* Don't care about the NSEI */
Jacob Erlbeckf8562e32014-09-19 16:03:07 +020080 llist_for_each_entry(link_info, &state->logical_links, list)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020081 if (link_info->sgsn_tlli.current == tlli ||
82 link_info->sgsn_tlli.assigned == tlli)
83 return link_info;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +020084
85 return NULL;
86}
87
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020088struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
Jacob Erlbeck91a0e862014-09-17 10:56:38 +020089 struct gbproxy_peer *peer,
90 uint32_t tlli, uint32_t sgsn_nsei)
91{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020092 struct gbproxy_link_info *link_info;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +020093 struct gbproxy_patch_state *state = &peer->patch_state;
94
Jacob Erlbeckba6267f2014-09-19 16:14:14 +020095 if (!tlli)
96 return NULL;
97
Jacob Erlbeckf8562e32014-09-19 16:03:07 +020098 llist_for_each_entry(link_info, &state->logical_links, list)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020099 if ((link_info->sgsn_tlli.current == tlli ||
100 link_info->sgsn_tlli.assigned == tlli) &&
101 link_info->sgsn_nsei == sgsn_nsei)
102 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200103
104 return NULL;
105}
106
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200107struct gbproxy_link_info *gbproxy_link_info_by_imsi(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200108 struct gbproxy_peer *peer,
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200109 const uint8_t *imsi,
110 size_t imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200111{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200112 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200113 struct gbproxy_patch_state *state = &peer->patch_state;
114
Jacob Erlbeck2fd1ba42014-09-11 14:57:03 +0200115 if (!gprs_is_mi_imsi(imsi, imsi_len))
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200116 return NULL;
117
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200118 llist_for_each_entry(link_info, &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200119 if (link_info->imsi_len != imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200120 continue;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200121 if (memcmp(link_info->imsi, imsi, imsi_len) != 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200122 continue;
123
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200124 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200125 }
126
127 return NULL;
128}
129
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200130void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info)
Jacob Erlbeck31591142014-09-03 11:59:48 +0200131{
132 struct msgb *msg, *nxt;
133
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200134 llist_for_each_entry_safe(msg, nxt, &link_info->stored_msgs, list) {
Jacob Erlbeck31591142014-09-03 11:59:48 +0200135 llist_del(&msg->list);
136 msgb_free(msg);
137 }
138}
139
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200140void gbproxy_delete_link_info(struct gbproxy_peer *peer,
141 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200142{
143 struct gbproxy_patch_state *state = &peer->patch_state;
144
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200145 gbproxy_link_info_discard_messages(link_info);
Jacob Erlbeck31591142014-09-03 11:59:48 +0200146
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200147 llist_del(&link_info->list);
148 talloc_free(link_info);
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200149 state->logical_link_count -= 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200150
151 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200152 state->logical_link_count;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200153}
154
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200155void gbproxy_delete_link_infos(struct gbproxy_peer *peer)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200156{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200157 struct gbproxy_link_info *link_info, *nxt;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200158 struct gbproxy_patch_state *state = &peer->patch_state;
159
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200160 llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200161 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200162
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200163 OSMO_ASSERT(state->logical_link_count == 0);
164 OSMO_ASSERT(llist_empty(&state->logical_links));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200165}
166
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200167void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
168 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200169{
170 struct gbproxy_patch_state *state = &peer->patch_state;
171
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200172 link_info->timestamp = now;
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200173 llist_add(&link_info->list, &state->logical_links);
174 state->logical_link_count += 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200175
176 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200177 state->logical_link_count;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200178}
179
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200180int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200181{
182 struct gbproxy_patch_state *state = &peer->patch_state;
183 int exceeded_max_len = 0;
184 int deleted_count = 0;
185 int check_for_age;
186
187 if (peer->cfg->tlli_max_len > 0)
188 exceeded_max_len =
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200189 state->logical_link_count - peer->cfg->tlli_max_len;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200190
191 check_for_age = peer->cfg->tlli_max_age > 0;
192
193 for (; exceeded_max_len > 0; exceeded_max_len--) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200194 struct gbproxy_link_info *link_info;
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200195 OSMO_ASSERT(!llist_empty(&state->logical_links));
196 link_info = llist_entry(state->logical_links.prev,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200197 struct gbproxy_link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200198 list);
199 LOGP(DGPRS, LOGL_INFO,
200 "Removing TLLI %08x from list "
201 "(stale, length %d, max_len exceeded)\n",
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200202 link_info->tlli.current, state->logical_link_count);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200203
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200204 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200205 deleted_count += 1;
206 }
207
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200208 while (check_for_age && !llist_empty(&state->logical_links)) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200209 time_t age;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200210 struct gbproxy_link_info *link_info;
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200211 link_info = llist_entry(state->logical_links.prev,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200212 struct gbproxy_link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200213 list);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200214 age = now - link_info->timestamp;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200215 /* age < 0 only happens after system time jumps, discard entry */
216 if (age <= peer->cfg->tlli_max_age && age >= 0) {
217 check_for_age = 0;
218 continue;
219 }
220
221 LOGP(DGPRS, LOGL_INFO,
222 "Removing TLLI %08x from list "
223 "(stale, age %d, max_age exceeded)\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200224 link_info->tlli.current, (int)age);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200225
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200226 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200227 deleted_count += 1;
228 }
229
230 return deleted_count;
231}
232
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200233struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200234{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200235 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200236
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200237 link_info = talloc_zero(peer, struct gbproxy_link_info);
238 link_info->tlli.ptmsi = GSM_RESERVED_TMSI;
239 link_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200240
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200241 INIT_LLIST_HEAD(&link_info->stored_msgs);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200242
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200243 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200244}
245
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200246void gbproxy_detach_link_info(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200247 struct gbproxy_peer *peer,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200248 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200249{
250 struct gbproxy_patch_state *state = &peer->patch_state;
251
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200252 llist_del(&link_info->list);
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200253 OSMO_ASSERT(state->logical_link_count > 0);
254 state->logical_link_count -= 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200255
256 peer->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200257 state->logical_link_count;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200258}
259
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200260void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200261 const uint8_t *imsi, size_t imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200262{
263 if (!gprs_is_mi_imsi(imsi, imsi_len))
264 return;
265
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200266 link_info->imsi_len = imsi_len;
267 link_info->imsi =
268 talloc_realloc_size(link_info, link_info->imsi, imsi_len);
269 OSMO_ASSERT(link_info->imsi != NULL);
270 memcpy(link_info->imsi, imsi, imsi_len);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200271}
272
273void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
274 struct gbproxy_peer *peer, uint32_t new_tlli)
275{
276 if (new_tlli == tlli_state->current)
277 return;
278
279 LOGP(DGPRS, LOGL_INFO,
280 "The TLLI has been reassigned from %08x to %08x\n",
281 tlli_state->current, new_tlli);
282
283 /* Remember assigned TLLI */
284 tlli_state->assigned = new_tlli;
285 tlli_state->bss_validated = 0;
286 tlli_state->net_validated = 0;
287}
288
289uint32_t gbproxy_map_tlli(uint32_t other_tlli,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200290 struct gbproxy_link_info *link_info, int to_bss)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200291{
292 uint32_t tlli = 0;
293 struct gbproxy_tlli_state *src, *dst;
294 if (to_bss) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200295 src = &link_info->sgsn_tlli;
296 dst = &link_info->tlli;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200297 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200298 src = &link_info->tlli;
299 dst = &link_info->sgsn_tlli;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200300 }
301 if (src->current == other_tlli)
302 tlli = dst->current;
303 else if (src->assigned == other_tlli)
304 tlli = dst->assigned;
305
306 return tlli;
307}
308
309static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
310 uint32_t tlli, int to_bss)
311{
312 LOGP(DGPRS, LOGL_DEBUG,
313 "%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
314 __func__, tlli_state->current, tlli_state->assigned,
315 tlli_state->net_validated, tlli_state->bss_validated, tlli);
316
317 if (!tlli_state->assigned || tlli_state->assigned != tlli)
318 return;
319
320 /* TODO: Is this ok? Check spec */
321 if (gprs_tlli_type(tlli) != TLLI_LOCAL)
322 return;
323
324 /* See GSM 04.08, 4.7.1.5 */
325 if (to_bss)
326 tlli_state->net_validated = 1;
327 else
328 tlli_state->bss_validated = 1;
329
330 if (!tlli_state->bss_validated || !tlli_state->net_validated)
331 return;
332
333 LOGP(DGPRS, LOGL_INFO,
334 "The TLLI %08x has been validated (was %08x)\n",
335 tlli_state->assigned, tlli_state->current);
336
337 tlli_state->current = tlli;
338 tlli_state->assigned = 0;
339}
340
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200341static void gbproxy_touch_link_info(struct gbproxy_peer *peer,
342 struct gbproxy_link_info *link_info,
Jacob Erlbeck9a7b0d52014-09-19 13:30:14 +0200343 time_t now)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200344{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200345 gbproxy_detach_link_info(peer, link_info);
346 gbproxy_attach_link_info(peer, now, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200347}
348
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200349static void gbproxy_unregister_link_info(struct gbproxy_peer *peer,
350 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200351{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200352 if (!link_info)
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200353 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200354
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200355 if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200356 LOGP(DGPRS, LOGL_INFO,
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200357 "Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200358 link_info->tlli.current);
359 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200360 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200361 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200362
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200363 link_info->tlli.current = 0;
364 link_info->tlli.assigned = 0;
365 link_info->sgsn_tlli.current = 0;
366 link_info->sgsn_tlli.assigned = 0;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200367
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200368 link_info->is_deregistered = 1;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200369
Jacob Erlbeckd211d1d2014-09-22 13:30:46 +0200370 gbproxy_reset_link(link_info);
371
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200372 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200373}
374
Jacob Erlbeck8992f302014-09-19 13:17:55 +0200375int gbproxy_imsi_matches(struct gbproxy_peer *peer,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200376 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200377{
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200378 if (!peer->cfg->check_imsi)
379 return 1;
380
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200381 return link_info != NULL && link_info->imsi_matches;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200382}
383
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200384void gbproxy_assign_imsi(struct gbproxy_peer *peer,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200385 struct gbproxy_link_info *link_info,
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200386 struct gprs_gb_parse_context *parse_ctx)
387{
Jacob Erlbeck8992f302014-09-19 13:17:55 +0200388 int imsi_matches;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200389 struct gbproxy_link_info *other_link_info;
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200390
391 /* Make sure that there is a second entry with the same IMSI */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200392 other_link_info = gbproxy_link_info_by_imsi(
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200393 peer, parse_ctx->imsi, parse_ctx->imsi_len);
394
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200395 if (other_link_info && other_link_info != link_info) {
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200396 char mi_buf[200];
397 mi_buf[0] = '\0';
398 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
399 parse_ctx->imsi, parse_ctx->imsi_len);
400 LOGP(DGPRS, LOGL_INFO,
401 "Removing TLLI %08x from list (IMSI %s re-used)\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200402 other_link_info->tlli.current, mi_buf);
403 gbproxy_delete_link_info(peer, other_link_info);
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200404 }
405
406 /* Update the IMSI field */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200407 gbproxy_update_link_info(link_info,
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200408 parse_ctx->imsi, parse_ctx->imsi_len);
409
410 /* Check, whether the IMSI matches */
Jacob Erlbeck8992f302014-09-19 13:17:55 +0200411 imsi_matches = gbproxy_check_imsi(peer, parse_ctx->imsi,
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200412 parse_ctx->imsi_len);
Jacob Erlbeck8992f302014-09-19 13:17:55 +0200413 if (imsi_matches >= 0)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200414 link_info->imsi_matches = imsi_matches;
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200415}
416
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200417static int gbproxy_tlli_match(const struct gbproxy_tlli_state *a,
418 const struct gbproxy_tlli_state *b)
419{
420 if (a->current && a->current == b->current)
421 return 1;
422
423 if (a->assigned && a->assigned == b->assigned)
424 return 1;
425
426 if (a->ptmsi != GSM_RESERVED_TMSI && a->ptmsi == b->ptmsi)
427 return 1;
428
429 return 0;
430}
431
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200432static void gbproxy_remove_matching_link_infos(
433 struct gbproxy_peer *peer, struct gbproxy_link_info *link_info)
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200434{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200435 struct gbproxy_link_info *info, *nxt;
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200436 struct gbproxy_patch_state *state = &peer->patch_state;
437
438 /* Make sure that there is no second entry with the same P-TMSI or TLLI */
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200439 llist_for_each_entry_safe(info, nxt, &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200440 if (info == link_info)
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200441 continue;
442
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200443 if (!gbproxy_tlli_match(&link_info->tlli, &info->tlli) &&
444 (link_info->sgsn_nsei != info->sgsn_nsei ||
445 !gbproxy_tlli_match(&link_info->sgsn_tlli, &info->sgsn_tlli)))
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200446 continue;
447
448 LOGP(DGPRS, LOGL_INFO,
449 "Removing TLLI %08x from list (P-TMSI/TLLI re-used)\n",
450 info->tlli.current);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200451 gbproxy_delete_link_info(peer, info);
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200452 }
453}
454
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200455struct gbproxy_link_info *gbproxy_get_link_info_ul(
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200456 struct gbproxy_peer *peer,
457 struct gprs_gb_parse_context *parse_ctx)
458{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200459 struct gbproxy_link_info *link_info = NULL;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200460
461 if (parse_ctx->tlli_enc)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200462 link_info = gbproxy_link_info_by_tlli(peer, parse_ctx->tlli);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200463
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200464 if (!link_info && parse_ctx->imsi)
465 link_info = gbproxy_link_info_by_imsi(
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200466 peer, parse_ctx->imsi, parse_ctx->imsi_len);
467
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200468 if (!link_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200469 uint32_t bss_ptmsi;
470 if (!gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN,
471 &bss_ptmsi))
472 LOGP(DGPRS, LOGL_ERROR,
473 "Failed to parse P-TMSI (TLLI is %08x)\n",
474 parse_ctx->tlli);
475 else
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200476 link_info = gbproxy_link_info_by_ptmsi(peer, bss_ptmsi);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200477 }
478
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200479 if (link_info)
480 link_info->is_deregistered = 0;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200481
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200482 return link_info;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200483}
484
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200485struct gbproxy_link_info *gbproxy_update_link_state_ul(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200486 struct gbproxy_peer *peer,
487 time_t now,
488 struct gprs_gb_parse_context *parse_ctx)
489{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200490 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200491
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200492 link_info = gbproxy_get_link_info_ul(peer, parse_ctx);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200493
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200494 if (parse_ctx->tlli_enc && parse_ctx->llc) {
495 uint32_t sgsn_tlli;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200496 if (!link_info) {
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200497 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list\n",
498 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200499 link_info = gbproxy_link_info_alloc(peer);
500 gbproxy_attach_link_info(peer, now, link_info);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200501
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200502 /* Setup TLLIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200503 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200504 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200505 link_info->sgsn_tlli.current = sgsn_tlli;
506 link_info->tlli.current = parse_ctx->tlli;;
507 } else if (!link_info->tlli.current) {
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200508 /* New TLLI (info found by IMSI or P-TMSI) */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200509 link_info->tlli.current = parse_ctx->tlli;
510 link_info->sgsn_tlli.current =
511 gbproxy_make_sgsn_tlli(peer, link_info,
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200512 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200513 gbproxy_touch_link_info(peer, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200514 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200515 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, link_info, 0);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200516 if (!sgsn_tlli)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200517 sgsn_tlli = gbproxy_make_sgsn_tlli(peer, link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200518 parse_ctx->tlli);
519
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200520 gbproxy_validate_tlli(&link_info->tlli,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200521 parse_ctx->tlli, 0);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200522 gbproxy_validate_tlli(&link_info->sgsn_tlli,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200523 sgsn_tlli, 0);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200524 gbproxy_touch_link_info(peer, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200525 }
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200526 } else if (link_info) {
527 gbproxy_touch_link_info(peer, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200528 }
529
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200530 if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
531 gbproxy_assign_imsi(peer, link_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200532
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200533 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200534}
535
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200536struct gbproxy_link_info *gbproxy_update_link_state_dl(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200537 struct gbproxy_peer *peer,
538 time_t now,
539 struct gprs_gb_parse_context *parse_ctx)
540{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200541 struct gbproxy_link_info *link_info = NULL;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200542
543 if (parse_ctx->tlli_enc)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200544 link_info = gbproxy_link_info_by_sgsn_tlli(
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200545 peer, parse_ctx->tlli, parse_ctx->peer_nsei);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200546
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200547 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && link_info) {
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200548 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200549 * register new TLLI */
550 uint32_t new_sgsn_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200551 uint32_t new_bss_ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200552 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
553 &new_sgsn_ptmsi)) {
554 LOGP(DGPRS, LOGL_ERROR,
555 "Failed to parse new TLLI/PTMSI (current is %08x)\n",
556 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200557 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200558 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200559 new_bss_ptmsi = gbproxy_make_bss_ptmsi(peer, new_sgsn_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200560
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200561 LOGP(DGPRS, LOGL_INFO,
562 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
563 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200564 /* Setup PTMSIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200565 link_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
566 link_info->tlli.ptmsi = new_bss_ptmsi;
567 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !link_info &&
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200568 !peer->cfg->patch_ptmsi) {
569 /* A new P-TMSI has been signalled in the message with an unknown
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200570 * TLLI, create a new link_info */
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200571 /* TODO: Add a test case for this branch */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200572 uint32_t new_ptmsi;
573 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN,
574 &new_ptmsi)) {
575 LOGP(DGPRS, LOGL_ERROR,
576 "Failed to parse new PTMSI (TLLI is %08x)\n",
577 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200578 return link_info;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200579 }
580
581 LOGP(DGPRS, LOGL_INFO,
582 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
583 parse_ctx->tlli, new_ptmsi);
584
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200585 link_info = gbproxy_link_info_alloc(peer);
586 link_info->sgsn_tlli.current = parse_ctx->tlli;;
587 link_info->tlli.current = parse_ctx->tlli;;
588 link_info->sgsn_tlli.ptmsi = new_ptmsi;
589 link_info->tlli.ptmsi = new_ptmsi;
590 gbproxy_attach_link_info(peer, now, link_info);
591 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !link_info &&
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200592 !peer->cfg->patch_ptmsi) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200593 /* Unknown SGSN TLLI, create a new link_info */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200594 uint32_t new_ptmsi;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200595 link_info = gbproxy_link_info_alloc(peer);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200596 LOGP(DGPRS, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
597 parse_ctx->tlli);
598
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200599 gbproxy_attach_link_info(peer, now, link_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200600
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200601 /* Setup TLLIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200602 link_info->sgsn_tlli.current = parse_ctx->tlli;
603 link_info->tlli.current = parse_ctx->tlli;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200604
605 if (!parse_ctx->new_ptmsi_enc)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200606 return link_info;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200607 /* A new P-TMSI has been signalled in the message */
608
609 if (!gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc,
610 GSM48_TMSI_LEN, &new_ptmsi)) {
611 LOGP(DGPRS, LOGL_ERROR,
612 "Failed to parse new PTMSI (TLLI is %08x)\n",
613 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200614 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200615 }
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200616 LOGP(DGPRS, LOGL_INFO,
617 "Assigning new P-TMSI %08x\n", new_ptmsi);
618 /* Setup P-TMSIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200619 link_info->sgsn_tlli.ptmsi = new_ptmsi;
620 link_info->tlli.ptmsi = new_ptmsi;
621 } else if (parse_ctx->tlli_enc && parse_ctx->llc && link_info) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200622 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200623 link_info, 1);
624 gbproxy_validate_tlli(&link_info->sgsn_tlli, parse_ctx->tlli, 1);
625 gbproxy_validate_tlli(&link_info->tlli, bss_tlli, 1);
626 gbproxy_touch_link_info(peer, link_info, now);
627 } else if (link_info) {
628 gbproxy_touch_link_info(peer, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200629 }
630
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200631 if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
632 gbproxy_assign_imsi(peer, link_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200633
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200634 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200635}
636
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200637void gbproxy_update_link_state_after(
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200638 struct gbproxy_peer *peer,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200639 struct gbproxy_link_info *link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200640 time_t now,
641 struct gprs_gb_parse_context *parse_ctx)
642{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200643 if (parse_ctx->invalidate_tlli && link_info) {
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200644 int keep_info =
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200645 peer->cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||
646 (peer->cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200647 parse_ctx->await_reattach) ||
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200648 (peer->cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&
649 link_info->imsi_len > 0);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200650 if (keep_info) {
651 LOGP(DGPRS, LOGL_INFO, "Unregistering TLLI %08x\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200652 link_info->tlli.current);
653 gbproxy_unregister_link_info(peer, link_info);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200654 } else {
655 LOGP(DGPRS, LOGL_INFO, "Removing TLLI %08x from list\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200656 link_info->tlli.current);
657 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200658 }
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200659 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200660 parse_ctx->new_ptmsi_enc && link_info) {
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200661 /* A new PTMSI has been signaled in the message,
662 * register new TLLI */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200663 uint32_t new_sgsn_ptmsi = link_info->sgsn_tlli.ptmsi;
664 uint32_t new_bss_ptmsi = link_info->tlli.ptmsi;
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200665 uint32_t new_sgsn_tlli;
666 uint32_t new_bss_tlli = 0;
667
668 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
669 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
670 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
671 LOGP(DGPRS, LOGL_INFO,
672 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
673 new_sgsn_tlli, new_bss_tlli);
674
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200675 gbproxy_reassign_tlli(&link_info->sgsn_tlli,
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200676 peer, new_sgsn_tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200677 gbproxy_reassign_tlli(&link_info->tlli,
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200678 peer, new_bss_tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200679 gbproxy_remove_matching_link_infos(peer, link_info);
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200680 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200681
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200682 gbproxy_remove_stale_link_infos(peer, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200683}
684
685