blob: 660165796e8a3cd1e03a4cf29ebf0165511d038d [file] [log] [blame]
Jacob Erlbeck9114bee2014-08-19 12:21:01 +02001/* Gb-proxy message patching */
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
Alexander Couzens82182d02020-09-22 13:21:46 +020021#include <osmocom/gprs/gprs_msgb.h>
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020022#include <osmocom/sgsn/gb_proxy.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020023
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020024#include <osmocom/sgsn/gprs_utils.h>
25#include <osmocom/sgsn/gprs_gb_parse.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020026
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020027#include <osmocom/sgsn/debug.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020028
29#include <osmocom/gprs/protocol/gsm_08_18.h>
30#include <osmocom/core/rate_ctr.h>
Harald Welte7e82b742017-08-12 13:43:54 +020031#include <osmocom/gsm/apn.h>
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020032
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +010033extern void *tall_sgsn_ctx;
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020034
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020035/* patch RA identifier in place */
Max25c65c32018-01-08 14:43:53 +010036static void gbproxy_patch_raid(struct gsm48_ra_id *raid_enc, struct gbproxy_peer *peer,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020037 int to_bss, const char *log_text)
38{
39 struct gbproxy_patch_state *state = &peer->patch_state;
Neels Hofmeyr10719b72018-02-21 00:39:36 +010040 struct osmo_plmn_id old_plmn;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020041 struct gprs_ra_id raid;
Jacob Erlbeckcba4c0c2014-09-15 14:38:37 +020042 enum gbproxy_peer_ctr counter =
43 to_bss ?
44 GBPROX_PEER_CTR_RAID_PATCHED_SGSN :
45 GBPROX_PEER_CTR_RAID_PATCHED_BSS;
46
Daniel Willmann447ad442020-11-26 18:19:21 +010047 OSMO_ASSERT(peer->nse);
48 struct gbproxy_config *cfg = peer->nse->cfg;
49 OSMO_ASSERT(cfg);
50
Neels Hofmeyr10719b72018-02-21 00:39:36 +010051 if (!state->local_plmn.mcc || !state->local_plmn.mnc)
Jacob Erlbeckcba4c0c2014-09-15 14:38:37 +020052 return;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020053
Max25c65c32018-01-08 14:43:53 +010054 gsm48_parse_ra(&raid, (uint8_t *)raid_enc);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020055
Neels Hofmeyr10719b72018-02-21 00:39:36 +010056 old_plmn = (struct osmo_plmn_id){
57 .mcc = raid.mcc,
58 .mnc = raid.mnc,
59 .mnc_3_digits = raid.mnc_3_digits,
60 };
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020061
62 if (!to_bss) {
63 /* BSS -> SGSN */
Neels Hofmeyr10719b72018-02-21 00:39:36 +010064 if (state->local_plmn.mcc)
Daniel Willmann447ad442020-11-26 18:19:21 +010065 raid.mcc = cfg->core_plmn.mcc;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020066
Neels Hofmeyr10719b72018-02-21 00:39:36 +010067 if (state->local_plmn.mnc) {
Daniel Willmann447ad442020-11-26 18:19:21 +010068 raid.mnc = cfg->core_plmn.mnc;
69 raid.mnc_3_digits = cfg->core_plmn.mnc_3_digits;
Neels Hofmeyr10719b72018-02-21 00:39:36 +010070 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020071 } else {
72 /* SGSN -> BSS */
Neels Hofmeyr10719b72018-02-21 00:39:36 +010073 if (state->local_plmn.mcc)
74 raid.mcc = state->local_plmn.mcc;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020075
Neels Hofmeyr10719b72018-02-21 00:39:36 +010076 if (state->local_plmn.mnc) {
77 raid.mnc = state->local_plmn.mnc;
78 raid.mnc_3_digits = state->local_plmn.mnc_3_digits;
79 }
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020080 }
81
Jacob Erlbeckcba4c0c2014-09-15 14:38:37 +020082 LOGP(DGPRS, LOGL_DEBUG,
83 "Patching %s to %s: "
Neels Hofmeyr10719b72018-02-21 00:39:36 +010084 "%s-%d-%d -> %s\n",
Jacob Erlbeckcba4c0c2014-09-15 14:38:37 +020085 log_text,
86 to_bss ? "BSS" : "SGSN",
Neels Hofmeyr10719b72018-02-21 00:39:36 +010087 osmo_plmn_name(&old_plmn), raid.lac, raid.rac,
88 osmo_rai_name(&raid));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020089
Max25c65c32018-01-08 14:43:53 +010090 gsm48_encode_ra(raid_enc, &raid);
Jacob Erlbeckcba4c0c2014-09-15 14:38:37 +020091 rate_ctr_inc(&peer->ctrg->ctr[counter]);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +020092}
93
94static void gbproxy_patch_apn_ie(struct msgb *msg,
95 uint8_t *apn_ie, size_t apn_ie_len,
96 struct gbproxy_peer *peer,
97 size_t *new_apn_ie_len, const char *log_text)
98{
99 struct apn_ie_hdr {
100 uint8_t iei;
101 uint8_t apn_len;
102 uint8_t apn[0];
103 } *hdr = (void *)apn_ie;
104
105 size_t apn_len = hdr->apn_len;
106 uint8_t *apn = hdr->apn;
Daniel Willmann447ad442020-11-26 18:19:21 +0100107 OSMO_ASSERT(peer->nse);
108 struct gbproxy_config *cfg = peer->nse->cfg;
109 OSMO_ASSERT(cfg);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200110
111 OSMO_ASSERT(apn_ie_len == apn_len + sizeof(struct apn_ie_hdr));
112 OSMO_ASSERT(apn_ie_len > 2 && apn_ie_len <= 102);
113
Daniel Willmann447ad442020-11-26 18:19:21 +0100114 if (cfg->core_apn_size == 0) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200115 char str1[110];
116 /* Remove the IE */
117 LOGP(DGPRS, LOGL_DEBUG,
118 "Patching %s to SGSN: Removing APN '%s'\n",
119 log_text,
Harald Welte7e82b742017-08-12 13:43:54 +0200120 osmo_apn_to_str(str1, apn, apn_len));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200121
122 *new_apn_ie_len = 0;
Pau Espin Pedrol107fb592018-08-15 14:11:22 +0200123 msgb_resize_area(msg, apn_ie, apn_ie_len, 0);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200124 } else {
125 /* Resize the IE */
126 char str1[110];
127 char str2[110];
128
Daniel Willmann447ad442020-11-26 18:19:21 +0100129 OSMO_ASSERT(cfg->core_apn_size <= 100);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200130
131 LOGP(DGPRS, LOGL_DEBUG,
132 "Patching %s to SGSN: "
133 "Replacing APN '%s' -> '%s'\n",
134 log_text,
Harald Welte7e82b742017-08-12 13:43:54 +0200135 osmo_apn_to_str(str1, apn, apn_len),
Daniel Willmann447ad442020-11-26 18:19:21 +0100136 osmo_apn_to_str(str2, cfg->core_apn,
137 cfg->core_apn_size));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200138
Daniel Willmann447ad442020-11-26 18:19:21 +0100139 *new_apn_ie_len = cfg->core_apn_size + 2;
140 msgb_resize_area(msg, apn, apn_len, cfg->core_apn_size);
141 memcpy(apn, cfg->core_apn, cfg->core_apn_size);
142 hdr->apn_len = cfg->core_apn_size;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200143 }
144
145 rate_ctr_inc(&peer->ctrg->ctr[GBPROX_PEER_CTR_APN_PATCHED]);
146}
147
148static int gbproxy_patch_tlli(uint8_t *tlli_enc,
149 struct gbproxy_peer *peer,
150 uint32_t new_tlli,
151 int to_bss, const char *log_text)
152{
153 uint32_t tlli_be;
154 uint32_t tlli;
155 enum gbproxy_peer_ctr counter =
156 to_bss ?
157 GBPROX_PEER_CTR_TLLI_PATCHED_SGSN :
158 GBPROX_PEER_CTR_TLLI_PATCHED_BSS;
159
160 memcpy(&tlli_be, tlli_enc, sizeof(tlli_be));
161 tlli = ntohl(tlli_be);
162
163 if (tlli == new_tlli)
164 return 0;
165
166 LOGP(DGPRS, LOGL_DEBUG,
167 "Patching %ss: "
168 "Replacing %08x -> %08x\n",
169 log_text, tlli, new_tlli);
170
171 tlli_be = htonl(new_tlli);
172 memcpy(tlli_enc, &tlli_be, sizeof(tlli_be));
173
174 rate_ctr_inc(&peer->ctrg->ctr[counter]);
175
176 return 1;
177}
178
179static int gbproxy_patch_ptmsi(uint8_t *ptmsi_enc,
180 struct gbproxy_peer *peer,
181 uint32_t new_ptmsi,
182 int to_bss, const char *log_text)
183{
184 uint32_t ptmsi_be;
185 uint32_t ptmsi;
186 enum gbproxy_peer_ctr counter =
187 to_bss ?
188 GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN :
189 GBPROX_PEER_CTR_PTMSI_PATCHED_BSS;
Jacob Erlbeck49389172014-10-02 16:14:47 +0200190 memcpy(&ptmsi_be, ptmsi_enc, sizeof(ptmsi_be));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200191 ptmsi = ntohl(ptmsi_be);
192
193 if (ptmsi == new_ptmsi)
194 return 0;
195
196 LOGP(DGPRS, LOGL_DEBUG,
197 "Patching %ss: "
198 "Replacing %08x -> %08x\n",
199 log_text, ptmsi, new_ptmsi);
200
201 ptmsi_be = htonl(new_ptmsi);
Jacob Erlbeck49389172014-10-02 16:14:47 +0200202 memcpy(ptmsi_enc, &ptmsi_be, sizeof(ptmsi_be));
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200203
204 rate_ctr_inc(&peer->ctrg->ctr[counter]);
205
206 return 1;
207}
208
209int gbproxy_patch_llc(struct msgb *msg, uint8_t *llc, size_t llc_len,
210 struct gbproxy_peer *peer,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200211 struct gbproxy_link_info *link_info, int *len_change,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200212 struct gprs_gb_parse_context *parse_ctx)
213{
214 struct gprs_llc_hdr_parsed *ghp = &parse_ctx->llc_hdr_parsed;
215 int have_patched = 0;
216 int fcs;
Daniel Willmann447ad442020-11-26 18:19:21 +0100217 OSMO_ASSERT(peer->nse);
218 struct gbproxy_config *cfg = peer->nse->cfg;
219 OSMO_ASSERT(cfg);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200220
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200221 if (parse_ctx->ptmsi_enc && link_info &&
Daniel Willmann447ad442020-11-26 18:19:21 +0100222 !parse_ctx->old_raid_is_foreign && cfg->patch_ptmsi) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200223 uint32_t ptmsi;
224 if (parse_ctx->to_bss)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200225 ptmsi = link_info->tlli.ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200226 else
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200227 ptmsi = link_info->sgsn_tlli.ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200228
229 if (ptmsi != GSM_RESERVED_TMSI) {
230 if (gbproxy_patch_ptmsi(parse_ctx->ptmsi_enc, peer,
231 ptmsi, parse_ctx->to_bss, "P-TMSI"))
232 have_patched = 1;
233 } else {
234 /* TODO: invalidate old RAI if present (see below) */
235 }
236 }
237
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200238 if (parse_ctx->new_ptmsi_enc && link_info && cfg->patch_ptmsi) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200239 uint32_t ptmsi;
240 if (parse_ctx->to_bss)
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200241 ptmsi = link_info->tlli.ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200242 else
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200243 ptmsi = link_info->sgsn_tlli.ptmsi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200244
245 OSMO_ASSERT(ptmsi);
246 if (gbproxy_patch_ptmsi(parse_ctx->new_ptmsi_enc, peer,
247 ptmsi, parse_ctx->to_bss, "new P-TMSI"))
248 have_patched = 1;
249 }
250
251 if (parse_ctx->raid_enc) {
Max25c65c32018-01-08 14:43:53 +0100252 gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->raid_enc, peer, parse_ctx->to_bss,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200253 parse_ctx->llc_msg_name);
254 have_patched = 1;
255 }
256
Jacob Erlbeck948c07f2014-09-11 15:22:18 +0200257 if (parse_ctx->old_raid_enc && !parse_ctx->old_raid_is_foreign) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200258 /* TODO: Patch to invalid if P-TMSI unknown. */
Max25c65c32018-01-08 14:43:53 +0100259 gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->old_raid_enc, peer, parse_ctx->to_bss,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200260 parse_ctx->llc_msg_name);
261 have_patched = 1;
262 }
263
264 if (parse_ctx->apn_ie &&
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200265 cfg->core_apn &&
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200266 !parse_ctx->to_bss &&
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200267 gbproxy_imsi_matches(cfg, GBPROX_MATCH_PATCHING, link_info) &&
268 cfg->core_apn) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200269 size_t new_len;
270 gbproxy_patch_apn_ie(msg,
271 parse_ctx->apn_ie, parse_ctx->apn_ie_len,
272 peer, &new_len, parse_ctx->llc_msg_name);
273 *len_change += (int)new_len - (int)parse_ctx->apn_ie_len;
274
275 have_patched = 1;
276 }
277
278 if (have_patched) {
279 llc_len += *len_change;
280 ghp->crc_length += *len_change;
281
282 /* Fix FCS */
283 fcs = gprs_llc_fcs(llc, ghp->crc_length);
284 LOGP(DLLC, LOGL_DEBUG, "Updated LLC message, CRC: %06x -> %06x\n",
285 ghp->fcs, fcs);
286
287 llc[llc_len - 3] = fcs & 0xff;
288 llc[llc_len - 2] = (fcs >> 8) & 0xff;
289 llc[llc_len - 1] = (fcs >> 16) & 0xff;
290 }
291
292 return have_patched;
293}
294
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100295/* patch BSSGP message to use core_plmn.mcc/mnc on the SGSN side */
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200296void gbproxy_patch_bssgp(struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
297 struct gbproxy_peer *peer,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200298 struct gbproxy_link_info *link_info, int *len_change,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200299 struct gprs_gb_parse_context *parse_ctx)
300{
301 const char *err_info = NULL;
302 int err_ctr = -1;
Daniel Willmann447ad442020-11-26 18:19:21 +0100303 OSMO_ASSERT(peer->nse);
304 struct gbproxy_config *cfg = peer->nse->cfg;
305 OSMO_ASSERT(cfg);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200306
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200307 if (parse_ctx->bssgp_raid_enc)
Max25c65c32018-01-08 14:43:53 +0100308 gbproxy_patch_raid((struct gsm48_ra_id *)parse_ctx->bssgp_raid_enc, peer,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200309 parse_ctx->to_bss, "BSSGP");
310
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200311 if (parse_ctx->need_decryption &&
Daniel Willmann447ad442020-11-26 18:19:21 +0100312 (cfg->patch_ptmsi || cfg->core_apn)) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200313 /* Patching LLC messages has been requested
314 * explicitly, but the message (including the
315 * type) is encrypted, so we possibly fail to
316 * patch the LLC part of the message. */
317 err_ctr = GBPROX_PEER_CTR_PATCH_CRYPT_ERR;
318 err_info = "GMM message is encrypted";
319 goto patch_error;
320 }
321
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200322 if (!link_info && parse_ctx->tlli_enc && parse_ctx->to_bss) {
Jacob Erlbeck37fda772014-09-05 10:22:27 +0200323 /* Happens with unknown (not cached) TLLI coming from
324 * the SGSN */
325 /* TODO: What shall be done with the message in this case? */
326 err_ctr = GBPROX_PEER_CTR_TLLI_UNKNOWN;
327 err_info = "TLLI sent by the SGSN is unknown";
328 goto patch_error;
329 }
330
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200331 if (!link_info)
Jacob Erlbeckecbd56c2014-08-26 10:01:57 +0200332 return;
333
Daniel Willmann447ad442020-11-26 18:19:21 +0100334 if (parse_ctx->tlli_enc && cfg->patch_ptmsi) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200335 uint32_t tlli = gbproxy_map_tlli(parse_ctx->tlli,
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200336 link_info, parse_ctx->to_bss);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200337
338 if (tlli) {
339 gbproxy_patch_tlli(parse_ctx->tlli_enc, peer, tlli,
340 parse_ctx->to_bss, "TLLI");
341 parse_ctx->tlli = tlli;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200342 } else {
343 /* Internal error */
344 err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
345 err_info = "Replacement TLLI is 0";
346 goto patch_error;
347 }
348 }
349
Daniel Willmann447ad442020-11-26 18:19:21 +0100350 if (parse_ctx->bssgp_ptmsi_enc && cfg->patch_ptmsi) {
Jacob Erlbeckc37ef6c2014-09-30 13:49:43 +0200351 uint32_t ptmsi;
352 if (parse_ctx->to_bss)
353 ptmsi = link_info->tlli.ptmsi;
354 else
355 ptmsi = link_info->sgsn_tlli.ptmsi;
356
357 if (ptmsi != GSM_RESERVED_TMSI)
358 gbproxy_patch_ptmsi(
359 parse_ctx->bssgp_ptmsi_enc, peer,
360 ptmsi, parse_ctx->to_bss, "BSSGP P-TMSI");
361 }
362
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200363 if (parse_ctx->llc) {
364 uint8_t *llc = parse_ctx->llc;
365 size_t llc_len = parse_ctx->llc_len;
366 int llc_len_change = 0;
367
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200368 gbproxy_patch_llc(msg, llc, llc_len, peer, link_info,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200369 &llc_len_change, parse_ctx);
370 /* Note that the APN might have been resized here, but no
371 * pointer int the parse_ctx will refer to an adress after the
372 * APN. So it's possible to patch first and do the TLLI
373 * handling afterwards. */
374
375 if (llc_len_change) {
376 llc_len += llc_len_change;
377
378 /* Fix LLC IE len */
379 /* TODO: This is a kludge, but the a pointer to the
380 * start of the IE is not available here */
381 if (llc[-2] == BSSGP_IE_LLC_PDU && llc[-1] & 0x80) {
382 /* most probably a one byte length */
383 if (llc_len > 127) {
384 err_info = "Cannot increase size";
385 err_ctr = GBPROX_PEER_CTR_PATCH_ERR;
386 goto patch_error;
387 }
388 llc[-1] = llc_len | 0x80;
389 } else {
390 llc[-2] = (llc_len >> 8) & 0x7f;
391 llc[-1] = llc_len & 0xff;
392 }
393 *len_change += llc_len_change;
394 }
395 /* Note that the tp struct might contain invalid pointers here
396 * if the LLC field has changed its size */
397 parse_ctx->llc_len = llc_len;
398 }
399 return;
400
401patch_error:
402 OSMO_ASSERT(err_ctr >= 0);
403 rate_ctr_inc(&peer->ctrg->ctr[err_ctr]);
404 LOGP(DGPRS, LOGL_ERROR,
405 "NSEI=%u(%s) failed to patch BSSGP message as requested: %s.\n",
406 msgb_nsei(msg), parse_ctx->to_bss ? "SGSN" : "BSS",
407 err_info);
408}
409
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200410void gbproxy_clear_patch_filter(struct gbproxy_match *match)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200411{
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200412 if (match->enable) {
413 regfree(&match->re_comp);
Harald Welteaed46ec2019-03-22 09:44:42 +0100414 match->enable = false;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200415 }
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200416 talloc_free(match->re_str);
417 match->re_str = NULL;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200418}
419
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200420int gbproxy_set_patch_filter(struct gbproxy_match *match, const char *filter,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200421 const char **err_msg)
422{
423 static char err_buf[300];
424 int rc;
425
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200426 gbproxy_clear_patch_filter(match);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200427
428 if (!filter)
429 return 0;
430
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200431 rc = regcomp(&match->re_comp, filter,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200432 REG_EXTENDED | REG_NOSUB | REG_ICASE);
433
434 if (rc == 0) {
Harald Welteaed46ec2019-03-22 09:44:42 +0100435 match->enable = true;
Pau Espin Pedrolb1d1c242018-10-30 17:27:59 +0100436 match->re_str = talloc_strdup(tall_sgsn_ctx, filter);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200437 return 0;
438 }
439
440 if (err_msg) {
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200441 regerror(rc, &match->re_comp,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200442 err_buf, sizeof(err_buf));
443 *err_msg = err_buf;
444 }
445
446 return -1;
447}
448
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200449int gbproxy_check_imsi(struct gbproxy_match *match,
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200450 const uint8_t *imsi, size_t imsi_len)
451{
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200452 int rc;
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200453 struct osmo_mobile_identity mi;
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200454
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200455 if (!match->enable)
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200456 return 1;
457
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200458 rc = osmo_mobile_identity_decode(&mi, imsi, imsi_len, false);
459 if (rc || mi.type != GSM_MI_TYPE_IMSI) {
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200460 LOGP(DGPRS, LOGL_NOTICE, "Invalid IMSI %s\n",
461 osmo_hexdump(imsi, imsi_len));
462 return -1;
463 }
464
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200465 LOGP(DGPRS, LOGL_DEBUG, "Checking IMSI '%s' (%d)\n", mi.imsi, rc);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200466
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200467 rc = regexec(&match->re_comp, mi.imsi, 0, NULL, 0);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200468 if (rc == REG_NOMATCH) {
469 LOGP(DGPRS, LOGL_INFO,
470 "IMSI '%s' doesn't match pattern '%s'\n",
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200471 mi.imsi, match->re_str);
Jacob Erlbeck9114bee2014-08-19 12:21:01 +0200472 return 0;
473 }
474
475 return 1;
476}