blob: 52c39fdcd5b8285e29501eb678d36052fb8bcfd5 [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>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020029#include <osmocom/core/rate_ctr.h>
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020030#include <osmocom/gsm/gsm48.h>
Harald Welte799e0c92010-04-30 21:49:24 +020031
Harald Welteea34a4e2012-06-16 14:59:56 +080032#include <osmocom/gprs/gprs_ns.h>
Harald Welte7e82b742017-08-12 13:43:54 +020033#include <osmocom/gsm/apn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080034
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020035#include <osmocom/sgsn/debug.h>
36#include <osmocom/sgsn/gb_proxy.h>
37#include <osmocom/sgsn/gprs_utils.h>
38#include <osmocom/sgsn/vty.h>
Harald Welte799e0c92010-04-30 21:49:24 +020039
Harald Welte4b037e42010-05-19 19:45:32 +020040#include <osmocom/vty/command.h>
41#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020042#include <osmocom/vty/misc.h>
Harald Welte799e0c92010-04-30 21:49:24 +020043
Harald Welte799e0c92010-04-30 21:49:24 +020044static struct gbproxy_config *g_cfg = NULL;
45
46/*
Pau Espin Pedrol94998fa2018-06-20 23:55:22 +020047 * vty code for gbproxy below
Harald Welte799e0c92010-04-30 21:49:24 +020048 */
Harald Welteb77c6972010-05-01 11:28:43 +020049static struct cmd_node gbproxy_node = {
Harald Welte799e0c92010-04-30 21:49:24 +020050 GBPROXY_NODE,
Harald Welte570ce242012-08-17 13:16:10 +020051 "%s(config-gbproxy)# ",
Harald Welte799e0c92010-04-30 21:49:24 +020052 1,
53};
54
Jacob Erlbeck7430da62014-09-12 15:09:56 +020055static const struct value_string keep_modes[] = {
56 {GBPROX_KEEP_NEVER, "never"},
57 {GBPROX_KEEP_REATTACH, "re-attach"},
58 {GBPROX_KEEP_IDENTIFIED, "identified"},
59 {GBPROX_KEEP_ALWAYS, "always"},
60 {0, NULL}
61};
62
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020063static const struct value_string match_ids[] = {
64 {GBPROX_MATCH_PATCHING, "patching"},
Jacob Erlbeckb36032c2014-09-25 13:21:48 +020065 {GBPROX_MATCH_ROUTING, "routing"},
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020066 {0, NULL}
67};
68
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020069static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020070{
71 struct gprs_ra_id raid;
72 gsm48_parse_ra(&raid, peer->ra);
73
74 vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
Neels Hofmeyr10719b72018-02-21 00:39:36 +010075 "RAI %s", peer->nsei, peer->bvci, osmo_rai_name(&raid));
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020076 if (peer->blocked)
77 vty_out(vty, " [BVC-BLOCKED]");
78
79 vty_out(vty, "%s", VTY_NEWLINE);
80}
81
Harald Welte799e0c92010-04-30 21:49:24 +020082static int config_write_gbproxy(struct vty *vty)
83{
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020084 enum gbproxy_match_id match_id;
85
Harald Welte799e0c92010-04-30 21:49:24 +020086 vty_out(vty, "gbproxy%s", VTY_NEWLINE);
87
Harald Welteff3bde82010-05-19 15:09:09 +020088 vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
Harald Welte799e0c92010-04-30 21:49:24 +020089 VTY_NEWLINE);
Harald Welte799e0c92010-04-30 21:49:24 +020090
Neels Hofmeyr10719b72018-02-21 00:39:36 +010091 if (g_cfg->core_plmn.mcc > 0)
92 vty_out(vty, " core-mobile-country-code %s%s",
93 osmo_mcc_name(g_cfg->core_plmn.mcc), VTY_NEWLINE);
94 if (g_cfg->core_plmn.mnc > 0)
95 vty_out(vty, " core-mobile-network-code %s%s",
96 osmo_mnc_name(g_cfg->core_plmn.mnc, g_cfg->core_plmn.mnc_3_digits), VTY_NEWLINE);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +020097
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020098 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
99 struct gbproxy_match *match = &g_cfg->matches[match_id];
100 if (match->re_str)
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200101 vty_out(vty, " match-imsi %s %s%s",
102 get_value_string(match_ids, match_id),
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200103 match->re_str, VTY_NEWLINE);
104 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200105
Jacob Erlbeck73685282014-05-23 20:48:07 +0200106 if (g_cfg->core_apn != NULL) {
107 if (g_cfg->core_apn_size > 0) {
108 char str[500] = {0};
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200109 vty_out(vty, " core-access-point-name %s%s",
Harald Welte7e82b742017-08-12 13:43:54 +0200110 osmo_apn_to_str(str, g_cfg->core_apn,
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200111 g_cfg->core_apn_size),
112 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200113 } else {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200114 vty_out(vty, " core-access-point-name none%s",
115 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200116 }
117 }
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200118
Jacob Erlbeck25f98e62014-08-28 13:47:53 +0200119 if (g_cfg->route_to_sgsn2)
120 vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
121 VTY_NEWLINE);
122
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200123 if (g_cfg->clean_stale_timer_freq > 0)
124 vty_out(vty, " link-list clean-stale-timer %u%s",
125 g_cfg->clean_stale_timer_freq, VTY_NEWLINE);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200126 if (g_cfg->tlli_max_age > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200127 vty_out(vty, " link-list max-age %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200128 g_cfg->tlli_max_age, VTY_NEWLINE);
129 if (g_cfg->tlli_max_len > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200130 vty_out(vty, " link-list max-length %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200131 g_cfg->tlli_max_len, VTY_NEWLINE);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200132 vty_out(vty, " link-list keep-mode %s%s",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200133 get_value_string(keep_modes, g_cfg->keep_link_infos),
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200134 VTY_NEWLINE);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200135 if (g_cfg->stored_msgs_max_len > 0)
136 vty_out(vty, " link stored-msgs-max-length %"PRIu32"%s",
137 g_cfg->stored_msgs_max_len, VTY_NEWLINE);
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200138
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200139
Harald Welte799e0c92010-04-30 21:49:24 +0200140 return CMD_SUCCESS;
141}
142
Harald Welte799e0c92010-04-30 21:49:24 +0200143DEFUN(cfg_gbproxy,
144 cfg_gbproxy_cmd,
145 "gbproxy",
146 "Configure the Gb proxy")
147{
148 vty->node = GBPROXY_NODE;
149 return CMD_SUCCESS;
150}
151
Harald Welte799e0c92010-04-30 21:49:24 +0200152DEFUN(cfg_nsip_sgsn_nsei,
153 cfg_nsip_sgsn_nsei_cmd,
Harald Welteff3bde82010-05-19 15:09:09 +0200154 "sgsn nsei <0-65534>",
Holger Hans Peter Freyther2eb6e2c2011-11-05 15:14:59 +0100155 "SGSN information\n"
156 "NSEI to be used in the connection with the SGSN\n"
157 "The NSEI\n")
Harald Welte799e0c92010-04-30 21:49:24 +0200158{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200159 unsigned int nsei = atoi(argv[0]);
Harald Welte799e0c92010-04-30 21:49:24 +0200160
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200161 if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
162 vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
163 nsei, VTY_NEWLINE);
164 return CMD_WARNING;
165 }
166
167 g_cfg->nsip_sgsn_nsei = nsei;
Harald Welte799e0c92010-04-30 21:49:24 +0200168 return CMD_SUCCESS;
169}
170
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200171#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
172
173DEFUN(cfg_gbproxy_core_mnc,
174 cfg_gbproxy_core_mnc_cmd,
175 "core-mobile-network-code <1-999>",
176 GBPROXY_CORE_MNC_STR "NCC value\n")
177{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100178 uint16_t mnc;
179 bool mnc_3_digits;
180 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
181 vty_out(vty, "%% Invalid MNC: %s%s", argv[0], VTY_NEWLINE);
182 return CMD_WARNING;
183 }
184 g_cfg->core_plmn.mnc = mnc;
185 g_cfg->core_plmn.mnc_3_digits = mnc_3_digits;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200186 return CMD_SUCCESS;
187}
188
189DEFUN(cfg_gbproxy_no_core_mnc,
190 cfg_gbproxy_no_core_mnc_cmd,
191 "no core-mobile-network-code",
192 NO_STR GBPROXY_CORE_MNC_STR)
193{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100194 g_cfg->core_plmn.mnc = 0;
195 g_cfg->core_plmn.mnc_3_digits = false;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200196 return CMD_SUCCESS;
197}
198
199#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
200
201DEFUN(cfg_gbproxy_core_mcc,
202 cfg_gbproxy_core_mcc_cmd,
203 "core-mobile-country-code <1-999>",
204 GBPROXY_CORE_MCC_STR "MCC value\n")
205{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100206 g_cfg->core_plmn.mcc = atoi(argv[0]);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200207 return CMD_SUCCESS;
208}
209
210DEFUN(cfg_gbproxy_no_core_mcc,
211 cfg_gbproxy_no_core_mcc_cmd,
212 "no core-mobile-country-code",
213 NO_STR GBPROXY_CORE_MCC_STR)
214{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100215 g_cfg->core_plmn.mcc = 0;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200216 return CMD_SUCCESS;
217}
218
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200219#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200220
221DEFUN(cfg_gbproxy_match_imsi,
222 cfg_gbproxy_match_imsi_cmd,
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200223 "match-imsi (patching|routing) .REGEXP",
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200224 GBPROXY_MATCH_IMSI_STR
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200225 "Patch MS related information elements on match only\n"
226 "Route to the secondary SGSN on match only\n"
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200227 "Regular expression for the IMSI match\n")
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200228{
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200229 const char *filter = argv[1];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200230 const char *err_msg = NULL;
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200231 struct gbproxy_match *match;
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200232 enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200233
234 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
235 match_id < GBPROX_MATCH_LAST);
236 match = &g_cfg->matches[match_id];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200237
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200238 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200239 vty_out(vty, "Match expression invalid: %s%s",
240 err_msg, VTY_NEWLINE);
241 return CMD_WARNING;
242 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200243
244 g_cfg->acquire_imsi = 1;
245
246 return CMD_SUCCESS;
247}
248
249DEFUN(cfg_gbproxy_no_match_imsi,
250 cfg_gbproxy_no_match_imsi_cmd,
251 "no match-imsi",
252 NO_STR GBPROXY_MATCH_IMSI_STR)
253{
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200254 enum gbproxy_match_id match_id;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200255
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200256 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
257 gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200258
259 g_cfg->acquire_imsi = 0;
260
261 return CMD_SUCCESS;
262}
263
Jacob Erlbeck73685282014-05-23 20:48:07 +0200264#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200265#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200266
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200267static int set_core_apn(struct vty *vty, const char *apn)
Jacob Erlbeck73685282014-05-23 20:48:07 +0200268{
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200269 int apn_len;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200270
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200271 if (!apn) {
272 talloc_free(g_cfg->core_apn);
273 g_cfg->core_apn = NULL;
274 g_cfg->core_apn_size = 0;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200275 return CMD_SUCCESS;
276 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200277
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200278 apn_len = strlen(apn);
279
280 if (apn_len >= 100) {
Jacob Erlbeck73685282014-05-23 20:48:07 +0200281 vty_out(vty, "APN string too long (max 99 chars)%s",
282 VTY_NEWLINE);
283 return CMD_WARNING;
284 }
285
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200286 if (apn_len == 0) {
287 talloc_free(g_cfg->core_apn);
288 /* TODO: replace NULL */
289 g_cfg->core_apn = talloc_zero_size(NULL, 2);
290 g_cfg->core_apn_size = 0;
291 } else {
292 /* TODO: replace NULL */
293 g_cfg->core_apn =
294 talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
295 g_cfg->core_apn_size =
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200296 gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200297 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200298
299 return CMD_SUCCESS;
300}
301
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200302DEFUN(cfg_gbproxy_core_apn,
303 cfg_gbproxy_core_apn_cmd,
304 "core-access-point-name (APN|none)",
305 GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
306{
307 if (strcmp(argv[0], "none") == 0)
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200308 return set_core_apn(vty, "");
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200309 else
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200310 return set_core_apn(vty, argv[0]);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200311}
312
Jacob Erlbeck73685282014-05-23 20:48:07 +0200313DEFUN(cfg_gbproxy_no_core_apn,
314 cfg_gbproxy_no_core_apn_cmd,
315 "no core-access-point-name",
316 NO_STR GBPROXY_CORE_APN_STR)
317{
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200318 return set_core_apn(vty, NULL);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200319}
320
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200321/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
322 * automatically when needed. This command is only left for manual testing
323 * (e.g. doing P-TMSI patching without using a secondary SGSN)
324 */
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200325#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
326
327DEFUN(cfg_gbproxy_patch_ptmsi,
328 cfg_gbproxy_patch_ptmsi_cmd,
329 "patch-ptmsi",
330 GBPROXY_PATCH_PTMSI_STR)
331{
332 g_cfg->patch_ptmsi = 1;
333
334 return CMD_SUCCESS;
335}
336
337DEFUN(cfg_gbproxy_no_patch_ptmsi,
338 cfg_gbproxy_no_patch_ptmsi_cmd,
339 "no patch-ptmsi",
340 NO_STR GBPROXY_PATCH_PTMSI_STR)
341{
342 g_cfg->patch_ptmsi = 0;
343
344 return CMD_SUCCESS;
345}
346
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200347/* TODO: Remove the acquire-imsi command, since that feature is enabled
348 * automatically when IMSI matching is enabled. This command is only left for
349 * manual testing (e.g. doing IMSI acquisition without IMSI based patching)
350 */
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200351#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
352
353DEFUN(cfg_gbproxy_acquire_imsi,
354 cfg_gbproxy_acquire_imsi_cmd,
355 "acquire-imsi",
356 GBPROXY_ACQUIRE_IMSI_STR)
357{
358 g_cfg->acquire_imsi = 1;
359
360 return CMD_SUCCESS;
361}
362
363DEFUN(cfg_gbproxy_no_acquire_imsi,
364 cfg_gbproxy_no_acquire_imsi_cmd,
365 "no acquire-imsi",
366 NO_STR GBPROXY_ACQUIRE_IMSI_STR)
367{
368 g_cfg->acquire_imsi = 0;
369
370 return CMD_SUCCESS;
371}
372
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200373#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
374
375DEFUN(cfg_gbproxy_secondary_sgsn,
376 cfg_gbproxy_secondary_sgsn_cmd,
377 "secondary-sgsn nsei <0-65534>",
378 GBPROXY_SECOND_SGSN_STR
379 "NSEI to be used in the connection with the SGSN\n"
380 "The NSEI\n")
381{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200382 unsigned int nsei = atoi(argv[0]);
383
384 if (g_cfg->nsip_sgsn_nsei == nsei) {
385 vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
386 nsei, VTY_NEWLINE);
387 return CMD_WARNING;
388 }
389
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200390 g_cfg->route_to_sgsn2 = 1;
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200391 g_cfg->nsip_sgsn2_nsei = nsei;
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200392
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200393 g_cfg->patch_ptmsi = 1;
394
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200395 return CMD_SUCCESS;
396}
397
398DEFUN(cfg_gbproxy_no_secondary_sgsn,
399 cfg_gbproxy_no_secondary_sgsn_cmd,
400 "no secondary-sgsn",
401 NO_STR GBPROXY_SECOND_SGSN_STR)
402{
403 g_cfg->route_to_sgsn2 = 0;
404 g_cfg->nsip_sgsn2_nsei = 0xFFFF;
405
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200406 g_cfg->patch_ptmsi = 0;
407
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200408 return CMD_SUCCESS;
409}
410
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200411#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200412#define GBPROXY_LINK_STR "Set TLLI parameters\n"
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200413
414#define GBPROXY_CLEAN_STALE_TIMER_STR "Periodic timer to clean stale links\n"
415
416DEFUN(cfg_gbproxy_link_list_clean_stale_timer,
417 cfg_gbproxy_link_list_clean_stale_timer_cmd,
418 "link-list clean-stale-timer <1-999999>",
419 GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR
420 "Frequency at which the periodic timer is fired (in seconds)\n")
421{
422 struct gbproxy_peer *peer;
423 g_cfg->clean_stale_timer_freq = (unsigned int) atoi(argv[0]);
424
425 /* Re-schedule running timers soon in case prev frequency was really big
426 and new frequency is desired to be lower. After initial run, periodic
427 time is used. Use random() to avoid firing timers for all peers at
428 the same time */
429 llist_for_each_entry(peer, &g_cfg->bts_peers, list)
430 osmo_timer_schedule(&peer->clean_stale_timer,
431 random() % 5, random() % 1000000);
432
433 return CMD_SUCCESS;
434}
435
436DEFUN(cfg_gbproxy_link_list_no_clean_stale_timer,
437 cfg_gbproxy_link_list_no_clean_stale_timer_cmd,
438 "no link-list clean-stale-timer",
439 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_CLEAN_STALE_TIMER_STR)
440
441{
442 struct gbproxy_peer *peer;
443 g_cfg->clean_stale_timer_freq = 0;
444
445 llist_for_each_entry(peer, &g_cfg->bts_peers, list)
446 osmo_timer_del(&peer->clean_stale_timer);
447
448 return CMD_SUCCESS;
449}
450
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200451#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
452
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200453DEFUN(cfg_gbproxy_link_list_max_age,
454 cfg_gbproxy_link_list_max_age_cmd,
455 "link-list max-age <1-999999>",
456 GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200457 "Maximum age in seconds\n")
458{
459 g_cfg->tlli_max_age = atoi(argv[0]);
460
Jacob Erlbeck73685282014-05-23 20:48:07 +0200461 return CMD_SUCCESS;
462}
463
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200464DEFUN(cfg_gbproxy_link_list_no_max_age,
465 cfg_gbproxy_link_list_no_max_age_cmd,
466 "no link-list max-age",
467 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200468{
469 g_cfg->tlli_max_age = 0;
470
471 return CMD_SUCCESS;
472}
473
474#define GBPROXY_MAX_LEN_STR "Limit list length\n"
475
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200476DEFUN(cfg_gbproxy_link_list_max_len,
477 cfg_gbproxy_link_list_max_len_cmd,
478 "link-list max-length <1-99999>",
479 GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
480 "Maximum number of logical links in the list\n")
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200481{
482 g_cfg->tlli_max_len = atoi(argv[0]);
483
484 return CMD_SUCCESS;
485}
486
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200487DEFUN(cfg_gbproxy_link_list_no_max_len,
488 cfg_gbproxy_link_list_no_max_len_cmd,
489 "no link-list max-length",
490 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200491{
492 g_cfg->tlli_max_len = 0;
493
494 return CMD_SUCCESS;
495}
496
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200497DEFUN(cfg_gbproxy_link_list_keep_mode,
498 cfg_gbproxy_link_list_keep_mode_cmd,
499 "link-list keep-mode (never|re-attach|identified|always)",
500 GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200501 "Discard entry immediately after detachment\n"
502 "Keep entry if a re-attachment has be requested\n"
503 "Keep entry if it associated with an IMSI\n"
504 "Don't discard entries after detachment\n")
505{
506 int val = get_string_value(keep_modes, argv[0]);
507 OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200508 g_cfg->keep_link_infos = val;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200509
510 return CMD_SUCCESS;
511}
512
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200513DEFUN(cfg_gbproxy_link_stored_msgs_max_len,
514 cfg_gbproxy_link_stored_msgs_max_len_cmd,
515 "link stored-msgs-max-length <1-99999>",
516 GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR
517 "Maximum number of msgb stored in the logical link waiting to acquire its IMSI\n")
518{
519 g_cfg->stored_msgs_max_len = (uint32_t) atoi(argv[0]);
520
521 return CMD_SUCCESS;
522}
523
524DEFUN(cfg_gbproxy_link_no_stored_msgs_max_len,
525 cfg_gbproxy_link_no_stored_msgs_max_len_cmd,
526 "no link stored-msgs-max-length",
527 NO_STR GBPROXY_LINK_STR GBPROXY_MAX_LEN_STR)
528{
529 g_cfg->stored_msgs_max_len = 0;
530
531 return CMD_SUCCESS;
532}
533
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200534
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200535DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
536 SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
537{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200538 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200539 int show_stats = argc >= 1;
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200540
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200541 if (show_stats)
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200542 vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200543
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200544 llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200545 gbprox_vty_print_peer(vty, peer);
546
547 if (show_stats)
548 vty_out_rate_ctr_group(vty, " ", peer->ctrg);
549 }
550 return CMD_SUCCESS;
551}
552
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200553DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
554 SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200555{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200556 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200557 char mi_buf[200];
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200558 time_t now;
559 struct timespec ts = {0,};
560
Pau Espin Pedrol36abead2018-08-17 13:27:20 +0200561 osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200562 now = ts.tv_sec;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200563
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200564 llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200565 struct gbproxy_link_info *link_info;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200566 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200567
568 gbprox_vty_print_peer(vty, peer);
569
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200570 llist_for_each_entry(link_info, &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200571 time_t age = now - link_info->timestamp;
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200572
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200573 if (link_info->imsi > 0) {
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200574 snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
575 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200576 link_info->imsi,
577 link_info->imsi_len);
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200578 } else {
579 snprintf(mi_buf, sizeof(mi_buf), "(none)");
580 }
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200581 vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200582 link_info->tlli.current, mi_buf, (int)age);
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200583
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200584 if (link_info->stored_msgs_len)
585 vty_out(vty, ", STORED %"PRIu32"/%"PRIu32,
586 link_info->stored_msgs_len,
587 g_cfg->stored_msgs_max_len);
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200588
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200589 if (g_cfg->route_to_sgsn2)
590 vty_out(vty, ", SGSN NSEI %d",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200591 link_info->sgsn_nsei);
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200592
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200593 if (link_info->is_deregistered)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200594 vty_out(vty, ", DE-REGISTERED");
595
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200596 vty_out(vty, "%s", VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200597 }
598 }
599 return CMD_SUCCESS;
600}
601
602DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
603 "delete-gbproxy-peer <0-65534> bvci <2-65534>",
604 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
605 "NSEI number\n"
606 "Only delete peer with a matching BVCI\n"
607 "BVCI number\n")
608{
609 const uint16_t nsei = atoi(argv[0]);
610 const uint16_t bvci = atoi(argv[1]);
611 int counter;
612
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200613 counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200614
615 if (counter == 0) {
616 vty_out(vty, "BVC not found%s", VTY_NEWLINE);
617 return CMD_WARNING;
618 }
619
620 return CMD_SUCCESS;
621}
622
623DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
624 "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
625 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
626 "NSEI number\n"
627 "Only delete BSSGP connections (BVC)\n"
628 "Only delete dynamic NS connections (NS-VC)\n"
629 "Delete BVC and dynamic NS connections\n"
630 "Show what would be deleted instead of actually deleting\n"
631 )
632{
633 const uint16_t nsei = atoi(argv[0]);
634 const char *mode = argv[1];
635 int dry_run = argc > 2;
636 int delete_bvc = 0;
637 int delete_nsvc = 0;
638 int counter;
639
640 if (strcmp(mode, "only-bvc") == 0)
641 delete_bvc = 1;
642 else if (strcmp(mode, "only-nsvc") == 0)
643 delete_nsvc = 1;
644 else
645 delete_bvc = delete_nsvc = 1;
646
647 if (delete_bvc) {
648 if (!dry_run)
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200649 counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200650 else {
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200651 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200652 counter = 0;
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200653 llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200654 if (peer->nsei != nsei)
655 continue;
656
657 vty_out(vty, "BVC: ");
658 gbprox_vty_print_peer(vty, peer);
659 counter += 1;
660 }
661 }
662 vty_out(vty, "%sDeleted %d BVC%s",
663 dry_run ? "Not " : "", counter, VTY_NEWLINE);
664 }
665
666 if (delete_nsvc) {
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200667 struct gprs_ns_inst *nsi = g_cfg->nsi;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200668 struct gprs_nsvc *nsvc, *nsvc2;
669
670 counter = 0;
671 llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
672 if (nsvc->nsei != nsei)
673 continue;
674 if (nsvc->persistent)
675 continue;
676
677 if (!dry_run)
678 gprs_nsvc_delete(nsvc);
679 else
680 vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
681 "remote %s%s",
682 nsvc->nsei, nsvc->nsvci,
683 gprs_ns_ll_str(nsvc), VTY_NEWLINE);
684 counter += 1;
685 }
686 vty_out(vty, "%sDeleted %d NS-VC%s",
687 dry_run ? "Not " : "", counter, VTY_NEWLINE);
688 }
689
690 return CMD_SUCCESS;
691}
692
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200693#define GBPROXY_DELETE_LINK_STR \
694 "Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200695
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200696DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
697 "delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
698 GBPROXY_DELETE_LINK_STR
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200699 "Delete entries with a matching TLLI (hex)\n"
700 "Delete entries with a matching IMSI\n"
Jacob Erlbeckde74e722014-10-28 11:29:43 +0100701 "Delete entries with a matching SGSN NSEI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200702 "Identification to match\n")
703{
704 const uint16_t nsei = atoi(argv[0]);
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200705 enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
706 uint32_t ident = 0;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200707 const char *imsi = NULL;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200708 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200709 struct gbproxy_link_info *link_info, *nxt;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200710 struct gbproxy_patch_state *state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200711 char mi_buf[200];
712 int found = 0;
713
714 match = argv[1][0];
715
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200716 switch (match) {
717 case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
718 case MATCH_IMSI: imsi = argv[2]; break;
719 case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
720 };
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200721
722 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
723 if (!peer) {
724 vty_out(vty, "Didn't find peer with NSEI %d%s",
725 nsei, VTY_NEWLINE);
726 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200727 }
728
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200729 state = &peer->patch_state;
730
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200731 llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200732 switch (match) {
733 case MATCH_TLLI:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200734 if (link_info->tlli.current != ident)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200735 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200736 break;
737 case MATCH_SGSN:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200738 if (link_info->sgsn_nsei != ident)
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200739 continue;
740 break;
741 case MATCH_IMSI:
Jacob Erlbeck6a1d4282014-10-20 17:22:36 +0200742 if (!link_info->imsi)
743 continue;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200744 mi_buf[0] = '\0';
745 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200746 link_info->imsi,
747 link_info->imsi_len);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200748
749 if (strcmp(mi_buf, imsi) != 0)
750 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200751 break;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200752 }
753
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200754 vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200755 VTY_NEWLINE);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200756 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200757 found += 1;
758 }
759
760 if (!found && argc >= 2) {
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200761 vty_out(vty, "Didn't find link entry with %s %s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200762 argv[1], argv[2], VTY_NEWLINE);
763 }
764
765 return CMD_SUCCESS;
766}
767
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200768DEFUN(delete_gb_link, delete_gb_link_cmd,
769 "delete-gbproxy-link <0-65534> (stale|de-registered)",
770 GBPROXY_DELETE_LINK_STR
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200771 "Delete stale entries\n"
772 "Delete de-registered entries\n")
773{
774 const uint16_t nsei = atoi(argv[0]);
775 enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
776 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200777 struct gbproxy_link_info *link_info, *nxt;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200778 struct gbproxy_patch_state *state;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200779 time_t now;
780 struct timespec ts = {0,};
781
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200782 int found = 0;
783
784 match = argv[1][0];
785
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200786 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200787 if (!peer) {
788 vty_out(vty, "Didn't find peer with NSEI %d%s",
789 nsei, VTY_NEWLINE);
790 return CMD_WARNING;
791 }
792
793 state = &peer->patch_state;
794
Pau Espin Pedrol36abead2018-08-17 13:27:20 +0200795 osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200796 now = ts.tv_sec;
797
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200798 if (match == MATCH_STALE) {
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200799 found = gbproxy_remove_stale_link_infos(peer, now);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200800 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200801 vty_out(vty, "Deleted %d stale logical link%s%s",
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200802 found, found == 1 ? "" : "s", VTY_NEWLINE);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200803 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200804 llist_for_each_entry_safe(link_info, nxt,
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200805 &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200806 if (!link_info->is_deregistered)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200807 continue;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200808
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200809 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200810 found += 1;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200811 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200812 }
813
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200814 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200815 vty_out(vty, "Deleted %d %s logical link%s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200816 found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200817
818 return CMD_SUCCESS;
819}
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200820
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200821/*
822 * legacy commands to provide an upgrade path from "broken" releases
823 * or pre-releases
824 */
825DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
826 cfg_gbproxy_broken_apn_match_cmd,
827 "core-access-point-name none match-imsi .REGEXP",
828 GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
829 "Patch MS related information elements on match only\n"
830 "Route to the secondary SGSN on match only\n"
831 "Regular expression for the IMSI match\n")
832{
833 const char *filter = argv[0];
834 const char *err_msg = NULL;
835 struct gbproxy_match *match;
836 enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
837
838 /* apply APN none */
839 set_core_apn(vty, "");
840
841 /* do the matching... with copy and paste */
842 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
843 match_id < GBPROX_MATCH_LAST);
844 match = &g_cfg->matches[match_id];
845
846 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
847 vty_out(vty, "Match expression invalid: %s%s",
848 err_msg, VTY_NEWLINE);
849 return CMD_WARNING;
850 }
851
852 g_cfg->acquire_imsi = 1;
853
854 return CMD_SUCCESS;
855}
856
857#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
858#define GBPROXY_MAX_LEN_STR "Limit list length\n"
859DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
860 cfg_gbproxy_depr_tlli_list_max_len_cmd,
861 "tlli-list max-length <1-99999>",
862 GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
863 "Maximum number of TLLIs in the list\n")
864{
865 g_cfg->tlli_max_len = atoi(argv[0]);
866
867 return CMD_SUCCESS;
868}
869
Harald Welte799e0c92010-04-30 21:49:24 +0200870int gbproxy_vty_init(void)
871{
Harald Welte995a2d32010-05-12 16:50:52 +0000872 install_element_ve(&show_gbproxy_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200873 install_element_ve(&show_gbproxy_links_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200874
Jacob Erlbeck4211d792013-10-24 12:48:23 +0200875 install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
876 install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200877 install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
878 install_element(ENABLE_NODE, &delete_gb_link_cmd);
Holger Hans Peter Freyther90267a92013-10-23 11:24:17 +0200879
Harald Welte799e0c92010-04-30 21:49:24 +0200880 install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
881 install_node(&gbproxy_node, config_write_gbproxy);
Harald Welte799e0c92010-04-30 21:49:24 +0200882 install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200883 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
884 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200885 install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200886 install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200887 install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200888 install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200889 install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200890 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_clean_stale_timer_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200891 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
892 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
893 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200894 install_element(GBPROXY_NODE, &cfg_gbproxy_link_stored_msgs_max_len_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200895 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
896 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200897 install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200898 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200899 install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200900 install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200901 install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
Pau Espin Pedrol82f13612018-08-17 13:13:27 +0200902 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_clean_stale_timer_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200903 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
904 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
Pau Espin Pedrol67f1d1e2018-08-16 12:11:46 +0200905 install_element(GBPROXY_NODE, &cfg_gbproxy_link_no_stored_msgs_max_len_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200906
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200907 /* broken or deprecated to allow an upgrade path */
908 install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
909 install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
910
Harald Welte799e0c92010-04-30 21:49:24 +0200911 return 0;
912}
913
914int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
915{
916 int rc;
917
918 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200919 rc = vty_read_config_file(config_file, NULL);
Harald Welte799e0c92010-04-30 21:49:24 +0200920 if (rc < 0) {
921 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
922 return rc;
923 }
924
925 return 0;
926}