blob: caad52e650dedcfa2f883d58187111ab00042061 [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>
42#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020043#include <osmocom/vty/misc.h>
Harald Welte799e0c92010-04-30 21:49:24 +020044
Harald Welte799e0c92010-04-30 21:49:24 +020045static struct gbproxy_config *g_cfg = NULL;
46
47/*
Pau Espin Pedrol94998fa2018-06-20 23:55:22 +020048 * vty code for gbproxy below
Harald Welte799e0c92010-04-30 21:49:24 +020049 */
Harald Welteb77c6972010-05-01 11:28:43 +020050static struct cmd_node gbproxy_node = {
Harald Welte799e0c92010-04-30 21:49:24 +020051 GBPROXY_NODE,
Harald Welte570ce242012-08-17 13:16:10 +020052 "%s(config-gbproxy)# ",
Harald Welte799e0c92010-04-30 21:49:24 +020053 1,
54};
55
Jacob Erlbeck7430da62014-09-12 15:09:56 +020056static const struct value_string keep_modes[] = {
57 {GBPROX_KEEP_NEVER, "never"},
58 {GBPROX_KEEP_REATTACH, "re-attach"},
59 {GBPROX_KEEP_IDENTIFIED, "identified"},
60 {GBPROX_KEEP_ALWAYS, "always"},
61 {0, NULL}
62};
63
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020064static const struct value_string match_ids[] = {
65 {GBPROX_MATCH_PATCHING, "patching"},
Jacob Erlbeckb36032c2014-09-25 13:21:48 +020066 {GBPROX_MATCH_ROUTING, "routing"},
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020067 {0, NULL}
68};
69
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020070static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020071{
72 struct gprs_ra_id raid;
73 gsm48_parse_ra(&raid, peer->ra);
74
75 vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
Daniel Willmann447ad442020-11-26 18:19:21 +010076 "RAI %s", peer->nse->nsei, peer->bvci, osmo_rai_name(&raid));
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020077 if (peer->blocked)
78 vty_out(vty, " [BVC-BLOCKED]");
79
80 vty_out(vty, "%s", VTY_NEWLINE);
81}
82
Harald Welte799e0c92010-04-30 21:49:24 +020083static int config_write_gbproxy(struct vty *vty)
84{
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020085 enum gbproxy_match_id match_id;
86
Harald Welte799e0c92010-04-30 21:49:24 +020087 vty_out(vty, "gbproxy%s", VTY_NEWLINE);
88
Harald Welteff3bde82010-05-19 15:09:09 +020089 vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
Harald Welte799e0c92010-04-30 21:49:24 +020090 VTY_NEWLINE);
Harald Welte799e0c92010-04-30 21:49:24 +020091
Neels Hofmeyr10719b72018-02-21 00:39:36 +010092 if (g_cfg->core_plmn.mcc > 0)
93 vty_out(vty, " core-mobile-country-code %s%s",
94 osmo_mcc_name(g_cfg->core_plmn.mcc), VTY_NEWLINE);
95 if (g_cfg->core_plmn.mnc > 0)
96 vty_out(vty, " core-mobile-network-code %s%s",
97 osmo_mnc_name(g_cfg->core_plmn.mnc, g_cfg->core_plmn.mnc_3_digits), VTY_NEWLINE);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +020098
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020099 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
100 struct gbproxy_match *match = &g_cfg->matches[match_id];
101 if (match->re_str)
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200102 vty_out(vty, " match-imsi %s %s%s",
103 get_value_string(match_ids, match_id),
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200104 match->re_str, VTY_NEWLINE);
105 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200106
Jacob Erlbeck73685282014-05-23 20:48:07 +0200107 if (g_cfg->core_apn != NULL) {
108 if (g_cfg->core_apn_size > 0) {
109 char str[500] = {0};
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200110 vty_out(vty, " core-access-point-name %s%s",
Harald Welte7e82b742017-08-12 13:43:54 +0200111 osmo_apn_to_str(str, g_cfg->core_apn,
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200112 g_cfg->core_apn_size),
113 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200114 } else {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200115 vty_out(vty, " core-access-point-name none%s",
116 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200117 }
118 }
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200119
Jacob Erlbeck25f98e62014-08-28 13:47:53 +0200120 if (g_cfg->route_to_sgsn2)
121 vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
122 VTY_NEWLINE);
123
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200124 if (g_cfg->clean_stale_timer_freq > 0)
125 vty_out(vty, " link-list clean-stale-timer %u%s",
126 g_cfg->clean_stale_timer_freq, VTY_NEWLINE);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200127 if (g_cfg->tlli_max_age > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200128 vty_out(vty, " link-list max-age %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200129 g_cfg->tlli_max_age, VTY_NEWLINE);
130 if (g_cfg->tlli_max_len > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200131 vty_out(vty, " link-list max-length %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200132 g_cfg->tlli_max_len, VTY_NEWLINE);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200133 vty_out(vty, " link-list keep-mode %s%s",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200134 get_value_string(keep_modes, g_cfg->keep_link_infos),
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200135 VTY_NEWLINE);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200136 if (g_cfg->stored_msgs_max_len > 0)
137 vty_out(vty, " link stored-msgs-max-length %"PRIu32"%s",
138 g_cfg->stored_msgs_max_len, VTY_NEWLINE);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200139
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200140
Harald Welte799e0c92010-04-30 21:49:24 +0200141 return CMD_SUCCESS;
142}
143
Harald Welte799e0c92010-04-30 21:49:24 +0200144DEFUN(cfg_gbproxy,
145 cfg_gbproxy_cmd,
146 "gbproxy",
147 "Configure the Gb proxy")
148{
149 vty->node = GBPROXY_NODE;
150 return CMD_SUCCESS;
151}
152
Harald Welte799e0c92010-04-30 21:49:24 +0200153DEFUN(cfg_nsip_sgsn_nsei,
154 cfg_nsip_sgsn_nsei_cmd,
Harald Welteff3bde82010-05-19 15:09:09 +0200155 "sgsn nsei <0-65534>",
Holger Hans Peter Freyther2eb6e2c2011-11-05 15:14:59 +0100156 "SGSN information\n"
157 "NSEI to be used in the connection with the SGSN\n"
158 "The NSEI\n")
Harald Welte799e0c92010-04-30 21:49:24 +0200159{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200160 unsigned int nsei = atoi(argv[0]);
Harald Welte799e0c92010-04-30 21:49:24 +0200161
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200162 if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
163 vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
164 nsei, VTY_NEWLINE);
165 return CMD_WARNING;
166 }
167
168 g_cfg->nsip_sgsn_nsei = nsei;
Harald Welte799e0c92010-04-30 21:49:24 +0200169 return CMD_SUCCESS;
170}
171
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200172#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
173
174DEFUN(cfg_gbproxy_core_mnc,
175 cfg_gbproxy_core_mnc_cmd,
176 "core-mobile-network-code <1-999>",
177 GBPROXY_CORE_MNC_STR "NCC value\n")
178{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100179 uint16_t mnc;
180 bool mnc_3_digits;
181 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
182 vty_out(vty, "%% Invalid MNC: %s%s", argv[0], VTY_NEWLINE);
183 return CMD_WARNING;
184 }
185 g_cfg->core_plmn.mnc = mnc;
186 g_cfg->core_plmn.mnc_3_digits = mnc_3_digits;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200187 return CMD_SUCCESS;
188}
189
190DEFUN(cfg_gbproxy_no_core_mnc,
191 cfg_gbproxy_no_core_mnc_cmd,
192 "no core-mobile-network-code",
193 NO_STR GBPROXY_CORE_MNC_STR)
194{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100195 g_cfg->core_plmn.mnc = 0;
196 g_cfg->core_plmn.mnc_3_digits = false;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200197 return CMD_SUCCESS;
198}
199
200#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
201
202DEFUN(cfg_gbproxy_core_mcc,
203 cfg_gbproxy_core_mcc_cmd,
204 "core-mobile-country-code <1-999>",
205 GBPROXY_CORE_MCC_STR "MCC value\n")
206{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100207 g_cfg->core_plmn.mcc = atoi(argv[0]);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200208 return CMD_SUCCESS;
209}
210
211DEFUN(cfg_gbproxy_no_core_mcc,
212 cfg_gbproxy_no_core_mcc_cmd,
213 "no core-mobile-country-code",
214 NO_STR GBPROXY_CORE_MCC_STR)
215{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100216 g_cfg->core_plmn.mcc = 0;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200217 return CMD_SUCCESS;
218}
219
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200220#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200221
222DEFUN(cfg_gbproxy_match_imsi,
223 cfg_gbproxy_match_imsi_cmd,
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200224 "match-imsi (patching|routing) .REGEXP",
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200225 GBPROXY_MATCH_IMSI_STR
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200226 "Patch MS related information elements on match only\n"
227 "Route to the secondary SGSN on match only\n"
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200228 "Regular expression for the IMSI match\n")
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200229{
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200230 const char *filter = argv[1];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200231 const char *err_msg = NULL;
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200232 struct gbproxy_match *match;
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200233 enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200234
235 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
236 match_id < GBPROX_MATCH_LAST);
237 match = &g_cfg->matches[match_id];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200238
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200239 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200240 vty_out(vty, "Match expression invalid: %s%s",
241 err_msg, VTY_NEWLINE);
242 return CMD_WARNING;
243 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200244
Harald Welteaed46ec2019-03-22 09:44:42 +0100245 g_cfg->acquire_imsi = true;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200246
247 return CMD_SUCCESS;
248}
249
250DEFUN(cfg_gbproxy_no_match_imsi,
251 cfg_gbproxy_no_match_imsi_cmd,
252 "no match-imsi",
253 NO_STR GBPROXY_MATCH_IMSI_STR)
254{
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200255 enum gbproxy_match_id match_id;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200256
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200257 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
258 gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200259
Harald Welteaed46ec2019-03-22 09:44:42 +0100260 g_cfg->acquire_imsi = false;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200261
262 return CMD_SUCCESS;
263}
264
Jacob Erlbeck73685282014-05-23 20:48:07 +0200265#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200266#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200267
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200268static int set_core_apn(struct vty *vty, const char *apn)
Jacob Erlbeck73685282014-05-23 20:48:07 +0200269{
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200270 int apn_len;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200271
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200272 if (!apn) {
273 talloc_free(g_cfg->core_apn);
274 g_cfg->core_apn = NULL;
275 g_cfg->core_apn_size = 0;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200276 return CMD_SUCCESS;
277 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200278
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200279 apn_len = strlen(apn);
280
281 if (apn_len >= 100) {
Jacob Erlbeck73685282014-05-23 20:48:07 +0200282 vty_out(vty, "APN string too long (max 99 chars)%s",
283 VTY_NEWLINE);
284 return CMD_WARNING;
285 }
286
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200287 if (apn_len == 0) {
288 talloc_free(g_cfg->core_apn);
289 /* TODO: replace NULL */
290 g_cfg->core_apn = talloc_zero_size(NULL, 2);
291 g_cfg->core_apn_size = 0;
292 } else {
293 /* TODO: replace NULL */
294 g_cfg->core_apn =
295 talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
296 g_cfg->core_apn_size =
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200297 gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200298 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200299
300 return CMD_SUCCESS;
301}
302
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200303DEFUN(cfg_gbproxy_core_apn,
304 cfg_gbproxy_core_apn_cmd,
305 "core-access-point-name (APN|none)",
306 GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
307{
308 if (strcmp(argv[0], "none") == 0)
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200309 return set_core_apn(vty, "");
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200310 else
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200311 return set_core_apn(vty, argv[0]);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200312}
313
Jacob Erlbeck73685282014-05-23 20:48:07 +0200314DEFUN(cfg_gbproxy_no_core_apn,
315 cfg_gbproxy_no_core_apn_cmd,
316 "no core-access-point-name",
317 NO_STR GBPROXY_CORE_APN_STR)
318{
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200319 return set_core_apn(vty, NULL);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200320}
321
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200322/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
323 * automatically when needed. This command is only left for manual testing
324 * (e.g. doing P-TMSI patching without using a secondary SGSN)
325 */
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200326#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
327
328DEFUN(cfg_gbproxy_patch_ptmsi,
329 cfg_gbproxy_patch_ptmsi_cmd,
330 "patch-ptmsi",
331 GBPROXY_PATCH_PTMSI_STR)
332{
Harald Welteaed46ec2019-03-22 09:44:42 +0100333 g_cfg->patch_ptmsi = true;
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200334
335 return CMD_SUCCESS;
336}
337
338DEFUN(cfg_gbproxy_no_patch_ptmsi,
339 cfg_gbproxy_no_patch_ptmsi_cmd,
340 "no patch-ptmsi",
341 NO_STR GBPROXY_PATCH_PTMSI_STR)
342{
Harald Welteaed46ec2019-03-22 09:44:42 +0100343 g_cfg->patch_ptmsi = false;
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200344
345 return CMD_SUCCESS;
346}
347
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200348/* TODO: Remove the acquire-imsi command, since that feature is enabled
349 * automatically when IMSI matching is enabled. This command is only left for
350 * manual testing (e.g. doing IMSI acquisition without IMSI based patching)
351 */
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200352#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
353
354DEFUN(cfg_gbproxy_acquire_imsi,
355 cfg_gbproxy_acquire_imsi_cmd,
356 "acquire-imsi",
357 GBPROXY_ACQUIRE_IMSI_STR)
358{
Harald Welteaed46ec2019-03-22 09:44:42 +0100359 g_cfg->acquire_imsi = true;
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200360
361 return CMD_SUCCESS;
362}
363
364DEFUN(cfg_gbproxy_no_acquire_imsi,
365 cfg_gbproxy_no_acquire_imsi_cmd,
366 "no acquire-imsi",
367 NO_STR GBPROXY_ACQUIRE_IMSI_STR)
368{
Harald Welteaed46ec2019-03-22 09:44:42 +0100369 g_cfg->acquire_imsi = false;
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200370
371 return CMD_SUCCESS;
372}
373
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200374#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
375
376DEFUN(cfg_gbproxy_secondary_sgsn,
377 cfg_gbproxy_secondary_sgsn_cmd,
378 "secondary-sgsn nsei <0-65534>",
379 GBPROXY_SECOND_SGSN_STR
380 "NSEI to be used in the connection with the SGSN\n"
381 "The NSEI\n")
382{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200383 unsigned int nsei = atoi(argv[0]);
384
385 if (g_cfg->nsip_sgsn_nsei == nsei) {
386 vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
387 nsei, VTY_NEWLINE);
388 return CMD_WARNING;
389 }
390
Harald Welteaed46ec2019-03-22 09:44:42 +0100391 g_cfg->route_to_sgsn2 = true;
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200392 g_cfg->nsip_sgsn2_nsei = nsei;
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200393
Harald Welteaed46ec2019-03-22 09:44:42 +0100394 g_cfg->patch_ptmsi = true;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200395
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200396 return CMD_SUCCESS;
397}
398
399DEFUN(cfg_gbproxy_no_secondary_sgsn,
400 cfg_gbproxy_no_secondary_sgsn_cmd,
401 "no secondary-sgsn",
402 NO_STR GBPROXY_SECOND_SGSN_STR)
403{
Harald Welteaed46ec2019-03-22 09:44:42 +0100404 g_cfg->route_to_sgsn2 = false;
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200405 g_cfg->nsip_sgsn2_nsei = 0xFFFF;
406
Harald Welteaed46ec2019-03-22 09:44:42 +0100407 g_cfg->patch_ptmsi = false;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200408
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200409 return CMD_SUCCESS;
410}
411
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200412#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200413#define GBPROXY_LINK_STR "Set TLLI parameters\n"
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200414
415#define GBPROXY_CLEAN_STALE_TIMER_STR "Periodic timer to clean stale links\n"
416
417DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
418 cfg_gbproxy_link_list_clean_stale_timer_cmd,
419 "link-list clean-stale-timer <1-999999>",
420 GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR
421 "Frequency at which the periodic timer is fired (in seconds)\n")
422{
Daniel Willmann447ad442020-11-26 18:19:21 +0100423 struct gbproxy_nse *nse;
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200424 g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
425
426 /* Re-schedule running timers soon in case prev frequency was really big
427 and new frequency is desired to be lower. After initial run, periodic
428 time is used. Use random() to avoid firing timers for all peers at
429 the same time */
Daniel Willmann447ad442020-11-26 18:19:21 +0100430 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
431 struct gbproxy_peer *peer;
432 llist_for_each_entry(peer, &nse->bts_peers, list)
433 osmo_timer_schedule(&peer->clean_stale_timer,
434 random() % 5, random() % 1000000);
435 }
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200436
437 return CMD_SUCCESS;
438}
439
440DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
441 cfg_gbproxy_link_list_no_clean_stale_timer_cmd,
442 "no link-list clean-stale-timer",
443 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)
444
445{
Daniel Willmann447ad442020-11-26 18:19:21 +0100446 struct gbproxy_nse *nse;
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200447 g_cfg->clean_stale_timer_freq = 0;
448
Daniel Willmann447ad442020-11-26 18:19:21 +0100449 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
450 struct gbproxy_peer *peer;
451 llist_for_each_entry(peer, &nse->bts_peers, list)
452 osmo_timer_del(&peer->clean_stale_timer);
453 }
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200454
455 return CMD_SUCCESS;
456}
457
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200458#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
459
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200460DEFUN(cfg_gbproxy_link_list_max_age,
461 cfg_gbproxy_link_list_max_age_cmd,
462 "link-list max-age <1-999999>",
463 GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200464 "Maximum age in seconds\n")
465{
466 g_cfg->tlli_max_age = atoi(argv[0]);
467
Jacob Erlbeck73685282014-05-23 20:48:07 +0200468 return CMD_SUCCESS;
469}
470
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200471DEFUN(cfg_gbproxy_link_list_no_max_age,
472 cfg_gbproxy_link_list_no_max_age_cmd,
473 "no link-list max-age",
474 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200475{
476 g_cfg->tlli_max_age = 0;
477
478 return CMD_SUCCESS;
479}
480
481#define GBPROXY_MAX_LEN_STR "Limit list length\n"
482
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200483DEFUN(cfg_gbproxy_link_list_max_len,
484 cfg_gbproxy_link_list_max_len_cmd,
485 "link-list max-length <1-99999>",
486 GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
487 "Maximum number of logical links in the list\n")
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200488{
489 g_cfg->tlli_max_len = atoi(argv[0]);
490
491 return CMD_SUCCESS;
492}
493
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200494DEFUN(cfg_gbproxy_link_list_no_max_len,
495 cfg_gbproxy_link_list_no_max_len_cmd,
496 "no link-list max-length",
497 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200498{
499 g_cfg->tlli_max_len = 0;
500
501 return CMD_SUCCESS;
502}
503
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200504DEFUN(cfg_gbproxy_link_list_keep_mode,
505 cfg_gbproxy_link_list_keep_mode_cmd,
506 "link-list keep-mode (never|re-attach|identified|always)",
507 GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200508 "Discard entry immediately after detachment\n"
509 "Keep entry if a re-attachment has be requested\n"
510 "Keep entry if it associated with an IMSI\n"
511 "Don't discard entries after detachment\n")
512{
513 int val = get_string_value(keep_modes, argv[0]);
514 OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200515 g_cfg->keep_link_infos = val;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200516
517 return CMD_SUCCESS;
518}
519
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200520DEFUN(cfg_gbproxy_link_stored_msgs_max_len,
521 cfg_gbproxy_link_stored_msgs_max_len_cmd,
522 "link stored-msgs-max-length <1-99999>",
523 GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR
524 "Maximum number of msgb stored in the logical link waiting to acquire its IMSI\n")
525{
526 g_cfg->stored_msgs_max_len = (uint32_t) atoi(argv[0]);
527
528 return CMD_SUCCESS;
529}
530
531DEFUN(cfg_gbproxy_link_no_stored_msgs_max_len,
532 cfg_gbproxy_link_no_stored_msgs_max_len_cmd,
533 "no link stored-msgs-max-length",
534 NO_STR GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR)
535{
536 g_cfg->stored_msgs_max_len = 0;
537
538 return CMD_SUCCESS;
539}
540
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200541
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200542DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
543 SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
544{
Daniel Willmann447ad442020-11-26 18:19:21 +0100545 struct gbproxy_nse *nse;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200546 int show_stats = argc >= 1;
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200547
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200548 if (show_stats)
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200549 vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200550
Daniel Willmann447ad442020-11-26 18:19:21 +0100551 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
552 struct gbproxy_peer *peer;
553 llist_for_each_entry(peer, &nse->bts_peers, list) {
554 gbprox_vty_print_peer(vty, peer);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200555
Daniel Willmann447ad442020-11-26 18:19:21 +0100556 if (show_stats)
557 vty_out_rate_ctr_group(vty, " ", peer->ctrg);
558 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200559 }
560 return CMD_SUCCESS;
561}
562
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200563DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
564 SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200565{
Daniel Willmann447ad442020-11-26 18:19:21 +0100566 struct gbproxy_nse *nse;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200567 time_t now;
568 struct timespec ts = {0,};
569
Pau Espin Pedrol36abead2018-08-17 13:27:20 +0200570 osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200571 now = ts.tv_sec;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200572
Daniel Willmann447ad442020-11-26 18:19:21 +0100573 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
574 struct gbproxy_peer *peer;
575 llist_for_each_entry(peer, &nse->bts_peers, list) {
576 struct gbproxy_link_info *link_info;
577 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200578
Daniel Willmann447ad442020-11-26 18:19:21 +0100579 gbprox_vty_print_peer(vty, peer);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200580
Daniel Willmann447ad442020-11-26 18:19:21 +0100581 llist_for_each_entry(link_info, &state->logical_links, list) {
582 time_t age = now - link_info->timestamp;
583 struct osmo_mobile_identity mi;
584 const char *imsi_str;
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200585
Daniel Willmann447ad442020-11-26 18:19:21 +0100586 if (link_info->imsi > 0) {
587 if (osmo_mobile_identity_decode(&mi, link_info->imsi, link_info->imsi_len, false)
588 || mi.type != GSM_MI_TYPE_IMSI)
589 imsi_str = "(invalid)";
590 else
591 imsi_str = mi.imsi;
592 } else {
593 imsi_str = "(none)";
594 }
595 vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
596 link_info->tlli.current, imsi_str, (int)age);
597
598 if (link_info->stored_msgs_len)
599 vty_out(vty, ", STORED %"PRIu32"/%"PRIu32,
600 link_info->stored_msgs_len,
601 g_cfg->stored_msgs_max_len);
602
603 if (g_cfg->route_to_sgsn2)
604 vty_out(vty, ", SGSN NSEI %d",
605 link_info->sgsn_nsei);
606
607 if (link_info->is_deregistered)
608 vty_out(vty, ", DE-REGISTERED");
609
610 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200611 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200612 }
613 }
614 return CMD_SUCCESS;
615}
616
617DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
618 "delete-gbproxy-peer <0-65534> bvci <2-65534>",
619 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
620 "NSEI number\n"
621 "Only delete peer with a matching BVCI\n"
622 "BVCI number\n")
623{
624 const uint16_t nsei = atoi(argv[0]);
625 const uint16_t bvci = atoi(argv[1]);
626 int counter;
627
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200628 counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200629
630 if (counter == 0) {
631 vty_out(vty, "BVC not found%s", VTY_NEWLINE);
632 return CMD_WARNING;
633 }
634
635 return CMD_SUCCESS;
636}
637
638DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
639 "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
640 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
641 "NSEI number\n"
642 "Only delete BSSGP connections (BVC)\n"
643 "Only delete dynamic NS connections (NS-VC)\n"
644 "Delete BVC and dynamic NS connections\n"
645 "Show what would be deleted instead of actually deleting\n"
646 )
647{
648 const uint16_t nsei = atoi(argv[0]);
649 const char *mode = argv[1];
650 int dry_run = argc > 2;
651 int delete_bvc = 0;
652 int delete_nsvc = 0;
653 int counter;
654
655 if (strcmp(mode, "only-bvc") == 0)
656 delete_bvc = 1;
657 else if (strcmp(mode, "only-nsvc") == 0)
658 delete_nsvc = 1;
659 else
660 delete_bvc = delete_nsvc = 1;
661
662 if (delete_bvc) {
663 if (!dry_run)
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200664 counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200665 else {
Daniel Willmann447ad442020-11-26 18:19:21 +0100666 struct gbproxy_nse *nse;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200667 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200668 counter = 0;
Daniel Willmann447ad442020-11-26 18:19:21 +0100669 llist_for_each_entry(nse, &g_cfg->nse_peers, list) {
670 if (nse->nsei != nsei)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200671 continue;
Daniel Willmann447ad442020-11-26 18:19:21 +0100672 llist_for_each_entry(peer, &nse->bts_peers, list) {
673 vty_out(vty, "BVC: ");
674 gbprox_vty_print_peer(vty, peer);
675 counter += 1;
676 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200677 }
678 }
679 vty_out(vty, "%sDeleted %d BVC%s",
680 dry_run ? "Not " : "", counter, VTY_NEWLINE);
681 }
682
683 if (delete_nsvc) {
Alexander Couzens82182d02020-09-22 13:21:46 +0200684 struct gprs_ns2_inst *nsi = g_cfg->nsi;
685 struct gprs_ns2_nse *nse;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200686
Alexander Couzens82182d02020-09-22 13:21:46 +0200687 nse = gprs_ns2_nse_by_nsei(nsi, nsei);
688 if (!nse) {
689 vty_out(vty, "NSEI not found%s", VTY_NEWLINE);
690 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200691 }
Alexander Couzens82182d02020-09-22 13:21:46 +0200692
693 /* TODO: We should NOT delete a persistent NSEI/NSVC as soon as we can check for these */
694 if (!dry_run)
695 gprs_ns2_free_nse(nse);
696
697 vty_out(vty, "%sDeleted NS-VCs for NSEI %d%s",
698 dry_run ? "Not " : "", nsei, VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200699 }
700
701 return CMD_SUCCESS;
702}
703
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200704#define GBPROXY_DELETE_LINK_STR \
705 "Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200706
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200707DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
708 "delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
709 GBPROXY_DELETE_LINK_STR
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200710 "Delete entries with a matching TLLI (hex)\n"
711 "Delete entries with a matching IMSI\n"
Jacob Erlbeckde74e722014-10-28 11:29:43 +0100712 "Delete entries with a matching SGSN NSEI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200713 "Identification to match\n")
714{
715 const uint16_t nsei = atoi(argv[0]);
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200716 enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
717 uint32_t ident = 0;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200718 const char *imsi = NULL;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200719 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200720 struct gbproxy_link_info *link_info, *nxt;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200721 struct gbproxy_patch_state *state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200722 int found = 0;
723
724 match = argv[1][0];
725
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200726 switch (match) {
727 case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
728 case MATCH_IMSI: imsi = argv[2]; break;
729 case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
730 };
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200731
732 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
733 if (!peer) {
734 vty_out(vty, "Didn't find peer with NSEI %d%s",
735 nsei, VTY_NEWLINE);
736 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200737 }
738
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200739 state = &peer->patch_state;
740
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200741 llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200742 struct osmo_mobile_identity mi;
743
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200744 switch (match) {
745 case MATCH_TLLI:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200746 if (link_info->tlli.current != ident)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200747 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200748 break;
749 case MATCH_SGSN:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200750 if (link_info->sgsn_nsei != ident)
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200751 continue;
752 break;
753 case MATCH_IMSI:
Jacob Erlbeck6a1d4282014-10-20 17:22:36 +0200754 if (!link_info->imsi)
755 continue;
Neels Hofmeyrb26a5a82020-05-29 16:53:23 +0200756 if (osmo_mobile_identity_decode(&mi, link_info->imsi, link_info->imsi_len, false)
757 || mi.type != GSM_MI_TYPE_IMSI)
758 continue;
759 if (strcmp(mi.imsi, imsi) != 0)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200760 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200761 break;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200762 }
763
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200764 vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200765 VTY_NEWLINE);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200766 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200767 found += 1;
768 }
769
770 if (!found && argc >= 2) {
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200771 vty_out(vty, "Didn't find link entry with %s %s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200772 argv[1], argv[2], VTY_NEWLINE);
773 }
774
775 return CMD_SUCCESS;
776}
777
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200778DEFUN(delete_gb_link, delete_gb_link_cmd,
779 "delete-gbproxy-link <0-65534> (stale|de-registered)",
780 GBPROXY_DELETE_LINK_STR
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200781 "Delete stale entries\n"
782 "Delete de-registered entries\n")
783{
784 const uint16_t nsei = atoi(argv[0]);
785 enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
786 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200787 struct gbproxy_link_info *link_info, *nxt;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200788 struct gbproxy_patch_state *state;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200789 time_t now;
790 struct timespec ts = {0,};
791
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200792 int found = 0;
793
794 match = argv[1][0];
795
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200796 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200797 if (!peer) {
798 vty_out(vty, "Didn't find peer with NSEI %d%s",
799 nsei, VTY_NEWLINE);
800 return CMD_WARNING;
801 }
802
803 state = &peer->patch_state;
804
Pau Espin Pedrol36abead2018-08-17 13:27:20 +0200805 osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200806 now = ts.tv_sec;
807
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200808 if (match == MATCH_STALE) {
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200809 found = gbproxy_remove_stale_link_infos(peer, now);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200810 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200811 vty_out(vty, "Deleted %d stale logical link%s%s",
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200812 found, found == 1 ? "" : "s", VTY_NEWLINE);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200813 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200814 llist_for_each_entry_safe(link_info, nxt,
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200815 &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200816 if (!link_info->is_deregistered)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200817 continue;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200818
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200819 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200820 found += 1;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200821 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200822 }
823
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200824 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200825 vty_out(vty, "Deleted %d %s logical link%s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200826 found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200827
828 return CMD_SUCCESS;
829}
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200830
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200831/*
832 * legacy commands to provide an upgrade path from "broken" releases
833 * or pre-releases
834 */
835DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
836 cfg_gbproxy_broken_apn_match_cmd,
837 "core-access-point-name none match-imsi .REGEXP",
838 GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
839 "Patch MS related information elements on match only\n"
840 "Route to the secondary SGSN on match only\n"
841 "Regular expression for the IMSI match\n")
842{
843 const char *filter = argv[0];
844 const char *err_msg = NULL;
845 struct gbproxy_match *match;
846 enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
847
848 /* apply APN none */
849 set_core_apn(vty, "");
850
851 /* do the matching... with copy and paste */
852 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
853 match_id < GBPROX_MATCH_LAST);
854 match = &g_cfg->matches[match_id];
855
856 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
857 vty_out(vty, "Match expression invalid: %s%s",
858 err_msg, VTY_NEWLINE);
859 return CMD_WARNING;
860 }
861
Harald Welteaed46ec2019-03-22 09:44:42 +0100862 g_cfg->acquire_imsi = true;
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200863
864 return CMD_SUCCESS;
865}
866
867#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
868#define GBPROXY_MAX_LEN_STR "Limit list length\n"
869DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
870 cfg_gbproxy_depr_tlli_list_max_len_cmd,
871 "tlli-list max-length <1-99999>",
872 GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
873 "Maximum number of TLLIs in the list\n")
874{
875 g_cfg->tlli_max_len = atoi(argv[0]);
876
877 return CMD_SUCCESS;
878}
879
Harald Welte799e0c92010-04-30 21:49:24 +0200880int gbproxy_vty_init(void)
881{
Harald Welte995a2d32010-05-12 16:50:52 +0000882 install_element_ve(&show_gbproxy_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200883 install_element_ve(&show_gbproxy_links_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200884
Jacob Erlbeck4211d792013-10-24 12:48:23 +0200885 install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
886 install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200887 install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
888 install_element(ENABLE_NODE, &delete_gb_link_cmd);
Holger Hans Peter Freyther90267a92013-10-23 11:24:17 +0200889
Harald Welte799e0c92010-04-30 21:49:24 +0200890 install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
891 install_node(&gbproxy_node, config_write_gbproxy);
Harald Welte799e0c92010-04-30 21:49:24 +0200892 install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200893 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
894 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200895 install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200896 install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200897 install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200898 install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200899 install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200900 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_clean_stale_timer_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200901 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
902 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
903 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200904 install_element(GBPROXY_NODE, &cfg_gbproxy_link_stored_msgs_max_len_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200905 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
906 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200907 install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200908 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200909 install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200910 install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200911 install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200912 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_clean_stale_timer_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200913 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
914 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200915 install_element(GBPROXY_NODE, &cfg_gbproxy_link_no_stored_msgs_max_len_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200916
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200917 /* broken or deprecated to allow an upgrade path */
918 install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
919 install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
920
Harald Welte799e0c92010-04-30 21:49:24 +0200921 return 0;
922}
923
924int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
925{
926 int rc;
927
928 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200929 rc = vty_read_config_file(config_file, NULL);
Harald Welte799e0c92010-04-30 21:49:24 +0200930 if (rc < 0) {
931 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
932 return rc;
933 }
934
935 return 0;
936}