blob: d7d35fe7cd35df7e763ccdcca85a9d1e9a0d0ed6 [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>
Harald Welte799e0c92010-04-30 21:49:24 +020026
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010027#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020028#include <osmocom/core/rate_ctr.h>
Neels Hofmeyree6cfdc2017-07-13 02:03:50 +020029#include <osmocom/gsm/gsm48.h>
Harald Welte799e0c92010-04-30 21:49:24 +020030
Harald Welteea34a4e2012-06-16 14:59:56 +080031#include <osmocom/gprs/gprs_ns.h>
Harald Welte7e82b742017-08-12 13:43:54 +020032#include <osmocom/gsm/apn.h>
Harald Welteea34a4e2012-06-16 14:59:56 +080033
Neels Hofmeyr396f2e62017-09-04 15:13:25 +020034#include <osmocom/sgsn/debug.h>
35#include <osmocom/sgsn/gb_proxy.h>
36#include <osmocom/sgsn/gprs_utils.h>
37#include <osmocom/sgsn/vty.h>
Harald Welte799e0c92010-04-30 21:49:24 +020038
Harald Welte4b037e42010-05-19 19:45:32 +020039#include <osmocom/vty/command.h>
40#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020041#include <osmocom/vty/misc.h>
Harald Welte799e0c92010-04-30 21:49:24 +020042
Harald Welte799e0c92010-04-30 21:49:24 +020043static struct gbproxy_config *g_cfg = NULL;
44
45/*
Pau Espin Pedrol94998fa2018-06-20 23:55:22 +020046 * vty code for gbproxy below
Harald Welte799e0c92010-04-30 21:49:24 +020047 */
Harald Welteb77c6972010-05-01 11:28:43 +020048static struct cmd_node gbproxy_node = {
Harald Welte799e0c92010-04-30 21:49:24 +020049 GBPROXY_NODE,
Harald Welte570ce242012-08-17 13:16:10 +020050 "%s(config-gbproxy)# ",
Harald Welte799e0c92010-04-30 21:49:24 +020051 1,
52};
53
Jacob Erlbeck7430da62014-09-12 15:09:56 +020054static const struct value_string keep_modes[] = {
55 {GBPROX_KEEP_NEVER, "never"},
56 {GBPROX_KEEP_REATTACH, "re-attach"},
57 {GBPROX_KEEP_IDENTIFIED, "identified"},
58 {GBPROX_KEEP_ALWAYS, "always"},
59 {0, NULL}
60};
61
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020062static const struct value_string match_ids[] = {
63 {GBPROX_MATCH_PATCHING, "patching"},
Jacob Erlbeckb36032c2014-09-25 13:21:48 +020064 {GBPROX_MATCH_ROUTING, "routing"},
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +020065 {0, NULL}
66};
67
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +020068static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020069{
70 struct gprs_ra_id raid;
71 gsm48_parse_ra(&raid, peer->ra);
72
73 vty_out(vty, "NSEI %5u, PTP-BVCI %5u, "
Neels Hofmeyr10719b72018-02-21 00:39:36 +010074 "RAI %s", peer->nsei, peer->bvci, osmo_rai_name(&raid));
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +020075 if (peer->blocked)
76 vty_out(vty, " [BVC-BLOCKED]");
77
78 vty_out(vty, "%s", VTY_NEWLINE);
79}
80
Harald Welte799e0c92010-04-30 21:49:24 +020081static int config_write_gbproxy(struct vty *vty)
82{
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020083 enum gbproxy_match_id match_id;
84
Harald Welte799e0c92010-04-30 21:49:24 +020085 vty_out(vty, "gbproxy%s", VTY_NEWLINE);
86
Harald Welteff3bde82010-05-19 15:09:09 +020087 vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
Harald Welte799e0c92010-04-30 21:49:24 +020088 VTY_NEWLINE);
Harald Welte799e0c92010-04-30 21:49:24 +020089
Neels Hofmeyr10719b72018-02-21 00:39:36 +010090 if (g_cfg->core_plmn.mcc > 0)
91 vty_out(vty, " core-mobile-country-code %s%s",
92 osmo_mcc_name(g_cfg->core_plmn.mcc), VTY_NEWLINE);
93 if (g_cfg->core_plmn.mnc > 0)
94 vty_out(vty, " core-mobile-network-code %s%s",
95 osmo_mnc_name(g_cfg->core_plmn.mnc, g_cfg->core_plmn.mnc_3_digits), VTY_NEWLINE);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +020096
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +020097 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id) {
98 struct gbproxy_match *match = &g_cfg->matches[match_id];
99 if (match->re_str)
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200100 vty_out(vty, " match-imsi %s %s%s",
101 get_value_string(match_ids, match_id),
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200102 match->re_str, VTY_NEWLINE);
103 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200104
Jacob Erlbeck73685282014-05-23 20:48:07 +0200105 if (g_cfg->core_apn != NULL) {
106 if (g_cfg->core_apn_size > 0) {
107 char str[500] = {0};
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200108 vty_out(vty, " core-access-point-name %s%s",
Harald Welte7e82b742017-08-12 13:43:54 +0200109 osmo_apn_to_str(str, g_cfg->core_apn,
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200110 g_cfg->core_apn_size),
111 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200112 } else {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200113 vty_out(vty, " core-access-point-name none%s",
114 VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200115 }
116 }
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200117
Jacob Erlbeck25f98e62014-08-28 13:47:53 +0200118 if (g_cfg->route_to_sgsn2)
119 vty_out(vty, " secondary-sgsn nsei %u%s", g_cfg->nsip_sgsn2_nsei,
120 VTY_NEWLINE);
121
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200122 if (g_cfg->tlli_max_age > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200123 vty_out(vty, " link-list max-age %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200124 g_cfg->tlli_max_age, VTY_NEWLINE);
125 if (g_cfg->tlli_max_len > 0)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200126 vty_out(vty, " link-list max-length %d%s",
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200127 g_cfg->tlli_max_len, VTY_NEWLINE);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200128 vty_out(vty, " link-list keep-mode %s%s",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200129 get_value_string(keep_modes, g_cfg->keep_link_infos),
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200130 VTY_NEWLINE);
131
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200132
Harald Welte799e0c92010-04-30 21:49:24 +0200133 return CMD_SUCCESS;
134}
135
Harald Welte799e0c92010-04-30 21:49:24 +0200136DEFUN(cfg_gbproxy,
137 cfg_gbproxy_cmd,
138 "gbproxy",
139 "Configure the Gb proxy")
140{
141 vty->node = GBPROXY_NODE;
142 return CMD_SUCCESS;
143}
144
Harald Welte799e0c92010-04-30 21:49:24 +0200145DEFUN(cfg_nsip_sgsn_nsei,
146 cfg_nsip_sgsn_nsei_cmd,
Harald Welteff3bde82010-05-19 15:09:09 +0200147 "sgsn nsei <0-65534>",
Holger Hans Peter Freyther2eb6e2c2011-11-05 15:14:59 +0100148 "SGSN information\n"
149 "NSEI to be used in the connection with the SGSN\n"
150 "The NSEI\n")
Harald Welte799e0c92010-04-30 21:49:24 +0200151{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200152 unsigned int nsei = atoi(argv[0]);
Harald Welte799e0c92010-04-30 21:49:24 +0200153
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200154 if (g_cfg->route_to_sgsn2 && g_cfg->nsip_sgsn2_nsei == nsei) {
155 vty_out(vty, "SGSN NSEI %d conflicts with secondary SGSN NSEI%s",
156 nsei, VTY_NEWLINE);
157 return CMD_WARNING;
158 }
159
160 g_cfg->nsip_sgsn_nsei = nsei;
Harald Welte799e0c92010-04-30 21:49:24 +0200161 return CMD_SUCCESS;
162}
163
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200164#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
165
166DEFUN(cfg_gbproxy_core_mnc,
167 cfg_gbproxy_core_mnc_cmd,
168 "core-mobile-network-code <1-999>",
169 GBPROXY_CORE_MNC_STR "NCC value\n")
170{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100171 uint16_t mnc;
172 bool mnc_3_digits;
173 if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
174 vty_out(vty, "%% Invalid MNC: %s%s", argv[0], VTY_NEWLINE);
175 return CMD_WARNING;
176 }
177 g_cfg->core_plmn.mnc = mnc;
178 g_cfg->core_plmn.mnc_3_digits = mnc_3_digits;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200179 return CMD_SUCCESS;
180}
181
182DEFUN(cfg_gbproxy_no_core_mnc,
183 cfg_gbproxy_no_core_mnc_cmd,
184 "no core-mobile-network-code",
185 NO_STR GBPROXY_CORE_MNC_STR)
186{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100187 g_cfg->core_plmn.mnc = 0;
188 g_cfg->core_plmn.mnc_3_digits = false;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200189 return CMD_SUCCESS;
190}
191
192#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
193
194DEFUN(cfg_gbproxy_core_mcc,
195 cfg_gbproxy_core_mcc_cmd,
196 "core-mobile-country-code <1-999>",
197 GBPROXY_CORE_MCC_STR "MCC value\n")
198{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100199 g_cfg->core_plmn.mcc = atoi(argv[0]);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200200 return CMD_SUCCESS;
201}
202
203DEFUN(cfg_gbproxy_no_core_mcc,
204 cfg_gbproxy_no_core_mcc_cmd,
205 "no core-mobile-country-code",
206 NO_STR GBPROXY_CORE_MCC_STR)
207{
Neels Hofmeyr10719b72018-02-21 00:39:36 +0100208 g_cfg->core_plmn.mcc = 0;
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200209 return CMD_SUCCESS;
210}
211
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200212#define GBPROXY_MATCH_IMSI_STR "Restrict actions to certain IMSIs\n"
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200213
214DEFUN(cfg_gbproxy_match_imsi,
215 cfg_gbproxy_match_imsi_cmd,
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200216 "match-imsi (patching|routing) .REGEXP",
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200217 GBPROXY_MATCH_IMSI_STR
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200218 "Patch MS related information elements on match only\n"
219 "Route to the secondary SGSN on match only\n"
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200220 "Regular expression for the IMSI match\n")
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200221{
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200222 const char *filter = argv[1];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200223 const char *err_msg = NULL;
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200224 struct gbproxy_match *match;
Jacob Erlbeckb36032c2014-09-25 13:21:48 +0200225 enum gbproxy_match_id match_id = get_string_value(match_ids, argv[0]);
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200226
227 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
228 match_id < GBPROX_MATCH_LAST);
229 match = &g_cfg->matches[match_id];
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200230
Jacob Erlbeck9a83d7a2014-09-25 11:17:31 +0200231 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200232 vty_out(vty, "Match expression invalid: %s%s",
233 err_msg, VTY_NEWLINE);
234 return CMD_WARNING;
235 }
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200236
237 g_cfg->acquire_imsi = 1;
238
239 return CMD_SUCCESS;
240}
241
242DEFUN(cfg_gbproxy_no_match_imsi,
243 cfg_gbproxy_no_match_imsi_cmd,
244 "no match-imsi",
245 NO_STR GBPROXY_MATCH_IMSI_STR)
246{
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200247 enum gbproxy_match_id match_id;
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200248
Jacob Erlbeck6c3fdc12014-09-25 13:39:06 +0200249 for (match_id = 0; match_id < ARRAY_SIZE(g_cfg->matches); ++match_id)
250 gbproxy_clear_patch_filter(&g_cfg->matches[match_id]);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200251
252 g_cfg->acquire_imsi = 0;
253
254 return CMD_SUCCESS;
255}
256
Jacob Erlbeck73685282014-05-23 20:48:07 +0200257#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200258#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200259
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200260static int set_core_apn(struct vty *vty, const char *apn)
Jacob Erlbeck73685282014-05-23 20:48:07 +0200261{
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200262 int apn_len;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200263
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200264 if (!apn) {
265 talloc_free(g_cfg->core_apn);
266 g_cfg->core_apn = NULL;
267 g_cfg->core_apn_size = 0;
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200268 return CMD_SUCCESS;
269 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200270
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200271 apn_len = strlen(apn);
272
273 if (apn_len >= 100) {
Jacob Erlbeck73685282014-05-23 20:48:07 +0200274 vty_out(vty, "APN string too long (max 99 chars)%s",
275 VTY_NEWLINE);
276 return CMD_WARNING;
277 }
278
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200279 if (apn_len == 0) {
280 talloc_free(g_cfg->core_apn);
281 /* TODO: replace NULL */
282 g_cfg->core_apn = talloc_zero_size(NULL, 2);
283 g_cfg->core_apn_size = 0;
284 } else {
285 /* TODO: replace NULL */
286 g_cfg->core_apn =
287 talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
288 g_cfg->core_apn_size =
Holger Hans Peter Freytherce1b22e2014-08-04 14:22:13 +0200289 gprs_str_to_apn(g_cfg->core_apn, apn_len + 1, apn);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200290 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200291
292 return CMD_SUCCESS;
293}
294
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200295DEFUN(cfg_gbproxy_core_apn,
296 cfg_gbproxy_core_apn_cmd,
297 "core-access-point-name (APN|none)",
298 GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
299{
300 if (strcmp(argv[0], "none") == 0)
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200301 return set_core_apn(vty, "");
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200302 else
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200303 return set_core_apn(vty, argv[0]);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200304}
305
Jacob Erlbeck73685282014-05-23 20:48:07 +0200306DEFUN(cfg_gbproxy_no_core_apn,
307 cfg_gbproxy_no_core_apn_cmd,
308 "no core-access-point-name",
309 NO_STR GBPROXY_CORE_APN_STR)
310{
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200311 return set_core_apn(vty, NULL);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200312}
313
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200314/* TODO: Remove the patch-ptmsi command, since P-TMSI patching is enabled
315 * automatically when needed. This command is only left for manual testing
316 * (e.g. doing P-TMSI patching without using a secondary SGSN)
317 */
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200318#define GBPROXY_PATCH_PTMSI_STR "Patch P-TMSI/TLLI\n"
319
320DEFUN(cfg_gbproxy_patch_ptmsi,
321 cfg_gbproxy_patch_ptmsi_cmd,
322 "patch-ptmsi",
323 GBPROXY_PATCH_PTMSI_STR)
324{
325 g_cfg->patch_ptmsi = 1;
326
327 return CMD_SUCCESS;
328}
329
330DEFUN(cfg_gbproxy_no_patch_ptmsi,
331 cfg_gbproxy_no_patch_ptmsi_cmd,
332 "no patch-ptmsi",
333 NO_STR GBPROXY_PATCH_PTMSI_STR)
334{
335 g_cfg->patch_ptmsi = 0;
336
337 return CMD_SUCCESS;
338}
339
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200340/* TODO: Remove the acquire-imsi command, since that feature is enabled
341 * automatically when IMSI matching is enabled. This command is only left for
342 * manual testing (e.g. doing IMSI acquisition without IMSI based patching)
343 */
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200344#define GBPROXY_ACQUIRE_IMSI_STR "Acquire the IMSI before establishing a LLC connection (Experimental)\n"
345
346DEFUN(cfg_gbproxy_acquire_imsi,
347 cfg_gbproxy_acquire_imsi_cmd,
348 "acquire-imsi",
349 GBPROXY_ACQUIRE_IMSI_STR)
350{
351 g_cfg->acquire_imsi = 1;
352
353 return CMD_SUCCESS;
354}
355
356DEFUN(cfg_gbproxy_no_acquire_imsi,
357 cfg_gbproxy_no_acquire_imsi_cmd,
358 "no acquire-imsi",
359 NO_STR GBPROXY_ACQUIRE_IMSI_STR)
360{
361 g_cfg->acquire_imsi = 0;
362
363 return CMD_SUCCESS;
364}
365
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200366#define GBPROXY_SECOND_SGSN_STR "Route matching LLC connections to a second SGSN (Experimental)\n"
367
368DEFUN(cfg_gbproxy_secondary_sgsn,
369 cfg_gbproxy_secondary_sgsn_cmd,
370 "secondary-sgsn nsei <0-65534>",
371 GBPROXY_SECOND_SGSN_STR
372 "NSEI to be used in the connection with the SGSN\n"
373 "The NSEI\n")
374{
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200375 unsigned int nsei = atoi(argv[0]);
376
377 if (g_cfg->nsip_sgsn_nsei == nsei) {
378 vty_out(vty, "Secondary SGSN NSEI %d conflicts with primary SGSN NSEI%s",
379 nsei, VTY_NEWLINE);
380 return CMD_WARNING;
381 }
382
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200383 g_cfg->route_to_sgsn2 = 1;
Jacob Erlbeckcc8856f2014-10-08 13:37:28 +0200384 g_cfg->nsip_sgsn2_nsei = nsei;
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200385
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200386 g_cfg->patch_ptmsi = 1;
387
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200388 return CMD_SUCCESS;
389}
390
391DEFUN(cfg_gbproxy_no_secondary_sgsn,
392 cfg_gbproxy_no_secondary_sgsn_cmd,
393 "no secondary-sgsn",
394 NO_STR GBPROXY_SECOND_SGSN_STR)
395{
396 g_cfg->route_to_sgsn2 = 0;
397 g_cfg->nsip_sgsn2_nsei = 0xFFFF;
398
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200399 g_cfg->patch_ptmsi = 0;
400
Jacob Erlbeckf4d60c82014-08-26 14:47:15 +0200401 return CMD_SUCCESS;
402}
403
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200404#define GBPROXY_LINK_LIST_STR "Set TLLI list parameters\n"
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200405#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
406
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200407DEFUN(cfg_gbproxy_link_list_max_age,
408 cfg_gbproxy_link_list_max_age_cmd,
409 "link-list max-age <1-999999>",
410 GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200411 "Maximum age in seconds\n")
412{
413 g_cfg->tlli_max_age = atoi(argv[0]);
414
Jacob Erlbeck73685282014-05-23 20:48:07 +0200415 return CMD_SUCCESS;
416}
417
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200418DEFUN(cfg_gbproxy_link_list_no_max_age,
419 cfg_gbproxy_link_list_no_max_age_cmd,
420 "no link-list max-age",
421 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_AGE_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200422{
423 g_cfg->tlli_max_age = 0;
424
425 return CMD_SUCCESS;
426}
427
428#define GBPROXY_MAX_LEN_STR "Limit list length\n"
429
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200430DEFUN(cfg_gbproxy_link_list_max_len,
431 cfg_gbproxy_link_list_max_len_cmd,
432 "link-list max-length <1-99999>",
433 GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR
434 "Maximum number of logical links in the list\n")
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200435{
436 g_cfg->tlli_max_len = atoi(argv[0]);
437
438 return CMD_SUCCESS;
439}
440
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200441DEFUN(cfg_gbproxy_link_list_no_max_len,
442 cfg_gbproxy_link_list_no_max_len_cmd,
443 "no link-list max-length",
444 NO_STR GBPROXY_LINK_LIST_STR GBPROXY_MAX_LEN_STR)
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200445{
446 g_cfg->tlli_max_len = 0;
447
448 return CMD_SUCCESS;
449}
450
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200451DEFUN(cfg_gbproxy_link_list_keep_mode,
452 cfg_gbproxy_link_list_keep_mode_cmd,
453 "link-list keep-mode (never|re-attach|identified|always)",
454 GBPROXY_LINK_LIST_STR "How to keep entries for detached logical links\n"
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200455 "Discard entry immediately after detachment\n"
456 "Keep entry if a re-attachment has be requested\n"
457 "Keep entry if it associated with an IMSI\n"
458 "Don't discard entries after detachment\n")
459{
460 int val = get_string_value(keep_modes, argv[0]);
461 OSMO_ASSERT(val >= GBPROX_KEEP_NEVER && val <= GBPROX_KEEP_ALWAYS);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200462 g_cfg->keep_link_infos = val;
Jacob Erlbeck7430da62014-09-12 15:09:56 +0200463
464 return CMD_SUCCESS;
465}
466
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200467
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200468DEFUN(show_gbproxy, show_gbproxy_cmd, "show gbproxy [stats]",
469 SHOW_STR "Display information about the Gb proxy\n" "Show statistics\n")
470{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200471 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200472 int show_stats = argc >= 1;
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200473
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200474 if (show_stats)
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200475 vty_out_rate_ctr_group(vty, "", g_cfg->ctrg);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200476
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200477 llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200478 gbprox_vty_print_peer(vty, peer);
479
480 if (show_stats)
481 vty_out_rate_ctr_group(vty, " ", peer->ctrg);
482 }
483 return CMD_SUCCESS;
484}
485
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200486DEFUN(show_gbproxy_links, show_gbproxy_links_cmd, "show gbproxy links",
487 SHOW_STR "Display information about the Gb proxy\n" "Show logical links\n")
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200488{
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200489 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200490 char mi_buf[200];
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200491 time_t now;
492 struct timespec ts = {0,};
493
494 clock_gettime(CLOCK_MONOTONIC, &ts);
495 now = ts.tv_sec;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200496
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200497 llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200498 struct gbproxy_link_info *link_info;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200499 struct gbproxy_patch_state *state = &peer->patch_state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200500
501 gbprox_vty_print_peer(vty, peer);
502
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200503 llist_for_each_entry(link_info, &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200504 time_t age = now - link_info->timestamp;
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200505 int stored_msgs = 0;
506 struct llist_head *iter;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200507 llist_for_each(iter, &link_info->stored_msgs)
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200508 stored_msgs++;
509
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200510 if (link_info->imsi > 0) {
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200511 snprintf(mi_buf, sizeof(mi_buf), "(invalid)");
512 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200513 link_info->imsi,
514 link_info->imsi_len);
Jacob Erlbeck89d3d342014-08-06 18:55:15 +0200515 } else {
516 snprintf(mi_buf, sizeof(mi_buf), "(none)");
517 }
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200518 vty_out(vty, " TLLI %08x, IMSI %s, AGE %d",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200519 link_info->tlli.current, mi_buf, (int)age);
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200520
521 if (stored_msgs)
522 vty_out(vty, ", STORED %d", stored_msgs);
523
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200524 if (g_cfg->route_to_sgsn2)
525 vty_out(vty, ", SGSN NSEI %d",
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200526 link_info->sgsn_nsei);
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200527
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200528 if (link_info->is_deregistered)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200529 vty_out(vty, ", DE-REGISTERED");
530
Jacob Erlbeck146e3072014-09-02 14:09:01 +0200531 vty_out(vty, "%s", VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200532 }
533 }
534 return CMD_SUCCESS;
535}
536
537DEFUN(delete_gb_bvci, delete_gb_bvci_cmd,
538 "delete-gbproxy-peer <0-65534> bvci <2-65534>",
539 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
540 "NSEI number\n"
541 "Only delete peer with a matching BVCI\n"
542 "BVCI number\n")
543{
544 const uint16_t nsei = atoi(argv[0]);
545 const uint16_t bvci = atoi(argv[1]);
546 int counter;
547
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200548 counter = gbproxy_cleanup_peers(g_cfg, nsei, bvci);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200549
550 if (counter == 0) {
551 vty_out(vty, "BVC not found%s", VTY_NEWLINE);
552 return CMD_WARNING;
553 }
554
555 return CMD_SUCCESS;
556}
557
558DEFUN(delete_gb_nsei, delete_gb_nsei_cmd,
559 "delete-gbproxy-peer <0-65534> (only-bvc|only-nsvc|all) [dry-run]",
560 "Delete a GBProxy peer by NSEI and optionally BVCI\n"
561 "NSEI number\n"
562 "Only delete BSSGP connections (BVC)\n"
563 "Only delete dynamic NS connections (NS-VC)\n"
564 "Delete BVC and dynamic NS connections\n"
565 "Show what would be deleted instead of actually deleting\n"
566 )
567{
568 const uint16_t nsei = atoi(argv[0]);
569 const char *mode = argv[1];
570 int dry_run = argc > 2;
571 int delete_bvc = 0;
572 int delete_nsvc = 0;
573 int counter;
574
575 if (strcmp(mode, "only-bvc") == 0)
576 delete_bvc = 1;
577 else if (strcmp(mode, "only-nsvc") == 0)
578 delete_nsvc = 1;
579 else
580 delete_bvc = delete_nsvc = 1;
581
582 if (delete_bvc) {
583 if (!dry_run)
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200584 counter = gbproxy_cleanup_peers(g_cfg, nsei, 0);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200585 else {
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200586 struct gbproxy_peer *peer;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200587 counter = 0;
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200588 llist_for_each_entry(peer, &g_cfg->bts_peers, list) {
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200589 if (peer->nsei != nsei)
590 continue;
591
592 vty_out(vty, "BVC: ");
593 gbprox_vty_print_peer(vty, peer);
594 counter += 1;
595 }
596 }
597 vty_out(vty, "%sDeleted %d BVC%s",
598 dry_run ? "Not " : "", counter, VTY_NEWLINE);
599 }
600
601 if (delete_nsvc) {
Holger Hans Peter Freythereece6272014-08-04 15:42:36 +0200602 struct gprs_ns_inst *nsi = g_cfg->nsi;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200603 struct gprs_nsvc *nsvc, *nsvc2;
604
605 counter = 0;
606 llist_for_each_entry_safe(nsvc, nsvc2, &nsi->gprs_nsvcs, list) {
607 if (nsvc->nsei != nsei)
608 continue;
609 if (nsvc->persistent)
610 continue;
611
612 if (!dry_run)
613 gprs_nsvc_delete(nsvc);
614 else
615 vty_out(vty, "NS-VC: NSEI %5u, NS-VCI %5u, "
616 "remote %s%s",
617 nsvc->nsei, nsvc->nsvci,
618 gprs_ns_ll_str(nsvc), VTY_NEWLINE);
619 counter += 1;
620 }
621 vty_out(vty, "%sDeleted %d NS-VC%s",
622 dry_run ? "Not " : "", counter, VTY_NEWLINE);
623 }
624
625 return CMD_SUCCESS;
626}
627
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200628#define GBPROXY_DELETE_LINK_STR \
629 "Delete a GBProxy logical link entry by NSEI and identification\nNSEI number\n"
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200630
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200631DEFUN(delete_gb_link_by_id, delete_gb_link_by_id_cmd,
632 "delete-gbproxy-link <0-65534> (tlli|imsi|sgsn-nsei) IDENT",
633 GBPROXY_DELETE_LINK_STR
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200634 "Delete entries with a matching TLLI (hex)\n"
635 "Delete entries with a matching IMSI\n"
Jacob Erlbeckde74e722014-10-28 11:29:43 +0100636 "Delete entries with a matching SGSN NSEI\n"
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200637 "Identification to match\n")
638{
639 const uint16_t nsei = atoi(argv[0]);
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200640 enum {MATCH_TLLI = 't', MATCH_IMSI = 'i', MATCH_SGSN = 's'} match;
641 uint32_t ident = 0;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200642 const char *imsi = NULL;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200643 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200644 struct gbproxy_link_info *link_info, *nxt;
Holger Hans Peter Freyther1ddd9e52014-08-04 11:35:32 +0200645 struct gbproxy_patch_state *state;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200646 char mi_buf[200];
647 int found = 0;
648
649 match = argv[1][0];
650
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200651 switch (match) {
652 case MATCH_TLLI: ident = strtoll(argv[2], NULL, 16); break;
653 case MATCH_IMSI: imsi = argv[2]; break;
654 case MATCH_SGSN: ident = strtoll(argv[2], NULL, 0); break;
655 };
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200656
657 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
658 if (!peer) {
659 vty_out(vty, "Didn't find peer with NSEI %d%s",
660 nsei, VTY_NEWLINE);
661 return CMD_WARNING;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200662 }
663
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200664 state = &peer->patch_state;
665
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200666 llist_for_each_entry_safe(link_info, nxt, &state->logical_links, list) {
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200667 switch (match) {
668 case MATCH_TLLI:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200669 if (link_info->tlli.current != ident)
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200670 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200671 break;
672 case MATCH_SGSN:
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200673 if (link_info->sgsn_nsei != ident)
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200674 continue;
675 break;
676 case MATCH_IMSI:
Jacob Erlbeck6a1d4282014-10-20 17:22:36 +0200677 if (!link_info->imsi)
678 continue;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200679 mi_buf[0] = '\0';
680 gsm48_mi_to_string(mi_buf, sizeof(mi_buf),
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200681 link_info->imsi,
682 link_info->imsi_len);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200683
684 if (strcmp(mi_buf, imsi) != 0)
685 continue;
Jacob Erlbeck91a0e862014-09-17 10:56:38 +0200686 break;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200687 }
688
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200689 vty_out(vty, "Deleting link with TLLI %08x%s", link_info->tlli.current,
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200690 VTY_NEWLINE);
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200691 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200692 found += 1;
693 }
694
695 if (!found && argc >= 2) {
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200696 vty_out(vty, "Didn't find link entry with %s %s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200697 argv[1], argv[2], VTY_NEWLINE);
698 }
699
700 return CMD_SUCCESS;
701}
702
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200703DEFUN(delete_gb_link, delete_gb_link_cmd,
704 "delete-gbproxy-link <0-65534> (stale|de-registered)",
705 GBPROXY_DELETE_LINK_STR
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200706 "Delete stale entries\n"
707 "Delete de-registered entries\n")
708{
709 const uint16_t nsei = atoi(argv[0]);
710 enum {MATCH_STALE = 's', MATCH_DEREGISTERED = 'd'} match;
711 struct gbproxy_peer *peer = 0;
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200712 struct gbproxy_link_info *link_info, *nxt;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200713 struct gbproxy_patch_state *state;
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200714 time_t now;
715 struct timespec ts = {0,};
716
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200717 int found = 0;
718
719 match = argv[1][0];
720
Jacob Erlbeck5f1faa32014-08-21 10:01:30 +0200721 peer = gbproxy_peer_by_nsei(g_cfg, nsei);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200722 if (!peer) {
723 vty_out(vty, "Didn't find peer with NSEI %d%s",
724 nsei, VTY_NEWLINE);
725 return CMD_WARNING;
726 }
727
728 state = &peer->patch_state;
729
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200730 clock_gettime(CLOCK_MONOTONIC, &ts);
731 now = ts.tv_sec;
732
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200733 if (match == MATCH_STALE) {
Jacob Erlbeckc6807c42014-09-19 16:34:01 +0200734 found = gbproxy_remove_stale_link_infos(peer, now);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200735 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200736 vty_out(vty, "Deleted %d stale logical link%s%s",
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200737 found, found == 1 ? "" : "s", VTY_NEWLINE);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200738 } else {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200739 llist_for_each_entry_safe(link_info, nxt,
Jacob Erlbeckf8562e32014-09-19 16:03:07 +0200740 &state->logical_links, list) {
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200741 if (!link_info->is_deregistered)
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200742 continue;
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200743
Jacob Erlbeck91d2f8a2014-09-19 15:07:27 +0200744 gbproxy_delete_link_info(peer, link_info);
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200745 found += 1;
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200746 }
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200747 }
748
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200749 if (found)
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200750 vty_out(vty, "Deleted %d %s logical link%s%s",
Jacob Erlbeckcdd37832014-09-16 08:56:26 +0200751 found, argv[1], found == 1 ? "" : "s", VTY_NEWLINE);
Holger Hans Peter Freyther18739ea2014-08-04 11:10:09 +0200752
753 return CMD_SUCCESS;
754}
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200755
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200756/*
757 * legacy commands to provide an upgrade path from "broken" releases
758 * or pre-releases
759 */
760DEFUN_DEPRECATED(cfg_gbproxy_broken_apn_match,
761 cfg_gbproxy_broken_apn_match_cmd,
762 "core-access-point-name none match-imsi .REGEXP",
763 GBPROXY_CORE_APN_STR GBPROXY_MATCH_IMSI_STR "Remove APN\n"
764 "Patch MS related information elements on match only\n"
765 "Route to the secondary SGSN on match only\n"
766 "Regular expression for the IMSI match\n")
767{
768 const char *filter = argv[0];
769 const char *err_msg = NULL;
770 struct gbproxy_match *match;
771 enum gbproxy_match_id match_id = get_string_value(match_ids, "patching");
772
773 /* apply APN none */
774 set_core_apn(vty, "");
775
776 /* do the matching... with copy and paste */
777 OSMO_ASSERT(match_id >= GBPROX_MATCH_PATCHING &&
778 match_id < GBPROX_MATCH_LAST);
779 match = &g_cfg->matches[match_id];
780
781 if (gbproxy_set_patch_filter(match, filter, &err_msg) != 0) {
782 vty_out(vty, "Match expression invalid: %s%s",
783 err_msg, VTY_NEWLINE);
784 return CMD_WARNING;
785 }
786
787 g_cfg->acquire_imsi = 1;
788
789 return CMD_SUCCESS;
790}
791
792#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
793#define GBPROXY_MAX_LEN_STR "Limit list length\n"
794DEFUN_DEPRECATED(cfg_gbproxy_depr_tlli_list_max_len,
795 cfg_gbproxy_depr_tlli_list_max_len_cmd,
796 "tlli-list max-length <1-99999>",
797 GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
798 "Maximum number of TLLIs in the list\n")
799{
800 g_cfg->tlli_max_len = atoi(argv[0]);
801
802 return CMD_SUCCESS;
803}
804
Harald Welte799e0c92010-04-30 21:49:24 +0200805int gbproxy_vty_init(void)
806{
Harald Welte995a2d32010-05-12 16:50:52 +0000807 install_element_ve(&show_gbproxy_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200808 install_element_ve(&show_gbproxy_links_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200809
Jacob Erlbeck4211d792013-10-24 12:48:23 +0200810 install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
811 install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200812 install_element(ENABLE_NODE, &delete_gb_link_by_id_cmd);
813 install_element(ENABLE_NODE, &delete_gb_link_cmd);
Holger Hans Peter Freyther90267a92013-10-23 11:24:17 +0200814
Harald Welte799e0c92010-04-30 21:49:24 +0200815 install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
816 install_node(&gbproxy_node, config_write_gbproxy);
Harald Welte799e0c92010-04-30 21:49:24 +0200817 install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200818 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
819 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200820 install_element(GBPROXY_NODE, &cfg_gbproxy_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200821 install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200822 install_element(GBPROXY_NODE, &cfg_gbproxy_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200823 install_element(GBPROXY_NODE, &cfg_gbproxy_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200824 install_element(GBPROXY_NODE, &cfg_gbproxy_acquire_imsi_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200825 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_age_cmd);
826 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_max_len_cmd);
827 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_keep_mode_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200828 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
829 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200830 install_element(GBPROXY_NODE, &cfg_gbproxy_no_match_imsi_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200831 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
Jacob Erlbeckcd9e1c92014-09-02 13:57:19 +0200832 install_element(GBPROXY_NODE, &cfg_gbproxy_no_secondary_sgsn_cmd);
Jacob Erlbeck0d4236b2014-08-18 14:54:37 +0200833 install_element(GBPROXY_NODE, &cfg_gbproxy_no_patch_ptmsi_cmd);
Jacob Erlbeck5f4ef322014-08-22 17:10:01 +0200834 install_element(GBPROXY_NODE, &cfg_gbproxy_no_acquire_imsi_cmd);
Jacob Erlbeckd4c79a42014-09-19 15:36:44 +0200835 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_age_cmd);
836 install_element(GBPROXY_NODE, &cfg_gbproxy_link_list_no_max_len_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200837
Holger Hans Peter Freyther925504b2015-09-24 10:21:40 +0200838 /* broken or deprecated to allow an upgrade path */
839 install_element(GBPROXY_NODE, &cfg_gbproxy_broken_apn_match_cmd);
840 install_element(GBPROXY_NODE, &cfg_gbproxy_depr_tlli_list_max_len_cmd);
841
Harald Welte799e0c92010-04-30 21:49:24 +0200842 return 0;
843}
844
845int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
846{
847 int rc;
848
849 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200850 rc = vty_read_config_file(config_file, NULL);
Harald Welte799e0c92010-04-30 21:49:24 +0200851 if (rc < 0) {
852 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
853 return rc;
854 }
855
856 return 0;
857}