blob: 0ea3a9305dbfcbd4ebdd2ba38b6ee6125aad3183 [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
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020023#include <osmocom/sgsn/gb_proxy.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020024
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020025#include <osmocom/sgsn/gprs_utils.h>
26#include <osmocom/sgsn/gprs_gb_parse.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020027
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020028#include <osmocom/sgsn/debug.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020029
30#include <osmocom/gsm/gsm_utils.h>
31
32#include <osmocom/core/rate_ctr.h>
33#include <osmocom/core/talloc.h>
34
Harald Welte8cd74402020-12-04 22:24:47 +010035struct gbproxy_link_info *gbproxy_link_info_by_tlli(struct gbproxy_bvc *bvc,
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;
Harald Welte8cd74402020-12-04 22:24:47 +010039 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020040
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(
Harald Welte8cd74402020-12-04 22:24:47 +010053 struct gbproxy_bvc *bvc,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020054 uint32_t ptmsi)
55{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020056 struct gbproxy_link_info *link_info;
Harald Welte8cd74402020-12-04 22:24:47 +010057 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020058
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(
Harald Welte8cd74402020-12-04 22:24:47 +010070 struct gbproxy_bvc *bvc,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020071 uint32_t tlli)
72{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020073 struct gbproxy_link_info *link_info;
Harald Welte8cd74402020-12-04 22:24:47 +010074 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020075
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(
Harald Welte8cd74402020-12-04 22:24:47 +010089 struct gbproxy_bvc *bvc,
Jacob Erlbeck91a0e862014-09-17 10:56:38 +020090 uint32_t tlli, uint32_t sgsn_nsei)
91{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +020092 struct gbproxy_link_info *link_info;
Harald Welte8cd74402020-12-04 22:24:47 +010093 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +020094
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(
Harald Welte8cd74402020-12-04 22:24:47 +0100108 struct gbproxy_bvc *bvc,
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;
Harald Welte8cd74402020-12-04 22:24:47 +0100113 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200114
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
Harald Welte8cd74402020-12-04 22:24:47 +0100140void gbproxy_delete_link_info(struct gbproxy_bvc *bvc,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200141 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200142{
Harald Welte8cd74402020-12-04 22:24:47 +0100143 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200144
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
Harald Welte8cd74402020-12-04 22:24:47 +0100151 bvc->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
Harald Welte8cd74402020-12-04 22:24:47 +0100155void gbproxy_delete_link_infos(struct gbproxy_bvc *bvc)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200156{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200157 struct gbproxy_link_info *link_info, *nxt;
Harald Welte8cd74402020-12-04 22:24:47 +0100158 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200159
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200160 llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list)
Harald Welte8cd74402020-12-04 22:24:47 +0100161 gbproxy_delete_link_info(bvc, 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
Harald Welte8cd74402020-12-04 22:24:47 +0100167void gbproxy_attach_link_info(struct gbproxy_bvc *bvc, time_t now,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200168 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200169{
Harald Welte8cd74402020-12-04 22:24:47 +0100170 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200171
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
Harald Welte8cd74402020-12-04 22:24:47 +0100176 bvc->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
Harald Welte8cd74402020-12-04 22:24:47 +0100180int gbproxy_remove_stale_link_infos(struct gbproxy_bvc *bvc, time_t now)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200181{
Harald Welte8cd74402020-12-04 22:24:47 +0100182 OSMO_ASSERT(bvc);
183 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200184 int exceeded_max_len = 0;
185 int deleted_count = 0;
186 int check_for_age;
Harald Welte8cd74402020-12-04 22:24:47 +0100187 OSMO_ASSERT(bvc->nse);
188 struct gbproxy_config *cfg = bvc->nse->cfg;
Daniel Willmann447ad442020-11-26 18:19:21 +0100189 OSMO_ASSERT(cfg);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200190
Daniel Willmann447ad442020-11-26 18:19:21 +0100191 if (cfg->tlli_max_len > 0)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200192 exceeded_max_len =
Daniel Willmann447ad442020-11-26 18:19:21 +0100193 state->logical_link_count - cfg->tlli_max_len;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200194
Daniel Willmann447ad442020-11-26 18:19:21 +0100195 check_for_age = cfg->tlli_max_age > 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200196
197 for (; exceeded_max_len > 0; exceeded_max_len--) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200198 struct gbproxy_link_info *link_info;
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200199 OSMO_ASSERT(!llist_empty(&state->logical_links));
200 link_info = llist_entry(state->logical_links.prev,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200201 struct gbproxy_link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200202 list);
Harald Welte8cd74402020-12-04 22:24:47 +0100203 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200204 "Removing TLLI %08x from list "
205 "(stale, length %d, max_len exceeded)\n",
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200206 link_info->tlli.current, state->logical_link_count);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200207
Harald Welte8cd74402020-12-04 22:24:47 +0100208 gbproxy_delete_link_info(bvc, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200209 deleted_count += 1;
210 }
211
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200212 while (check_for_age && !llist_empty(&state->logical_links)) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200213 time_t age;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200214 struct gbproxy_link_info *link_info;
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200215 link_info = llist_entry(state->logical_links.prev,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200216 struct gbproxy_link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200217 list);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200218 age = now - link_info->timestamp;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200219 /* age < 0 only happens after system time jumps, discard entry */
Daniel Willmann447ad442020-11-26 18:19:21 +0100220 if (age <= cfg->tlli_max_age && age >= 0) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200221 check_for_age = 0;
222 continue;
223 }
224
Harald Welte8cd74402020-12-04 22:24:47 +0100225 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200226 "Removing TLLI %08x from list "
227 "(stale, age %d, max_age exceeded)\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200228 link_info->tlli.current, (int)age);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200229
Harald Welte8cd74402020-12-04 22:24:47 +0100230 gbproxy_delete_link_info(bvc, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200231 deleted_count += 1;
232 }
233
234 return deleted_count;
235}
236
Harald Welte8cd74402020-12-04 22:24:47 +0100237struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_bvc *bvc)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200238{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200239 struct gbproxy_link_info *link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200240
Harald Welte8cd74402020-12-04 22:24:47 +0100241 link_info = talloc_zero(bvc, struct gbproxy_link_info);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200242 link_info->tlli.ptmsi = GSM_RESERVED_TMSI;
243 link_info->sgsn_tlli.ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200244
Jacob Erlbeck65750282014-09-22 15:41:21 +0200245 link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
246
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200247 INIT_LLIST_HEAD(&link_info->stored_msgs);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200248
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200249 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200250}
251
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200252void gbproxy_detach_link_info(
Harald Welte8cd74402020-12-04 22:24:47 +0100253 struct gbproxy_bvc *bvc,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200254 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200255{
Harald Welte8cd74402020-12-04 22:24:47 +0100256 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200257
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200258 llist_del(&link_info->list);
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200259 OSMO_ASSERT(state->logical_link_count > 0);
260 state->logical_link_count -= 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200261
Harald Welte8cd74402020-12-04 22:24:47 +0100262 bvc->ctrg->ctr[GBPROX_PEER_CTR_TLLI_CACHE_SIZE].current =
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200263 state->logical_link_count;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200264}
265
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200266void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200267 const uint8_t *imsi, size_t imsi_len)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200268{
269 if (!gprs_is_mi_imsi(imsi, imsi_len))
270 return;
271
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200272 link_info->imsi_len = imsi_len;
273 link_info->imsi =
274 talloc_realloc_size(link_info, link_info->imsi, imsi_len);
275 OSMO_ASSERT(link_info->imsi != NULL);
276 memcpy(link_info->imsi, imsi, imsi_len);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200277}
278
279void gbproxy_reassign_tlli(struct gbproxy_tlli_state *tlli_state,
Harald Welte8cd74402020-12-04 22:24:47 +0100280 struct gbproxy_bvc *bvc, uint32_t new_tlli)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200281{
Harald Welte8cd74402020-12-04 22:24:47 +0100282 OSMO_ASSERT(bvc);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200283 if (new_tlli == tlli_state->current)
284 return;
285
Harald Welte8cd74402020-12-04 22:24:47 +0100286 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200287 "The TLLI has been reassigned from %08x to %08x\n",
288 tlli_state->current, new_tlli);
289
290 /* Remember assigned TLLI */
291 tlli_state->assigned = new_tlli;
Harald Welteaed46ec2019-03-22 09:44:42 +0100292 tlli_state->bss_validated = false;
293 tlli_state->net_validated = false;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200294}
295
296uint32_t gbproxy_map_tlli(uint32_t other_tlli,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200297 struct gbproxy_link_info *link_info, int to_bss)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200298{
299 uint32_t tlli = 0;
300 struct gbproxy_tlli_state *src, *dst;
301 if (to_bss) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200302 src = &link_info->sgsn_tlli;
303 dst = &link_info->tlli;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200304 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200305 src = &link_info->tlli;
306 dst = &link_info->sgsn_tlli;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200307 }
308 if (src->current == other_tlli)
309 tlli = dst->current;
310 else if (src->assigned == other_tlli)
311 tlli = dst->assigned;
312
313 return tlli;
314}
315
316static void gbproxy_validate_tlli(struct gbproxy_tlli_state *tlli_state,
317 uint32_t tlli, int to_bss)
318{
319 LOGP(DGPRS, LOGL_DEBUG,
320 "%s({current = %08x, assigned = %08x, net_vld = %d, bss_vld = %d}, %08x)\n",
321 __func__, tlli_state->current, tlli_state->assigned,
322 tlli_state->net_validated, tlli_state->bss_validated, tlli);
323
324 if (!tlli_state->assigned || tlli_state->assigned != tlli)
325 return;
326
327 /* TODO: Is this ok? Check spec */
328 if (gprs_tlli_type(tlli) != TLLI_LOCAL)
329 return;
330
331 /* See GSM 04.08, 4.7.1.5 */
332 if (to_bss)
Harald Welteaed46ec2019-03-22 09:44:42 +0100333 tlli_state->net_validated = true;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200334 else
Harald Welteaed46ec2019-03-22 09:44:42 +0100335 tlli_state->bss_validated = true;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200336
337 if (!tlli_state->bss_validated || !tlli_state->net_validated)
338 return;
339
340 LOGP(DGPRS, LOGL_INFO,
341 "The TLLI %08x has been validated (was %08x)\n",
342 tlli_state->assigned, tlli_state->current);
343
344 tlli_state->current = tlli;
345 tlli_state->assigned = 0;
346}
347
Harald Welte8cd74402020-12-04 22:24:47 +0100348static void gbproxy_touch_link_info(struct gbproxy_bvc *bvc,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200349 struct gbproxy_link_info *link_info,
Jacob Erlbeck9a7b0d52014-09-19 13:30:14 +0200350 time_t now)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200351{
Harald Welte8cd74402020-12-04 22:24:47 +0100352 gbproxy_detach_link_info(bvc, link_info);
353 gbproxy_attach_link_info(bvc, now, link_info);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200354}
355
Harald Welte8cd74402020-12-04 22:24:47 +0100356static int gbproxy_unregister_link_info(struct gbproxy_bvc *bvc,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200357 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200358{
Harald Welte8cd74402020-12-04 22:24:47 +0100359 OSMO_ASSERT(bvc);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200360 if (!link_info)
Daniel Willmannbeade312016-11-07 17:54:29 +0100361 return 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200362
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200363 if (link_info->tlli.ptmsi == GSM_RESERVED_TMSI && !link_info->imsi_len) {
Harald Welte8cd74402020-12-04 22:24:47 +0100364 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200365 "Removing TLLI %08x from list (P-TMSI or IMSI are not set)\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200366 link_info->tlli.current);
Harald Welte8cd74402020-12-04 22:24:47 +0100367 gbproxy_delete_link_info(bvc, link_info);
Daniel Willmannbeade312016-11-07 17:54:29 +0100368 return 1;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200369 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200370
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200371 link_info->tlli.current = 0;
372 link_info->tlli.assigned = 0;
373 link_info->sgsn_tlli.current = 0;
374 link_info->sgsn_tlli.assigned = 0;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200375
Harald Welteaed46ec2019-03-22 09:44:42 +0100376 link_info->is_deregistered = true;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200377
Jacob Erlbeckd211d1d2014-09-22 13:30:46 +0200378 gbproxy_reset_link(link_info);
379
Daniel Willmannbeade312016-11-07 17:54:29 +0100380 return 0;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200381}
382
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200383int gbproxy_imsi_matches(struct gbproxy_config *cfg,
384 enum gbproxy_match_id match_id,
385 struct gbproxy_link_info *link_info)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200386{
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200387 struct gbproxy_match *match;
388 OSMO_ASSERT(match_id >= 0 && match_id < ARRAY_SIZE(cfg->matches));
389
390 match = &cfg->matches[match_id];
391 if (!match->enable)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200392 return 1;
393
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200394 return link_info != NULL && link_info->is_matching[match_id];
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200395}
396
Harald Welte8cd74402020-12-04 22:24:47 +0100397static void gbproxy_assign_imsi(struct gbproxy_bvc *bvc,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200398 struct gbproxy_link_info *link_info,
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200399 struct gprs_gb_parse_context *parse_ctx)
400{
Jacob Erlbeck8992f302014-09-19 13:17:55 +0200401 int imsi_matches;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200402 struct gbproxy_link_info *other_link_info;
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200403 enum gbproxy_match_id match_id;
Harald Welte8cd74402020-12-04 22:24:47 +0100404 OSMO_ASSERT(bvc);
405 OSMO_ASSERT(bvc->nse);
406 struct gbproxy_config *cfg = bvc->nse->cfg;
Daniel Willmann447ad442020-11-26 18:19:21 +0100407 OSMO_ASSERT(cfg);
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200408
409 /* Make sure that there is a second entry with the same IMSI */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200410 other_link_info = gbproxy_link_info_by_imsi(
Harald Welte8cd74402020-12-04 22:24:47 +0100411 bvc, parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200412
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200413 if (other_link_info && other_link_info != link_info) {
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200414 struct osmo_mobile_identity mi;
415 if (osmo_mobile_identity_decode(&mi, parse_ctx->imsi, parse_ctx->imsi_len, false)
416 || mi.type != GSM_MI_TYPE_IMSI) {
Harald Welte8cd74402020-12-04 22:24:47 +0100417 LOGPBVC(bvc, LOGL_ERROR, "Failed to decode Mobile Identity\n");
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200418 } else {
Harald Welte8cd74402020-12-04 22:24:47 +0100419 LOGPBVC(bvc, LOGL_INFO,
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200420 "Removing TLLI %08x from list (IMSI %s re-used)\n",
421 other_link_info->tlli.current, mi.imsi);
Harald Welte8cd74402020-12-04 22:24:47 +0100422 gbproxy_delete_link_info(bvc, other_link_info);
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200423 }
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200424 }
425
426 /* Update the IMSI field */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200427 gbproxy_update_link_info(link_info,
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200428 parse_ctx->imsi, parse_ctx->imsi_len);
429
430 /* Check, whether the IMSI matches */
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200431 OSMO_ASSERT(ARRAY_SIZE(link_info->is_matching) ==
Daniel Willmann447ad442020-11-26 18:19:21 +0100432 ARRAY_SIZE(cfg->matches));
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200433 for (match_id = 0; match_id < ARRAY_SIZE(link_info->is_matching);
434 ++match_id) {
435 imsi_matches = gbproxy_check_imsi(
Daniel Willmann447ad442020-11-26 18:19:21 +0100436 &cfg->matches[match_id],
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200437 parse_ctx->imsi, parse_ctx->imsi_len);
438 if (imsi_matches >= 0)
Harald Welteaed46ec2019-03-22 09:44:42 +0100439 link_info->is_matching[match_id] = imsi_matches ? true : false;
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200440 }
Jacob Erlbeck16a3cd32014-09-15 11:46:42 +0200441}
442
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200443static int gbproxy_tlli_match(const struct gbproxy_tlli_state *a,
444 const struct gbproxy_tlli_state *b)
445{
446 if (a->current && a->current == b->current)
447 return 1;
448
449 if (a->assigned && a->assigned == b->assigned)
450 return 1;
451
452 if (a->ptmsi != GSM_RESERVED_TMSI && a->ptmsi == b->ptmsi)
453 return 1;
454
455 return 0;
456}
457
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200458static void gbproxy_remove_matching_link_infos(
Harald Welte8cd74402020-12-04 22:24:47 +0100459 struct gbproxy_bvc *bvc, struct gbproxy_link_info *link_info)
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200460{
Harald Welte8cd74402020-12-04 22:24:47 +0100461 OSMO_ASSERT(bvc);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200462 struct gbproxy_link_info *info, *nxt;
Harald Welte8cd74402020-12-04 22:24:47 +0100463 struct gbproxy_patch_state *state = &bvc->patch_state;
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200464
465 /* Make sure that there is no second entry with the same P-TMSI or TLLI */
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200466 llist_for_each_entry_safe(info, nxt, &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200467 if (info == link_info)
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200468 continue;
469
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200470 if (!gbproxy_tlli_match(&link_info->tlli, &info->tlli) &&
471 (link_info->sgsn_nsei != info->sgsn_nsei ||
472 !gbproxy_tlli_match(&link_info->sgsn_tlli, &info->sgsn_tlli)))
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200473 continue;
474
Harald Welte8cd74402020-12-04 22:24:47 +0100475 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200476 "Removing TLLI %08x from list (P-TMSI/TLLI re-used)\n",
477 info->tlli.current);
Harald Welte8cd74402020-12-04 22:24:47 +0100478 gbproxy_delete_link_info(bvc, info);
Jacob Erlbeck1a024422014-09-16 14:10:27 +0200479 }
480}
481
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100482static struct gbproxy_link_info *gbproxy_get_link_info_ul(
Harald Welte8cd74402020-12-04 22:24:47 +0100483 struct gbproxy_bvc *bvc,
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100484 int *tlli_is_valid,
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200485 struct gprs_gb_parse_context *parse_ctx)
486{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200487 struct gbproxy_link_info *link_info = NULL;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200488
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100489 if (parse_ctx->tlli_enc) {
Harald Welte8cd74402020-12-04 22:24:47 +0100490 link_info = gbproxy_link_info_by_tlli(bvc, parse_ctx->tlli);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200491
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100492 if (link_info) {
493 *tlli_is_valid = 1;
494 return link_info;
495 }
496 }
497
498 *tlli_is_valid = 0;
499
500 if (!link_info && parse_ctx->imsi) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200501 link_info = gbproxy_link_info_by_imsi(
Harald Welte8cd74402020-12-04 22:24:47 +0100502 bvc, parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100503 }
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200504
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200505 if (!link_info && parse_ctx->ptmsi_enc && !parse_ctx->old_raid_is_foreign) {
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200506 uint32_t bss_ptmsi;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200507 gprs_parse_tmsi(parse_ctx->ptmsi_enc, &bss_ptmsi);
Harald Welte8cd74402020-12-04 22:24:47 +0100508 link_info = gbproxy_link_info_by_ptmsi(bvc, bss_ptmsi);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200509 }
510
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100511 if (!link_info)
512 return NULL;
513
Harald Welteaed46ec2019-03-22 09:44:42 +0100514 link_info->is_deregistered = false;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200515
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200516 return link_info;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200517}
518
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200519struct gbproxy_link_info *gbproxy_update_link_state_ul(
Harald Welte8cd74402020-12-04 22:24:47 +0100520 struct gbproxy_bvc *bvc,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200521 time_t now,
522 struct gprs_gb_parse_context *parse_ctx)
523{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200524 struct gbproxy_link_info *link_info;
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100525 int tlli_is_valid;
Harald Welte8cd74402020-12-04 22:24:47 +0100526 OSMO_ASSERT(bvc);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200527
Harald Welte8cd74402020-12-04 22:24:47 +0100528 link_info = gbproxy_get_link_info_ul(bvc, &tlli_is_valid, parse_ctx);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200529
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200530 if (parse_ctx->tlli_enc && parse_ctx->llc) {
531 uint32_t sgsn_tlli;
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100532
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200533 if (!link_info) {
Harald Welte8cd74402020-12-04 22:24:47 +0100534 LOGPBVC(bvc, LOGL_INFO, "Adding TLLI %08x to list\n",
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200535 parse_ctx->tlli);
Harald Welte8cd74402020-12-04 22:24:47 +0100536 link_info = gbproxy_link_info_alloc(bvc);
537 gbproxy_attach_link_info(bvc, now, link_info);
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200538
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200539 /* Setup TLLIs */
Harald Welte8cd74402020-12-04 22:24:47 +0100540 sgsn_tlli = gbproxy_make_sgsn_tlli(bvc, link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200541 parse_ctx->tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200542 link_info->sgsn_tlli.current = sgsn_tlli;
Jacob Erlbeckf349bae2014-09-29 12:45:36 +0200543 link_info->tlli.current = parse_ctx->tlli;
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100544 } else if (!tlli_is_valid) {
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200545 /* New TLLI (info found by IMSI or P-TMSI) */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200546 link_info->tlli.current = parse_ctx->tlli;
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100547 link_info->tlli.assigned = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200548 link_info->sgsn_tlli.current =
Harald Welte8cd74402020-12-04 22:24:47 +0100549 gbproxy_make_sgsn_tlli(bvc, link_info,
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200550 parse_ctx->tlli);
Jacob Erlbeck59ac49d2014-10-30 17:15:43 +0100551 link_info->sgsn_tlli.assigned = 0;
Harald Welte8cd74402020-12-04 22:24:47 +0100552 gbproxy_touch_link_info(bvc, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200553 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200554 sgsn_tlli = gbproxy_map_tlli(parse_ctx->tlli, link_info, 0);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200555 if (!sgsn_tlli)
Harald Welte8cd74402020-12-04 22:24:47 +0100556 sgsn_tlli = gbproxy_make_sgsn_tlli(bvc, link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200557 parse_ctx->tlli);
558
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200559 gbproxy_validate_tlli(&link_info->tlli,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200560 parse_ctx->tlli, 0);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200561 gbproxy_validate_tlli(&link_info->sgsn_tlli,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200562 sgsn_tlli, 0);
Harald Welte8cd74402020-12-04 22:24:47 +0100563 gbproxy_touch_link_info(bvc, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200564 }
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200565 } else if (link_info) {
Harald Welte8cd74402020-12-04 22:24:47 +0100566 gbproxy_touch_link_info(bvc, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200567 }
568
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200569 if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
Harald Welte8cd74402020-12-04 22:24:47 +0100570 gbproxy_assign_imsi(bvc, link_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200571
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200572 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200573}
574
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200575static struct gbproxy_link_info *gbproxy_get_link_info_dl(
Harald Welte8cd74402020-12-04 22:24:47 +0100576 struct gbproxy_bvc *bvc,
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200577 struct gprs_gb_parse_context *parse_ctx)
578{
579 struct gbproxy_link_info *link_info = NULL;
580
581 /* Which key to use depends on its availability only, if that fails, do
582 * not retry it with another key (e.g. IMSI). */
583 if (parse_ctx->tlli_enc)
Harald Welte8cd74402020-12-04 22:24:47 +0100584 link_info = gbproxy_link_info_by_sgsn_tlli(bvc, parse_ctx->tlli,
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200585 parse_ctx->peer_nsei);
586
587 /* TODO: Get link_info by (SGSN) P-TMSI if that is available (see
588 * GSM 08.18, 7.2) instead of using the IMSI as key. */
589 else if (parse_ctx->imsi)
590 link_info = gbproxy_link_info_by_imsi(
Harald Welte8cd74402020-12-04 22:24:47 +0100591 bvc, parse_ctx->imsi, parse_ctx->imsi_len);
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200592
593 if (link_info)
Harald Welteaed46ec2019-03-22 09:44:42 +0100594 link_info->is_deregistered = false;
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200595
596 return link_info;
597}
598
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200599struct gbproxy_link_info *gbproxy_update_link_state_dl(
Harald Welte8cd74402020-12-04 22:24:47 +0100600 struct gbproxy_bvc *bvc,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200601 time_t now,
602 struct gprs_gb_parse_context *parse_ctx)
603{
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200604 struct gbproxy_link_info *link_info = NULL;
Harald Welte8cd74402020-12-04 22:24:47 +0100605 OSMO_ASSERT(bvc);
606 OSMO_ASSERT(bvc->nse);
607 struct gbproxy_config *cfg = bvc->nse->cfg;
Daniel Willmann447ad442020-11-26 18:19:21 +0100608 OSMO_ASSERT(cfg);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200609
Harald Welte8cd74402020-12-04 22:24:47 +0100610 link_info = gbproxy_get_link_info_dl(bvc, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200611
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200612 if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && link_info) {
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200613 /* A new P-TMSI has been signalled in the message,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200614 * register new TLLI */
615 uint32_t new_sgsn_ptmsi;
Jacob Erlbeck91e9f552014-10-20 16:30:06 +0200616 uint32_t new_bss_ptmsi = GSM_RESERVED_TMSI;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200617 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_sgsn_ptmsi);
Jacob Erlbeck91e9f552014-10-20 16:30:06 +0200618
619 if (link_info->sgsn_tlli.ptmsi == new_sgsn_ptmsi)
620 new_bss_ptmsi = link_info->tlli.ptmsi;
621
622 if (new_bss_ptmsi == GSM_RESERVED_TMSI)
Harald Welte8cd74402020-12-04 22:24:47 +0100623 new_bss_ptmsi = gbproxy_make_bss_ptmsi(bvc, new_sgsn_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200624
Harald Welte8cd74402020-12-04 22:24:47 +0100625 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200626 "Got new PTMSI %08x from SGSN, using %08x for BSS\n",
627 new_sgsn_ptmsi, new_bss_ptmsi);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200628 /* Setup PTMSIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200629 link_info->sgsn_tlli.ptmsi = new_sgsn_ptmsi;
630 link_info->tlli.ptmsi = new_bss_ptmsi;
631 } else if (parse_ctx->tlli_enc && parse_ctx->new_ptmsi_enc && !link_info &&
Daniel Willmann447ad442020-11-26 18:19:21 +0100632 !cfg->patch_ptmsi) {
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200633 /* A new P-TMSI has been signalled in the message with an unknown
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200634 * TLLI, create a new link_info */
Jacob Erlbecka42fe9f2014-09-12 14:15:02 +0200635 /* TODO: Add a test case for this branch */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200636 uint32_t new_ptmsi;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200637 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200638
Harald Welte8cd74402020-12-04 22:24:47 +0100639 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200640 "Adding TLLI %08x to list (SGSN, new P-TMSI is %08x)\n",
641 parse_ctx->tlli, new_ptmsi);
642
Harald Welte8cd74402020-12-04 22:24:47 +0100643 link_info = gbproxy_link_info_alloc(bvc);
Jacob Erlbeckf349bae2014-09-29 12:45:36 +0200644 link_info->sgsn_tlli.current = parse_ctx->tlli;
645 link_info->tlli.current = parse_ctx->tlli;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200646 link_info->sgsn_tlli.ptmsi = new_ptmsi;
647 link_info->tlli.ptmsi = new_ptmsi;
Harald Welte8cd74402020-12-04 22:24:47 +0100648 gbproxy_attach_link_info(bvc, now, link_info);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200649 } else if (parse_ctx->tlli_enc && parse_ctx->llc && !link_info &&
Daniel Willmann447ad442020-11-26 18:19:21 +0100650 !cfg->patch_ptmsi) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200651 /* Unknown SGSN TLLI, create a new link_info */
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200652 uint32_t new_ptmsi;
Harald Welte8cd74402020-12-04 22:24:47 +0100653 link_info = gbproxy_link_info_alloc(bvc);
654 LOGPBVC(bvc, LOGL_INFO, "Adding TLLI %08x to list (SGSN)\n",
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200655 parse_ctx->tlli);
656
Harald Welte8cd74402020-12-04 22:24:47 +0100657 gbproxy_attach_link_info(bvc, now, link_info);
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200658
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200659 /* Setup TLLIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200660 link_info->sgsn_tlli.current = parse_ctx->tlli;
661 link_info->tlli.current = parse_ctx->tlli;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200662
663 if (!parse_ctx->new_ptmsi_enc)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200664 return link_info;
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200665 /* A new P-TMSI has been signalled in the message */
666
Jacob Erlbeck49389172014-10-02 16:14:47 +0200667 gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi);
Harald Welte8cd74402020-12-04 22:24:47 +0100668 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200669 "Assigning new P-TMSI %08x\n", new_ptmsi);
670 /* Setup P-TMSIs */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200671 link_info->sgsn_tlli.ptmsi = new_ptmsi;
672 link_info->tlli.ptmsi = new_ptmsi;
673 } else if (parse_ctx->tlli_enc && parse_ctx->llc && link_info) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200674 uint32_t bss_tlli = gbproxy_map_tlli(parse_ctx->tlli,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200675 link_info, 1);
676 gbproxy_validate_tlli(&link_info->sgsn_tlli, parse_ctx->tlli, 1);
677 gbproxy_validate_tlli(&link_info->tlli, bss_tlli, 1);
Harald Welte8cd74402020-12-04 22:24:47 +0100678 gbproxy_touch_link_info(bvc, link_info, now);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200679 } else if (link_info) {
Harald Welte8cd74402020-12-04 22:24:47 +0100680 gbproxy_touch_link_info(bvc, link_info, now);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200681 }
682
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200683 if (parse_ctx->imsi && link_info && link_info->imsi_len == 0)
Harald Welte8cd74402020-12-04 22:24:47 +0100684 gbproxy_assign_imsi(bvc, link_info, parse_ctx);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200685
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200686 return link_info;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200687}
688
Daniel Willmannbeade312016-11-07 17:54:29 +0100689int gbproxy_update_link_state_after(
Harald Welte8cd74402020-12-04 22:24:47 +0100690 struct gbproxy_bvc *bvc,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200691 struct gbproxy_link_info *link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200692 time_t now,
693 struct gprs_gb_parse_context *parse_ctx)
694{
Daniel Willmannbeade312016-11-07 17:54:29 +0100695 int rc = 0;
Harald Welte8cd74402020-12-04 22:24:47 +0100696 OSMO_ASSERT(bvc);
697 OSMO_ASSERT(bvc->nse);
698 struct gbproxy_config *cfg = bvc->nse->cfg;
Daniel Willmann447ad442020-11-26 18:19:21 +0100699 OSMO_ASSERT(cfg);
700
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200701 if (parse_ctx->invalidate_tlli && link_info) {
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200702 int keep_info =
Daniel Willmann447ad442020-11-26 18:19:21 +0100703 cfg->keep_link_infos == GBPROX_KEEP_ALWAYS ||
704 (cfg->keep_link_infos == GBPROX_KEEP_REATTACH &&
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200705 parse_ctx->await_reattach) ||
Daniel Willmann447ad442020-11-26 18:19:21 +0100706 (cfg->keep_link_infos == GBPROX_KEEP_IDENTIFIED &&
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200707 link_info->imsi_len > 0);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200708 if (keep_info) {
Harald Welte8cd74402020-12-04 22:24:47 +0100709 LOGPBVC(bvc, LOGL_INFO, "Unregistering TLLI %08x\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200710 link_info->tlli.current);
Harald Welte8cd74402020-12-04 22:24:47 +0100711 rc = gbproxy_unregister_link_info(bvc, link_info);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200712 } else {
Harald Welte8cd74402020-12-04 22:24:47 +0100713 LOGPBVC(bvc, LOGL_INFO, "Removing TLLI %08x from list\n",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200714 link_info->tlli.current);
Harald Welte8cd74402020-12-04 22:24:47 +0100715 gbproxy_delete_link_info(bvc, link_info);
Daniel Willmannbeade312016-11-07 17:54:29 +0100716 rc = 1;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200717 }
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200718 } else if (parse_ctx->to_bss && parse_ctx->tlli_enc &&
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200719 parse_ctx->new_ptmsi_enc && link_info) {
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200720 /* A new PTMSI has been signaled in the message,
721 * register new TLLI */
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200722 uint32_t new_sgsn_ptmsi = link_info->sgsn_tlli.ptmsi;
723 uint32_t new_bss_ptmsi = link_info->tlli.ptmsi;
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200724 uint32_t new_sgsn_tlli;
725 uint32_t new_bss_tlli = 0;
726
727 new_sgsn_tlli = gprs_tmsi2tlli(new_sgsn_ptmsi, TLLI_LOCAL);
728 if (new_bss_ptmsi != GSM_RESERVED_TMSI)
729 new_bss_tlli = gprs_tmsi2tlli(new_bss_ptmsi, TLLI_LOCAL);
Harald Welte8cd74402020-12-04 22:24:47 +0100730 LOGPBVC(bvc, LOGL_INFO,
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200731 "Assigning new TLLI %08x to SGSN, %08x to BSS\n",
732 new_sgsn_tlli, new_bss_tlli);
733
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200734 gbproxy_reassign_tlli(&link_info->sgsn_tlli,
Harald Welte8cd74402020-12-04 22:24:47 +0100735 bvc, new_sgsn_tlli);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200736 gbproxy_reassign_tlli(&link_info->tlli,
Harald Welte8cd74402020-12-04 22:24:47 +0100737 bvc, new_bss_tlli);
738 gbproxy_remove_matching_link_infos(bvc, link_info);
Jacob Erlbeckb1ee5cd2014-09-04 14:53:30 +0200739 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200740
Harald Welte8cd74402020-12-04 22:24:47 +0100741 gbproxy_remove_stale_link_infos(bvc, now);
Daniel Willmannbeade312016-11-07 17:54:29 +0100742
743 return rc;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200744}
745
746