blob: 379b8c2343139a6f016cc42a20c2371166a21a49 [file] [log] [blame]
Harald Welte799e0c92010-04-30 21:49:24 +02001/*
2 * (C) 2010 by Harald Welte <laforge@gnumonks.org>
3 * (C) 2010 by On-Waves
4 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01007 * 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
Harald Welte799e0c92010-04-30 21:49:24 +02009 * (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
Harald Welte9af6ddf2011-01-01 15:25:50 +010014 * GNU Affero General Public License for more details.
Harald Welte799e0c92010-04-30 21:49:24 +020015 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * 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/>.
Harald Welte799e0c92010-04-30 21:49:24 +020018 *
19 */
20
Harald Welte799e0c92010-04-30 21:49:24 +020021#include <sys/socket.h>
22#include <netinet/in.h>
23#include <arpa/inet.h>
Jacob Erlbeck73685282014-05-23 20:48:07 +020024#include <string.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020025#include <time.h>
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +020026#include <inttypes.h>
Harald Welte799e0c92010-04-30 21:49:24 +020027
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010028#include <osmocom/core/talloc.h>
Alexander Couzens82182d02020-09-22 13:21:46 +020029#include <osmocom/core/timer.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020030#include <osmocom/core/rate_ctr.h>
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020031#include <osmocom/gsm/gsm48.h>
Harald Welte799e0c92010-04-30 21:49:24 +020032
Alexander Couzens82182d02020-09-22 13:21:46 +020033#include <osmocom/gprs/gprs_ns2.h>
Harald Welte7e82b742017-08-12 13:43:54 +020034#include <osmocom/gsm/apn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080035
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020036#include <osmocom/sgsn/debug.h>
37#include <osmocom/sgsn/gb_proxy.h>
38#include <osmocom/sgsn/gprs_utils.h>
39#include <osmocom/sgsn/vty.h>
Harald Welte799e0c92010-04-30 21:49:24 +020040
Harald Welte4b037e42010-05-19 19:45:32 +020041#include <osmocom/vty/command.h>
Daniel Willmanne8c8ec92020-12-02 19:33:50 +010042#include <osmocom/vty/logging.h>
Harald Welte4b037e42010-05-19 19:45:32 +020043#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020044#include <osmocom/vty/misc.h>
Harald Welte799e0c92010-04-30 21:49:24 +020045
Harald Welte799e0c92010-04-30 21:49:24 +020046static struct gbproxy_config *g_cfg = NULL;
47
48/*
Pau Espin Pedrol94998fa2018-06-20 23:55:22 +020049 * vty code for gbproxy below
Harald Welte799e0c92010-04-30 21:49:24 +020050 */
Harald Welteb77c6972010-05-01 11:28:43 +020051static struct cmd_node gbproxy_node = {
Harald Welte799e0c92010-04-30 21:49:24 +020052 GBPROXY_NODE,
Harald Welte570ce242012-08-17 13:16:10 +020053 "%s(config-gbproxy)# ",
Harald Welte799e0c92010-04-30 21:49:24 +020054 1,
55};
56
Jacob Erlbeck7430da62014-09-12 15:09:56 +020057static const struct value_string keep_modes[] = {
58 {GBPROX_KEEP_NEVER, "never"},
59 {GBPROX_KEEP_REATTACH, "re-attach"},
60 {GBPROX_KEEP_IDENTIFIED, "identified"},
61 {GBPROX_KEEP_ALWAYS, "always"},
62 {0, NULL}
63};
64
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020065static const struct value_string match_ids[] = {
66 {GBPROX_MATCH_PATCHING, "patching"},
Jacob Erlbeckb36032c2014-09-25 13:21:48 +020067 {GBPROX_MATCH_ROUTING, "routing"},
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020068 {0, NULL}
69};
70
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020071static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020072{
73 struct gprs_ra_id raid;
74 gsm48_parse_ra(&raid, peer->ra);
75
76 vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
Daniel Willmann447ad442020-11-26 18:19:21 +010077 "RAI %s", peer->nse->nsei, peer->bvci, osmo_rai_name(&raid));
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020078 if (peer->blocked)
79 vty_out(vty, " [BVC-BLOCKED]");
80
81 vty_out(vty, "%s", VTY_NEWLINE);
82}
83
Harald Welte799e0c92010-04-30 21:49:24 +020084static int config_write_gbproxy(struct vty *vty)
85{
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020086 enum gbproxy_match_id match_id;
87
Harald Welte799e0c92010-04-30 21:49:24 +020088 vty_out(vty, "gbproxy%s", VTY_NEWLINE);
89
Harald Welteff3bde82010-05-19 15:09:09 +020090 vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
Harald Welte799e0c92010-04-30 21:49:24 +020091 VTY_NEWLINE);
Harald Welte799e0c92010-04-30 21:49:24 +020092
Neels Hofmeyr10719b72018-02-21 00:39:36 +010093 if (g_cfg->core_plmn.mcc > 0)
94 vty_out(vty, " core-mobile-country-code %s%s",
95 osmo_mcc_name(g_cfg->core_plmn.mcc), VTY_NEWLINE);
96 if (g_cfg->core_plmn.mnc > 0)
97 vty_out(vty, " core-mobile-network-code %s%s",
98 osmo_mnc_name(g_cfg->core_plmn.mnc, g_cfg->core_plmn.mnc_3_digits), VTY_NEWLINE);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +020099
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200100 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
101 struct gbproxy_match *match = &g_cfg->matches[match_id];
102 if (match->re_str)
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200103 vty_out(vty, " match-imsi %s %s%s",
104 get_value_string(match_ids, match_id),
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200105 match->re_str, VTY_NEWLINE);
106 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200107
Jacob Erlbeck73685282014-05-23 20:48:07 +0200108 if (g_cfg->core_apn != NULL) {
109 if (g_cfg->core_apn_size > 0) {
110 char str[500] = {0};
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200111 vty_out(vty, " core-access-point-name %s%s",
Harald Welte7e82b742017-08-12 13:43:54 +0200112 osmo_apn_to_str(str, g_cfg->core_apn,
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200113 g_cfg->core_apn_size),
114 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200115 } else {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200116 vty_out(vty, " core-access-point-name none%s",
117 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200118 }
119 }
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200120
Jacob Erlbeck25f98e62014-08-28 13:47:53 +0200121 if (g_cfg->route_to_sgsn2)
122 vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
123 VTY_NEWLINE);
124
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200125 if (g_cfg->clean_stale_timer_freq > 0)
126 vty_out(vty, " link-list clean-stale-timer %u%s",
127 g_cfg->clean_stale_timer_freq, VTY_NEWLINE);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200128 if (g_cfg->tlli_max_age > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200129 vty_out(vty, " link-list max-age %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200130 g_cfg->tlli_max_age, VTY_NEWLINE);
131 if (g_cfg->tlli_max_len > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200132 vty_out(vty, " link-list max-length %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200133 g_cfg->tlli_max_len, VTY_NEWLINE);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200134 vty_out(vty, " link-list keep-mode %s%s",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200135 get_value_string(keep_modes, g_cfg->keep_link_infos),
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200136 VTY_NEWLINE);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200137 if (g_cfg->stored_msgs_max_len > 0)
138 vty_out(vty, " link stored-msgs-max-length %"PRIu32"%s",
139 g_cfg->stored_msgs_max_len, VTY_NEWLINE);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200140
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200141
Harald Welte799e0c92010-04-30 21:49:24 +0200142 return CMD_SUCCESS;
143}
144
Harald Welte799e0c92010-04-30 21:49:24 +0200145DEFUN(cfg_gbproxy,
146 cfg_gbproxy_cmd,
147 "gbproxy",
148 "Configure the Gb proxy")
149{
150 vty->node = GBPROXY_NODE;
151 return CMD_SUCCESS;
152}
153
Harald Welte799e0c92010-04-30 21:49:24 +0200154DEFUN(cfg_nsip_sgsn_nsei,
155 cfg_nsip_sgsn_nsei_cmd,
Harald Welteff3bde82010-05-19 15:09:09 +0200156 "sgsn nsei <0-65534>",
Holger Hans Peter Freyther2eb6e2c2011-11-05 15:14:59 +0100157 "SGSN information\n"
158 "NSEI to be used in the connection with the SGSN\n"
159 "The NSEI\n")
Harald Welte799e0c92010-04-30 21:49:24 +0200160{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200161 unsigned int nsei = atoi(argv[0]);
Harald Welte799e0c92010-04-30 21:49:24 +0200162
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200163 if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
164 vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
165 nsei, VTY_NEWLINE);
166 return CMD_WARNING;
167 }
168
169 g_cfg->nsip_sgsn_nsei = nsei;
Harald Welte799e0c92010-04-30 21:49:24 +0200170 return CMD_SUCCESS;
171}
172
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200173#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
174
175DEFUN(cfg_gbproxy_core_mnc,
176 cfg_gbproxy_core_mnc_cmd,
177 "core-mobile-network-code <1-999>",
178 GBPROXY_CORE_MNC_STR "NCC value\n")
179{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100180 uint16_t mnc;
181 bool mnc_3_digits;
182 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
183 vty_out(vty, "%% Invalid MNC: %s%s", argv[0], VTY_NEWLINE);
184 return CMD_WARNING;
185 }
186 g_cfg->core_plmn.mnc = mnc;
187 g_cfg->core_plmn.mnc_3_digits = mnc_3_digits;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200188 return CMD_SUCCESS;
189}
190
191DEFUN(cfg_gbproxy_no_core_mnc,
192 cfg_gbproxy_no_core_mnc_cmd,
193 "no core-mobile-network-code",
194 NO_STR GBPROXY_CORE_MNC_STR)
195{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100196 g_cfg->core_plmn.mnc = 0;
197 g_cfg->core_plmn.mnc_3_digits = false;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200198 return CMD_SUCCESS;
199}
200
201#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
202
203DEFUN(cfg_gbproxy_core_mcc,
204 cfg_gbproxy_core_mcc_cmd,
205 "core-mobile-country-code <1-999>",
206 GBPROXY_CORE_MCC_STR "MCC value\n")
207{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100208 g_cfg->core_plmn.mcc = atoi(argv[0]);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200209 return CMD_SUCCESS;
210}
211
212DEFUN(cfg_gbproxy_no_core_mcc,
213 cfg_gbproxy_no_core_mcc_cmd,
214 "no core-mobile-country-code",
215 NO_STR GBPROXY_CORE_MCC_STR)
216{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100217 g_cfg->core_plmn.mcc = 0;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200218 return CMD_SUCCESS;
219}
220
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200221#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200222
223DEFUN(cfg_gbproxy_match_imsi,
224 cfg_gbproxy_match_imsi_cmd,
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200225 "match-imsi (patching|routing) .REGEXP",
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200226 GBPROXY_MATCH_IMSI_STR
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200227 "Patch MS related information elements on match only\n"
228 "Route to the secondary SGSN on match only\n"
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200229 "Regular expression for the IMSI match\n")
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200230{
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200231 const char *filter = argv[1];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200232 const char *err_msg = NULL;
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200233 struct gbproxy_match *match;
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200234 enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200235
236 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
237 match_id < GBPROX_MATCH_LAST);
238 match = &g_cfg->matches[match_id];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200239
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200240 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200241 vty_out(vty, "Match expression invalid: %s%s",
242 err_msg, VTY_NEWLINE);
243 return CMD_WARNING;
244 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200245
Harald Welteaed46ec2019-03-22 09:44:42 +0100246 g_cfg->acquire_imsi = true;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200247
248 return CMD_SUCCESS;
249}
250
251DEFUN(cfg_gbproxy_no_match_imsi,
252 cfg_gbproxy_no_match_imsi_cmd,
253 "no match-imsi",
254 NO_STR GBPROXY_MATCH_IMSI_STR)
255{
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200256 enum gbproxy_match_id match_id;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200257
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200258 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
259 gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200260
Harald Welteaed46ec2019-03-22 09:44:42 +0100261 g_cfg->acquire_imsi = false;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200262
263 return CMD_SUCCESS;
264}
265
Jacob Erlbeck73685282014-05-23 20:48:07 +0200266#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200267#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200268
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200269static int set_core_apn(struct vty *vty, const char *apn)
Jacob Erlbeck73685282014-05-23 20:48:07 +0200270{
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200271 int apn_len;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200272
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200273 if (!apn) {
274 talloc_free(g_cfg->core_apn);
275 g_cfg->core_apn = NULL;
276 g_cfg->core_apn_size = 0;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200277 return CMD_SUCCESS;
278 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200279
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200280 apn_len = strlen(apn);
281
282 if (apn_len >= 100) {
Jacob Erlbeck73685282014-05-23 20:48:07 +0200283 vty_out(vty, "APN string too long (max 99 chars)%s",
284 VTY_NEWLINE);
285 return CMD_WARNING;
286 }
287
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200288 if (apn_len == 0) {
289 talloc_free(g_cfg->core_apn);
290 /* TODO: replace NULL */
291 g_cfg->core_apn = talloc_zero_size(NULL, 2);
292 g_cfg->core_apn_size = 0;
293 } else {
294 /* TODO: replace NULL */
295 g_cfg->core_apn =
296 talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
297 g_cfg->core_apn_size =
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200298 gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200299 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200300
301 return CMD_SUCCESS;
302}
303
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200304DEFUN(cfg_gbproxy_core_apn,
305 cfg_gbproxy_core_apn_cmd,
306 "core-access-point-name (APN|none)",
307 GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
308{
309 if (strcmp(argv[0], "none") == 0)
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200310 return set_core_apn(vty, "");
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200311 else
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200312 return set_core_apn(vty, argv[0]);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200313}
314
Jacob Erlbeck73685282014-05-23 20:48:07 +0200315DEFUN(cfg_gbproxy_no_core_apn,
316 cfg_gbproxy_no_core_apn_cmd,
317 "no core-access-point-name",
318 NO_STR GBPROXY_CORE_APN_STR)
319{
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200320 return set_core_apn(vty, NULL);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200321}
322
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200323/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
324 * automatically when needed. This command is only left for manual testing
325 * (e.g. doing P-TMSI patching without using a secondary SGSN)
326 */
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200327#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
328
329DEFUN(cfg_gbproxy_patch_ptmsi,
330 cfg_gbproxy_patch_ptmsi_cmd,
331 "patch-ptmsi",
332 GBPROXY_PATCH_PTMSI_STR)
333{
Harald Welteaed46ec2019-03-22 09:44:42 +0100334 g_cfg->patch_ptmsi = true;
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200335
336 return CMD_SUCCESS;
337}
338
339DEFUN(cfg_gbproxy_no_patch_ptmsi,
340 cfg_gbproxy_no_patch_ptmsi_cmd,
341 "no patch-ptmsi",
342 NO_STR GBPROXY_PATCH_PTMSI_STR)
343{
Harald Welteaed46ec2019-03-22 09:44:42 +0100344 g_cfg->patch_ptmsi = false;
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200345
346 return CMD_SUCCESS;
347}
348
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200349/* TODO: Remove the acquire-imsi command, since that feature is enabled
350 * automatically when IMSI matching is enabled. This command is only left for
351 * manual testing (e.g. doing IMSI acquisition without IMSI based patching)
352 */
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200353#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
354
355DEFUN(cfg_gbproxy_acquire_imsi,
356 cfg_gbproxy_acquire_imsi_cmd,
357 "acquire-imsi",
358 GBPROXY_ACQUIRE_IMSI_STR)
359{
Harald Welteaed46ec2019-03-22 09:44:42 +0100360 g_cfg->acquire_imsi = true;
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200361
362 return CMD_SUCCESS;
363}
364
365DEFUN(cfg_gbproxy_no_acquire_imsi,
366 cfg_gbproxy_no_acquire_imsi_cmd,
367 "no acquire-imsi",
368 NO_STR GBPROXY_ACQUIRE_IMSI_STR)
369{
Harald Welteaed46ec2019-03-22 09:44:42 +0100370 g_cfg->acquire_imsi = false;
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200371
372 return CMD_SUCCESS;
373}
374
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200375#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
376
377DEFUN(cfg_gbproxy_secondary_sgsn,
378 cfg_gbproxy_secondary_sgsn_cmd,
379 "secondary-sgsn nsei <0-65534>",
380 GBPROXY_SECOND_SGSN_STR
381 "NSEI to be used in the connection with the SGSN\n"
382 "The NSEI\n")
383{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200384 unsigned int nsei = atoi(argv[0]);
385
386 if (g_cfg->nsip_sgsn_nsei == nsei) {
387 vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
388 nsei, VTY_NEWLINE);
389 return CMD_WARNING;
390 }
391
Harald Welteaed46ec2019-03-22 09:44:42 +0100392 g_cfg->route_to_sgsn2 = true;
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200393 g_cfg->nsip_sgsn2_nsei = nsei;
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200394
Harald Welteaed46ec2019-03-22 09:44:42 +0100395 g_cfg->patch_ptmsi = true;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200396
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200397 return CMD_SUCCESS;
398}
399
400DEFUN(cfg_gbproxy_no_secondary_sgsn,
401 cfg_gbproxy_no_secondary_sgsn_cmd,
402 "no secondary-sgsn",
403 NO_STR GBPROXY_SECOND_SGSN_STR)
404{
Harald Welteaed46ec2019-03-22 09:44:42 +0100405 g_cfg->route_to_sgsn2 = false;
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200406 g_cfg->nsip_sgsn2_nsei = 0xFFFF;
407
Harald Welteaed46ec2019-03-22 09:44:42 +0100408 g_cfg->patch_ptmsi = false;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200409
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200410 return CMD_SUCCESS;
411}
412
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200413#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200414#define GBPROXY_LINK_STR "Set TLLI parameters\n"
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200415
416#define GBPROXY_CLEAN_STALE_TIMER_STR "Periodic timer to clean stale links\n"
417
418DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
419 cfg_gbproxy_link_list_clean_stale_timer_cmd,
420 "link-list clean-stale-timer <1-999999>",
421 GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR
422 "Frequency at which the periodic timer is fired (in seconds)\n")
423{
Daniel Willmann447ad442020-11-26 18:19:21 +0100424 struct gbproxy_nse *nse;
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200425 g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
426
427 /* Re-schedule running timers soon in case prev frequency was really big
428 and new frequency is desired to be lower. After initial run, periodic
429 time is used. Use random() to avoid firing timers for all peers at
430 the same time */
Daniel Willmann447ad442020-11-26 18:19:21 +0100431 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
432 struct gbproxy_peer *peer;
433 llist_for_each_entry(peer, &nse->bts_peers, list)
434 osmo_timer_schedule(&peer->clean_stale_timer,
435 random() % 5, random() % 1000000);
436 }
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200437
438 return CMD_SUCCESS;
439}
440
441DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
442 cfg_gbproxy_link_list_no_clean_stale_timer_cmd,
443 "no link-list clean-stale-timer",
444 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)
445
446{
Daniel Willmann447ad442020-11-26 18:19:21 +0100447 struct gbproxy_nse *nse;
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200448 g_cfg->clean_stale_timer_freq = 0;
449
Daniel Willmann447ad442020-11-26 18:19:21 +0100450 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
451 struct gbproxy_peer *peer;
452 llist_for_each_entry(peer, &nse->bts_peers, list)
453 osmo_timer_del(&peer->clean_stale_timer);
454 }
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200455
456 return CMD_SUCCESS;
457}
458
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200459#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
460
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200461DEFUN(cfg_gbproxy_link_list_max_age,
462 cfg_gbproxy_link_list_max_age_cmd,
463 "link-list max-age <1-999999>",
464 GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200465 "Maximum age in seconds\n")
466{
467 g_cfg->tlli_max_age = atoi(argv[0]);
468
Jacob Erlbeck73685282014-05-23 20:48:07 +0200469 return CMD_SUCCESS;
470}
471
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200472DEFUN(cfg_gbproxy_link_list_no_max_age,
473 cfg_gbproxy_link_list_no_max_age_cmd,
474 "no link-list max-age",
475 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200476{
477 g_cfg->tlli_max_age = 0;
478
479 return CMD_SUCCESS;
480}
481
482#define GBPROXY_MAX_LEN_STR "Limit list length\n"
483
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200484DEFUN(cfg_gbproxy_link_list_max_len,
485 cfg_gbproxy_link_list_max_len_cmd,
486 "link-list max-length <1-99999>",
487 GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
488 "Maximum number of logical links in the list\n")
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200489{
490 g_cfg->tlli_max_len = atoi(argv[0]);
491
492 return CMD_SUCCESS;
493}
494
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200495DEFUN(cfg_gbproxy_link_list_no_max_len,
496 cfg_gbproxy_link_list_no_max_len_cmd,
497 "no link-list max-length",
498 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200499{
500 g_cfg->tlli_max_len = 0;
501
502 return CMD_SUCCESS;
503}
504
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200505DEFUN(cfg_gbproxy_link_list_keep_mode,
506 cfg_gbproxy_link_list_keep_mode_cmd,
507 "link-list keep-mode (never|re-attach|identified|always)",
508 GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200509 "Discard entry immediately after detachment\n"
510 "Keep entry if a re-attachment has be requested\n"
511 "Keep entry if it associated with an IMSI\n"
512 "Don't discard entries after detachment\n")
513{
514 int val = get_string_value(keep_modes, argv[0]);
515 OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200516 g_cfg->keep_link_infos = val;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200517
518 return CMD_SUCCESS;
519}
520
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200521DEFUN(cfg_gbproxy_link_stored_msgs_max_len,
522 cfg_gbproxy_link_stored_msgs_max_len_cmd,
523 "link stored-msgs-max-length <1-99999>",
524 GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR
525 "Maximum number of msgb stored in the logical link waiting to acquire its IMSI\n")
526{
527 g_cfg->stored_msgs_max_len = (uint32_t) atoi(argv[0]);
528
529 return CMD_SUCCESS;
530}
531
532DEFUN(cfg_gbproxy_link_no_stored_msgs_max_len,
533 cfg_gbproxy_link_no_stored_msgs_max_len_cmd,
534 "no link stored-msgs-max-length",
535 NO_STR GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR)
536{
537 g_cfg->stored_msgs_max_len = 0;
538
539 return CMD_SUCCESS;
540}
541
Daniel Willmanne8c8ec92020-12-02 19:33:50 +0100542static void log_set_bvc_filter(struct log_target *target,
543 const uint16_t *bvci)
544{
545 if (bvci) {
546 uintptr_t bvci_filter = *bvci | BVC_LOG_CTX_FLAG;
547 target->filter_map |= (1 << LOG_FLT_GB_BVC);
548 target->filter_data[LOG_FLT_GB_BVC] = (void *)bvci_filter;
549 } else if (target->filter_data[LOG_FLT_GB_BVC]) {
550 target->filter_map = ~(1 << LOG_FLT_GB_BVC);
551 target->filter_data[LOG_FLT_GB_BVC] = NULL;
552 }
553}
554
555DEFUN(logging_fltr_bvc,
556 logging_fltr_bvc_cmd,
557 "logging filter bvc bvci <0-65535>",
558 LOGGING_STR FILTER_STR
559 "Filter based on BSSGP VC\n"
560 "Identify BVC by BVCI\n"
561 "Numeric identifier\n")
562{
563 struct log_target *tgt;
564 uint16_t id = atoi(argv[0]);
565
566 log_tgt_mutex_lock();
567 tgt = osmo_log_vty2tgt(vty);
568 if (!tgt) {
569 log_tgt_mutex_unlock();
570 return CMD_WARNING;
571 }
572
573 log_set_bvc_filter(tgt, &id);
574 log_tgt_mutex_unlock();
575 return CMD_SUCCESS;
576}
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200577
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200578DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
579 SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
580{
Daniel Willmann447ad442020-11-26 18:19:21 +0100581 struct gbproxy_nse *nse;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200582 int show_stats = argc >= 1;
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200583
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200584 if (show_stats)
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200585 vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200586
Daniel Willmann447ad442020-11-26 18:19:21 +0100587 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
588 struct gbproxy_peer *peer;
589 llist_for_each_entry(peer, &nse->bts_peers, list) {
590 gbprox_vty_print_peer(vty, peer);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200591
Daniel Willmann447ad442020-11-26 18:19:21 +0100592 if (show_stats)
593 vty_out_rate_ctr_group(vty, " ", peer->ctrg);
594 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200595 }
596 return CMD_SUCCESS;
597}
598
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200599DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
600 SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200601{
Daniel Willmann447ad442020-11-26 18:19:21 +0100602 struct gbproxy_nse *nse;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200603 time_t now;
604 struct timespec ts = {0,};
605
Pau Espin Pedrol36abead2018-08-17 13:27:20 +0200606 osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200607 now = ts.tv_sec;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200608
Daniel Willmann447ad442020-11-26 18:19:21 +0100609 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
610 struct gbproxy_peer *peer;
611 llist_for_each_entry(peer, &nse->bts_peers, list) {
612 struct gbproxy_link_info *link_info;
613 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200614
Daniel Willmann447ad442020-11-26 18:19:21 +0100615 gbprox_vty_print_peer(vty, peer);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200616
Daniel Willmann447ad442020-11-26 18:19:21 +0100617 llist_for_each_entry(link_info, &state->logical_links, list) {
618 time_t age = now - link_info->timestamp;
619 struct osmo_mobile_identity mi;
620 const char *imsi_str;
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200621
Daniel Willmann447ad442020-11-26 18:19:21 +0100622 if (link_info->imsi > 0) {
623 if (osmo_mobile_identity_decode(&mi, link_info->imsi, link_info->imsi_len, false)
624 || mi.type != GSM_MI_TYPE_IMSI)
625 imsi_str = "(invalid)";
626 else
627 imsi_str = mi.imsi;
628 } else {
629 imsi_str = "(none)";
630 }
631 vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
632 link_info->tlli.current, imsi_str, (int)age);
633
634 if (link_info->stored_msgs_len)
635 vty_out(vty, ", STORED %"PRIu32"/%"PRIu32,
636 link_info->stored_msgs_len,
637 g_cfg->stored_msgs_max_len);
638
639 if (g_cfg->route_to_sgsn2)
640 vty_out(vty, ", SGSN NSEI %d",
641 link_info->sgsn_nsei);
642
643 if (link_info->is_deregistered)
644 vty_out(vty, ", DE-REGISTERED");
645
646 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200647 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200648 }
649 }
650 return CMD_SUCCESS;
651}
652
653DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
654 "delete-gbproxy-peer <0-65534> bvci <2-65534>",
655 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
656 "NSEI number\n"
657 "Only delete peer with a matching BVCI\n"
658 "BVCI number\n")
659{
660 const uint16_t nsei = atoi(argv[0]);
661 const uint16_t bvci = atoi(argv[1]);
662 int counter;
663
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200664 counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200665
666 if (counter == 0) {
667 vty_out(vty, "BVC not found%s", VTY_NEWLINE);
668 return CMD_WARNING;
669 }
670
671 return CMD_SUCCESS;
672}
673
674DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
675 "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
676 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
677 "NSEI number\n"
678 "Only delete BSSGP connections (BVC)\n"
679 "Only delete dynamic NS connections (NS-VC)\n"
680 "Delete BVC and dynamic NS connections\n"
681 "Show what would be deleted instead of actually deleting\n"
682 )
683{
684 const uint16_t nsei = atoi(argv[0]);
685 const char *mode = argv[1];
686 int dry_run = argc > 2;
687 int delete_bvc = 0;
688 int delete_nsvc = 0;
689 int counter;
690
691 if (strcmp(mode, "only-bvc") == 0)
692 delete_bvc = 1;
693 else if (strcmp(mode, "only-nsvc") == 0)
694 delete_nsvc = 1;
695 else
696 delete_bvc = delete_nsvc = 1;
697
698 if (delete_bvc) {
699 if (!dry_run)
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200700 counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200701 else {
Daniel Willmann447ad442020-11-26 18:19:21 +0100702 struct gbproxy_nse *nse;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200703 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200704 counter = 0;
Daniel Willmann447ad442020-11-26 18:19:21 +0100705 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
706 if (nse->nsei != nsei)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200707 continue;
Daniel Willmann447ad442020-11-26 18:19:21 +0100708 llist_for_each_entry(peer, &nse->bts_peers, list) {
709 vty_out(vty, "BVC: ");
710 gbprox_vty_print_peer(vty, peer);
711 counter += 1;
712 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200713 }
714 }
715 vty_out(vty, "%sDeleted %d BVC%s",
716 dry_run ? "Not " : "", counter, VTY_NEWLINE);
717 }
718
719 if (delete_nsvc) {
Alexander Couzens82182d02020-09-22 13:21:46 +0200720 struct gprs_ns2_inst *nsi = g_cfg->nsi;
721 struct gprs_ns2_nse *nse;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200722
Alexander Couzens82182d02020-09-22 13:21:46 +0200723 nse = gprs_ns2_nse_by_nsei(nsi, nsei);
724 if (!nse) {
725 vty_out(vty, "NSEI not found%s", VTY_NEWLINE);
726 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200727 }
Alexander Couzens82182d02020-09-22 13:21:46 +0200728
729 /* TODO: We should NOT delete a persistent NSEI/NSVC as soon as we can check for these */
730 if (!dry_run)
731 gprs_ns2_free_nse(nse);
732
733 vty_out(vty, "%sDeleted NS-VCs for NSEI %d%s",
734 dry_run ? "Not " : "", nsei, VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200735 }
736
737 return CMD_SUCCESS;
738}
739
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200740#define GBPROXY_DELETE_LINK_STR \
741 "Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200742
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200743DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
744 "delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
745 GBPROXY_DELETE_LINK_STR
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200746 "Delete entries with a matching TLLI (hex)\n"
747 "Delete entries with a matching IMSI\n"
Jacob Erlbeckde74e722014-10-28 11:29:43 +0100748 "Delete entries with a matching SGSN NSEI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200749 "Identification to match\n")
750{
751 const uint16_t nsei = atoi(argv[0]);
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200752 enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
753 uint32_t ident = 0;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200754 const char *imsi = NULL;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200755 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200756 struct gbproxy_link_info *link_info, *nxt;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200757 struct gbproxy_patch_state *state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200758 int found = 0;
759
760 match = argv[1][0];
761
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200762 switch (match) {
763 case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
764 case MATCH_IMSI: imsi = argv[2]; break;
765 case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
766 };
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200767
768 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
769 if (!peer) {
770 vty_out(vty, "Didn't find peer with NSEI %d%s",
771 nsei, VTY_NEWLINE);
772 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200773 }
774
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200775 state = &peer->patch_state;
776
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200777 llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200778 struct osmo_mobile_identity mi;
779
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200780 switch (match) {
781 case MATCH_TLLI:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200782 if (link_info->tlli.current != ident)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200783 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200784 break;
785 case MATCH_SGSN:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200786 if (link_info->sgsn_nsei != ident)
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200787 continue;
788 break;
789 case MATCH_IMSI:
Jacob Erlbeck6a1d4282014-10-20 17:22:36 +0200790 if (!link_info->imsi)
791 continue;
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200792 if (osmo_mobile_identity_decode(&mi, link_info->imsi, link_info->imsi_len, false)
793 || mi.type != GSM_MI_TYPE_IMSI)
794 continue;
795 if (strcmp(mi.imsi, imsi) != 0)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200796 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200797 break;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200798 }
799
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200800 vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200801 VTY_NEWLINE);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200802 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200803 found += 1;
804 }
805
806 if (!found && argc >= 2) {
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200807 vty_out(vty, "Didn't find link entry with %s %s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200808 argv[1], argv[2], VTY_NEWLINE);
809 }
810
811 return CMD_SUCCESS;
812}
813
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200814DEFUN(delete_gb_link, delete_gb_link_cmd,
815 "delete-gbproxy-link <0-65534> (stale|de-registered)",
816 GBPROXY_DELETE_LINK_STR
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200817 "Delete stale entries\n"
818 "Delete de-registered entries\n")
819{
820 const uint16_t nsei = atoi(argv[0]);
821 enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
822 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200823 struct gbproxy_link_info *link_info, *nxt;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200824 struct gbproxy_patch_state *state;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200825 time_t now;
826 struct timespec ts = {0,};
827
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200828 int found = 0;
829
830 match = argv[1][0];
831
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200832 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200833 if (!peer) {
834 vty_out(vty, "Didn't find peer with NSEI %d%s",
835 nsei, VTY_NEWLINE);
836 return CMD_WARNING;
837 }
838
839 state = &peer->patch_state;
840
Pau Espin Pedrol36abead2018-08-17 13:27:20 +0200841 osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200842 now = ts.tv_sec;
843
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200844 if (match == MATCH_STALE) {
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200845 found = gbproxy_remove_stale_link_infos(peer, now);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200846 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200847 vty_out(vty, "Deleted %d stale logical link%s%s",
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200848 found, found == 1 ? "" : "s", VTY_NEWLINE);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200849 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200850 llist_for_each_entry_safe(link_info, nxt,
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200851 &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200852 if (!link_info->is_deregistered)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200853 continue;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200854
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200855 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200856 found += 1;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200857 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200858 }
859
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200860 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200861 vty_out(vty, "Deleted %d %s logical link%s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200862 found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200863
864 return CMD_SUCCESS;
865}
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200866
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200867/*
868 * legacy commands to provide an upgrade path from "broken" releases
869 * or pre-releases
870 */
871DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
872 cfg_gbproxy_broken_apn_match_cmd,
873 "core-access-point-name none match-imsi .REGEXP",
874 GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
875 "Patch MS related information elements on match only\n"
876 "Route to the secondary SGSN on match only\n"
877 "Regular expression for the IMSI match\n")
878{
879 const char *filter = argv[0];
880 const char *err_msg = NULL;
881 struct gbproxy_match *match;
882 enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
883
884 /* apply APN none */
885 set_core_apn(vty, "");
886
887 /* do the matching... with copy and paste */
888 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
889 match_id < GBPROX_MATCH_LAST);
890 match = &g_cfg->matches[match_id];
891
892 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
893 vty_out(vty, "Match expression invalid: %s%s",
894 err_msg, VTY_NEWLINE);
895 return CMD_WARNING;
896 }
897
Harald Welteaed46ec2019-03-22 09:44:42 +0100898 g_cfg->acquire_imsi = true;
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200899
900 return CMD_SUCCESS;
901}
902
903#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
904#define GBPROXY_MAX_LEN_STR "Limit list length\n"
905DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
906 cfg_gbproxy_depr_tlli_list_max_len_cmd,
907 "tlli-list max-length <1-99999>",
908 GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
909 "Maximum number of TLLIs in the list\n")
910{
911 g_cfg->tlli_max_len = atoi(argv[0]);
912
913 return CMD_SUCCESS;
914}
915
Harald Welte799e0c92010-04-30 21:49:24 +0200916int gbproxy_vty_init(void)
917{
Harald Welte995a2d32010-05-12 16:50:52 +0000918 install_element_ve(&show_gbproxy_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200919 install_element_ve(&show_gbproxy_links_cmd);
Daniel Willmanne8c8ec92020-12-02 19:33:50 +0100920 install_element_ve(&logging_fltr_bvc_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200921
Jacob Erlbeck4211d792013-10-24 12:48:23 +0200922 install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
923 install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200924 install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
925 install_element(ENABLE_NODE, &delete_gb_link_cmd);
Holger Hans Peter Freyther90267a92013-10-23 11:24:17 +0200926
Harald Welte799e0c92010-04-30 21:49:24 +0200927 install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
928 install_node(&gbproxy_node, config_write_gbproxy);
Harald Welte799e0c92010-04-30 21:49:24 +0200929 install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200930 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
931 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200932 install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200933 install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200934 install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200935 install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200936 install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200937 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_clean_stale_timer_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200938 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
939 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
940 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200941 install_element(GBPROXY_NODE, &cfg_gbproxy_link_stored_msgs_max_len_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200942 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
943 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200944 install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200945 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200946 install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200947 install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200948 install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200949 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_clean_stale_timer_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200950 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
951 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200952 install_element(GBPROXY_NODE, &cfg_gbproxy_link_no_stored_msgs_max_len_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200953
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200954 /* broken or deprecated to allow an upgrade path */
955 install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
956 install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
957
Harald Welte799e0c92010-04-30 21:49:24 +0200958 return 0;
959}
960
961int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
962{
963 int rc;
964
965 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200966 rc = vty_read_config_file(config_file, NULL);
Harald Welte799e0c92010-04-30 21:49:24 +0200967 if (rc < 0) {
968 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
969 return rc;
970 }
971
972 return 0;
973}