blob: e7506fc3e9629218d9691451c3b70e8a48709509 [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>
Harald Welte799e0c92010-04-30 21:49:24 +020025
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010026#include <osmocom/core/talloc.h>
Harald Welte799e0c92010-04-30 21:49:24 +020027
Harald Welteea34a4e2012-06-16 14:59:56 +080028#include <osmocom/gprs/gprs_ns.h>
29
Harald Welte799e0c92010-04-30 21:49:24 +020030#include <openbsc/debug.h>
Harald Welteb77c6972010-05-01 11:28:43 +020031#include <openbsc/gb_proxy.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020032#include <openbsc/vty.h>
Harald Welte799e0c92010-04-30 21:49:24 +020033
Harald Welte4b037e42010-05-19 19:45:32 +020034#include <osmocom/vty/command.h>
35#include <osmocom/vty/vty.h>
Harald Welte799e0c92010-04-30 21:49:24 +020036
Harald Welte799e0c92010-04-30 21:49:24 +020037static struct gbproxy_config *g_cfg = NULL;
38
39/*
40 * vty code for mgcp below
41 */
Harald Welteb77c6972010-05-01 11:28:43 +020042static struct cmd_node gbproxy_node = {
Harald Welte799e0c92010-04-30 21:49:24 +020043 GBPROXY_NODE,
Harald Welte570ce242012-08-17 13:16:10 +020044 "%s(config-gbproxy)# ",
Harald Welte799e0c92010-04-30 21:49:24 +020045 1,
46};
47
Jacob Erlbeck91fb6802014-05-28 10:59:10 +020048static const struct value_string patch_modes[] = {
49 {GBPROX_PATCH_DEFAULT, "default"},
50 {GBPROX_PATCH_BSSGP, "bssgp"},
51 {GBPROX_PATCH_LLC_ATTACH_REQ, "llc-attach-req"},
52 {GBPROX_PATCH_LLC_ATTACH, "llc-attach"},
53 {GBPROX_PATCH_LLC_GMM, "llc-gmm"},
Jacob Erlbeck73685282014-05-23 20:48:07 +020054 {GBPROX_PATCH_LLC_GSM, "llc-gsm"},
Jacob Erlbeck91fb6802014-05-28 10:59:10 +020055 {GBPROX_PATCH_LLC, "llc"},
56 {0, NULL}
57};
58
Harald Welte799e0c92010-04-30 21:49:24 +020059static int config_write_gbproxy(struct vty *vty)
60{
Harald Welte799e0c92010-04-30 21:49:24 +020061 vty_out(vty, "gbproxy%s", VTY_NEWLINE);
62
Harald Welteff3bde82010-05-19 15:09:09 +020063 vty_out(vty, " sgsn nsei %u%s", g_cfg->nsip_sgsn_nsei,
Harald Welte799e0c92010-04-30 21:49:24 +020064 VTY_NEWLINE);
Harald Welte799e0c92010-04-30 21:49:24 +020065
Jacob Erlbeck67a44452014-05-19 10:14:58 +020066 if (g_cfg->core_mcc > 0)
67 vty_out(vty, " core-mobile-country-code %d%s",
68 g_cfg->core_mcc, VTY_NEWLINE);
69 if (g_cfg->core_mnc > 0)
70 vty_out(vty, " core-mobile-network-code %d%s",
71 g_cfg->core_mnc, VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +020072 if (g_cfg->core_apn != NULL) {
73 if (g_cfg->core_apn_size > 0) {
74 char str[500] = {0};
Jacob Erlbeck7c101d92014-06-06 18:49:23 +020075 vty_out(vty, " core-access-point-name %s",
Jacob Erlbeck73685282014-05-23 20:48:07 +020076 gbprox_apn_to_str(str, g_cfg->core_apn,
Jacob Erlbeck7c101d92014-06-06 18:49:23 +020077 g_cfg->core_apn_size));
Jacob Erlbeck73685282014-05-23 20:48:07 +020078 } else {
Jacob Erlbeck7c101d92014-06-06 18:49:23 +020079 vty_out(vty, " core-access-point-name none");
Jacob Erlbeck73685282014-05-23 20:48:07 +020080 }
Jacob Erlbeck7c101d92014-06-06 18:49:23 +020081 if (g_cfg->match_re)
82 vty_out(vty, " match-imsi %s%s",
83 g_cfg->match_re, VTY_NEWLINE);
84 else
85 vty_out(vty, "%s", VTY_NEWLINE);
Jacob Erlbeck73685282014-05-23 20:48:07 +020086 }
Jacob Erlbeck7c101d92014-06-06 18:49:23 +020087 if (g_cfg->tlli_max_age > 0)
88 vty_out(vty, " tlli-list max-age %d%s",
89 g_cfg->tlli_max_age, VTY_NEWLINE);
90 if (g_cfg->tlli_max_len > 0)
91 vty_out(vty, " tlli-list max-length %d%s",
92 g_cfg->tlli_max_len, VTY_NEWLINE);
Jacob Erlbeck67a44452014-05-19 10:14:58 +020093
Jacob Erlbeck91fb6802014-05-28 10:59:10 +020094 if (g_cfg->patch_mode != GBPROX_PATCH_DEFAULT)
95 vty_out(vty, " patch-mode %s%s",
96 get_value_string(patch_modes, g_cfg->patch_mode),
97 VTY_NEWLINE);
98
Harald Welte799e0c92010-04-30 21:49:24 +020099 return CMD_SUCCESS;
100}
101
Harald Welte799e0c92010-04-30 21:49:24 +0200102DEFUN(cfg_gbproxy,
103 cfg_gbproxy_cmd,
104 "gbproxy",
105 "Configure the Gb proxy")
106{
107 vty->node = GBPROXY_NODE;
108 return CMD_SUCCESS;
109}
110
Harald Welte799e0c92010-04-30 21:49:24 +0200111DEFUN(cfg_nsip_sgsn_nsei,
112 cfg_nsip_sgsn_nsei_cmd,
Harald Welteff3bde82010-05-19 15:09:09 +0200113 "sgsn nsei <0-65534>",
Holger Hans Peter Freyther2eb6e2c2011-11-05 15:14:59 +0100114 "SGSN information\n"
115 "NSEI to be used in the connection with the SGSN\n"
116 "The NSEI\n")
Harald Welte799e0c92010-04-30 21:49:24 +0200117{
118 unsigned int port = atoi(argv[0]);
119
120 g_cfg->nsip_sgsn_nsei = port;
121 return CMD_SUCCESS;
122}
123
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200124#define GBPROXY_CORE_MNC_STR "Use this network code for the core network\n"
125
126DEFUN(cfg_gbproxy_core_mnc,
127 cfg_gbproxy_core_mnc_cmd,
128 "core-mobile-network-code <1-999>",
129 GBPROXY_CORE_MNC_STR "NCC value\n")
130{
131 g_cfg->core_mnc = atoi(argv[0]);
132 return CMD_SUCCESS;
133}
134
135DEFUN(cfg_gbproxy_no_core_mnc,
136 cfg_gbproxy_no_core_mnc_cmd,
137 "no core-mobile-network-code",
138 NO_STR GBPROXY_CORE_MNC_STR)
139{
140 g_cfg->core_mnc = 0;
141 return CMD_SUCCESS;
142}
143
144#define GBPROXY_CORE_MCC_STR "Use this country code for the core network\n"
145
146DEFUN(cfg_gbproxy_core_mcc,
147 cfg_gbproxy_core_mcc_cmd,
148 "core-mobile-country-code <1-999>",
149 GBPROXY_CORE_MCC_STR "MCC value\n")
150{
151 g_cfg->core_mcc = atoi(argv[0]);
152 return CMD_SUCCESS;
153}
154
155DEFUN(cfg_gbproxy_no_core_mcc,
156 cfg_gbproxy_no_core_mcc_cmd,
157 "no core-mobile-country-code",
158 NO_STR GBPROXY_CORE_MCC_STR)
159{
160 g_cfg->core_mcc = 0;
161 return CMD_SUCCESS;
162}
163
Jacob Erlbeck73685282014-05-23 20:48:07 +0200164#define GBPROXY_CORE_APN_STR "Use this access point name (APN) for the backbone\n"
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200165#define GBPROXY_CORE_APN_ARG_STR "Replace APN by this string\n" "Remove APN\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200166
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200167static int set_core_apn(struct vty *vty, const char *apn, const char *filter)
Jacob Erlbeck73685282014-05-23 20:48:07 +0200168{
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200169 const char *err_msg = NULL;
170 int apn_len;
Jacob Erlbeck73685282014-05-23 20:48:07 +0200171
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200172 if (!apn) {
173 talloc_free(g_cfg->core_apn);
174 g_cfg->core_apn = NULL;
175 g_cfg->core_apn_size = 0;
176 gbprox_set_patch_filter(NULL, NULL);
177 return CMD_SUCCESS;
178 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200179
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200180 apn_len = strlen(apn);
181
182 if (apn_len >= 100) {
Jacob Erlbeck73685282014-05-23 20:48:07 +0200183 vty_out(vty, "APN string too long (max 99 chars)%s",
184 VTY_NEWLINE);
185 return CMD_WARNING;
186 }
187
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200188 if (!filter) {
189 gbprox_set_patch_filter(NULL, NULL);
190 } else if (gbprox_set_patch_filter(filter, &err_msg) != 0) {
191 vty_out(vty, "Match expression invalid: %s%s",
192 err_msg, VTY_NEWLINE);
193 return CMD_WARNING;
194 }
195
196 talloc_free(g_cfg->match_re);
197 if (filter)
198 /* TODO: replace NULL */
199 g_cfg->match_re = talloc_strdup(NULL, filter);
200 else
201 g_cfg->match_re = NULL;
202
203 if (apn_len == 0) {
204 talloc_free(g_cfg->core_apn);
205 /* TODO: replace NULL */
206 g_cfg->core_apn = talloc_zero_size(NULL, 2);
207 g_cfg->core_apn_size = 0;
208 } else {
209 /* TODO: replace NULL */
210 g_cfg->core_apn =
211 talloc_realloc_size(NULL, g_cfg->core_apn, apn_len + 1);
212 g_cfg->core_apn_size =
213 gbprox_str_to_apn(g_cfg->core_apn, apn, apn_len + 1);
214 }
Jacob Erlbeck73685282014-05-23 20:48:07 +0200215
216 return CMD_SUCCESS;
217}
218
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200219DEFUN(cfg_gbproxy_core_apn,
220 cfg_gbproxy_core_apn_cmd,
221 "core-access-point-name (APN|none)",
222 GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR)
223{
224 if (strcmp(argv[0], "none") == 0)
225 return set_core_apn(vty, "", NULL);
226 else
227 return set_core_apn(vty, argv[0], NULL);
228}
229
230DEFUN(cfg_gbproxy_core_apn_match,
231 cfg_gbproxy_core_apn_match_cmd,
232 "core-access-point-name (APN|none) match-imsi .REGEXP",
233 GBPROXY_CORE_APN_STR GBPROXY_CORE_APN_ARG_STR
234 "Only modify if the IMSI matches\n"
235 "Regular expression for the match\n")
236{
237 if (strcmp(argv[0], "none") == 0)
238 return set_core_apn(vty, "", argv[1]);
239 else
240 return set_core_apn(vty, argv[0], argv[1]);
241}
242
Jacob Erlbeck73685282014-05-23 20:48:07 +0200243DEFUN(cfg_gbproxy_no_core_apn,
244 cfg_gbproxy_no_core_apn_cmd,
245 "no core-access-point-name",
246 NO_STR GBPROXY_CORE_APN_STR)
247{
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200248 return set_core_apn(vty, NULL, NULL);
249}
250
251#define GBPROXY_TLLI_LIST_STR "Set TLLI list parameters\n"
252#define GBPROXY_MAX_AGE_STR "Limit maximum age\n"
253
254DEFUN(cfg_gbproxy_tlli_list_max_age,
255 cfg_gbproxy_tlli_list_max_age_cmd,
256 "tlli-list max-age <1-999999>",
257 GBPROXY_TLLI_LIST_STR GBPROXY_MAX_AGE_STR
258 "Maximum age in seconds\n")
259{
260 g_cfg->tlli_max_age = atoi(argv[0]);
261
Jacob Erlbeck73685282014-05-23 20:48:07 +0200262 return CMD_SUCCESS;
263}
264
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200265DEFUN(cfg_gbproxy_tlli_list_no_max_age,
266 cfg_gbproxy_tlli_list_no_max_age_cmd,
267 "no tlli-list max-age",
268 NO_STR GBPROXY_TLLI_LIST_STR GBPROXY_MAX_AGE_STR)
269{
270 g_cfg->tlli_max_age = 0;
271
272 return CMD_SUCCESS;
273}
274
275#define GBPROXY_MAX_LEN_STR "Limit list length\n"
276
277DEFUN(cfg_gbproxy_tlli_list_max_len,
278 cfg_gbproxy_tlli_list_max_len_cmd,
279 "tlli-list max-length <1-99999>",
280 GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR
281 "Maximum number of TLLIs in the list\n")
282{
283 g_cfg->tlli_max_len = atoi(argv[0]);
284
285 return CMD_SUCCESS;
286}
287
288DEFUN(cfg_gbproxy_tlli_list_no_max_len,
289 cfg_gbproxy_tlli_list_no_max_len_cmd,
290 "no tlli-list max-length",
291 NO_STR GBPROXY_TLLI_LIST_STR GBPROXY_MAX_LEN_STR)
292{
293 g_cfg->tlli_max_len = 0;
294
295 return CMD_SUCCESS;
296}
297
298
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200299DEFUN(cfg_gbproxy_patch_mode,
300 cfg_gbproxy_patch_mode_cmd,
Jacob Erlbeck73685282014-05-23 20:48:07 +0200301 "patch-mode (default|bssgp|llc-attach-req|llc-attach|llc-gmm|llc-gsm|llc)",
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200302 "Set patch mode\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200303 "Use build-in default (best effort, try to patch everything)\n"
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200304 "Only patch BSSGP headers\n"
305 "Patch BSSGP headers and LLC Attach Request messages\n"
306 "Patch BSSGP headers and LLC Attach Request/Accept messages\n"
Jacob Erlbeck73685282014-05-23 20:48:07 +0200307 "Patch BSSGP headers and LLC GMM messages\n"
308 "Patch BSSGP headers, LLC GMM, and LLC GSM messages\n"
309 "Patch BSSGP headers and all supported LLC messages\n"
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200310 )
311{
312 int val = get_string_value(patch_modes, argv[0]);
313 OSMO_ASSERT(val >= 0);
314 g_cfg->patch_mode = val;
315 return CMD_SUCCESS;
316}
317
318
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200319
Harald Welte799e0c92010-04-30 21:49:24 +0200320int gbproxy_vty_init(void)
321{
Harald Welte995a2d32010-05-12 16:50:52 +0000322 install_element_ve(&show_gbproxy_cmd);
Jacob Erlbeck7dd498d2014-06-19 10:15:27 +0200323 install_element_ve(&show_gbproxy_tllis_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200324
Jacob Erlbeck4211d792013-10-24 12:48:23 +0200325 install_element(ENABLE_NODE, &delete_gb_bvci_cmd);
326 install_element(ENABLE_NODE, &delete_gb_nsei_cmd);
Jacob Erlbeck7dd498d2014-06-19 10:15:27 +0200327 install_element(ENABLE_NODE, &delete_gb_tlli_cmd);
Holger Hans Peter Freyther90267a92013-10-23 11:24:17 +0200328
Harald Welte799e0c92010-04-30 21:49:24 +0200329 install_element(CONFIG_NODE, &cfg_gbproxy_cmd);
330 install_node(&gbproxy_node, config_write_gbproxy);
Jacob Erlbeck36722e12013-10-29 09:30:30 +0100331 vty_install_default(GBPROXY_NODE);
Harald Welte799e0c92010-04-30 21:49:24 +0200332 install_element(GBPROXY_NODE, &cfg_nsip_sgsn_nsei_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200333 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mcc_cmd);
334 install_element(GBPROXY_NODE, &cfg_gbproxy_core_mnc_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200335 install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_cmd);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200336 install_element(GBPROXY_NODE, &cfg_gbproxy_core_apn_match_cmd);
337 install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_max_age_cmd);
338 install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_max_len_cmd);
Jacob Erlbeck67a44452014-05-19 10:14:58 +0200339 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mcc_cmd);
340 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_mnc_cmd);
Jacob Erlbeck73685282014-05-23 20:48:07 +0200341 install_element(GBPROXY_NODE, &cfg_gbproxy_no_core_apn_cmd);
Jacob Erlbeck7c101d92014-06-06 18:49:23 +0200342 install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_no_max_age_cmd);
343 install_element(GBPROXY_NODE, &cfg_gbproxy_tlli_list_no_max_len_cmd);
Jacob Erlbeck91fb6802014-05-28 10:59:10 +0200344 install_element(GBPROXY_NODE, &cfg_gbproxy_patch_mode_cmd);
Harald Welte799e0c92010-04-30 21:49:24 +0200345
346 return 0;
347}
348
349int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg)
350{
351 int rc;
352
353 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200354 rc = vty_read_config_file(config_file, NULL);
Harald Welte799e0c92010-04-30 21:49:24 +0200355 if (rc < 0) {
356 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
357 return rc;
358 }
359
360 return 0;
361}
362