blob: b5c1cf287b22c4e877bcb4540b116cac91dfd3d0 [file] [log] [blame]
Jonathan Santos03fd8d02011-05-25 13:54:02 -04001/* OpenBSC NAT interface to quagga VTY */
Jonathan Santos5a45b152011-08-17 15:33:57 -04002/* (C) 2010-2011 by Holger Hans Peter Freyther
3 * (C) 2010-2011 by On-Waves
Jonathan Santos03fd8d02011-05-25 13:54:02 -04004 * All Rights Reserved
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * 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
9 * (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
14 * GNU Affero General Public License for more details.
15 *
16 * 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/>.
18 *
19 */
20
21#include <openbsc/vty.h>
22#include <openbsc/bsc_nat.h>
23#include <openbsc/bsc_nat_sccp.h>
24#include <openbsc/bsc_msc.h>
25#include <openbsc/gsm_04_08.h>
26#include <openbsc/mgcp.h>
27#include <openbsc/vty.h>
28
Jonathan Santos5a45b152011-08-17 15:33:57 -040029#include <osmocom/core/talloc.h>
30#include <osmocom/core/rate_ctr.h>
31#include <osmocom/core/utils.h>
32#include <osmocom/vty/logging.h>
33#include <osmocom/vty/misc.h>
Jonathan Santos03fd8d02011-05-25 13:54:02 -040034
35#include <osmocom/sccp/sccp.h>
36
37#include <stdlib.h>
38
39static struct bsc_nat *_nat;
40
Jonathan Santos5a45b152011-08-17 15:33:57 -040041
42#define PAGING_STR "Paging\n"
43#define SMSC_REWRITE "SMSC Rewriting\n"
44
Jonathan Santos03fd8d02011-05-25 13:54:02 -040045static struct cmd_node nat_node = {
46 NAT_NODE,
47 "%s(nat)#",
48 1,
49};
50
51static struct cmd_node bsc_node = {
52 NAT_BSC_NODE,
53 "%s(bsc)#",
54 1,
55};
56
Jonathan Santos5a45b152011-08-17 15:33:57 -040057static struct cmd_node pgroup_node = {
58 PGROUP_NODE,
59 "%s(paging-group)#",
60 1,
61};
62
63static int config_write_pgroup(struct vty *vty)
64{
65 return CMD_SUCCESS;
66}
67
Jonathan Santos03fd8d02011-05-25 13:54:02 -040068static void write_acc_lst(struct vty *vty, struct bsc_nat_acc_lst *lst)
69{
70 struct bsc_nat_acc_lst_entry *entry;
71
72 llist_for_each_entry(entry, &lst->fltr_list, list) {
73 if (entry->imsi_allow)
74 vty_out(vty, " access-list %s imsi-allow %s%s",
75 lst->name, entry->imsi_allow, VTY_NEWLINE);
76 if (entry->imsi_deny)
77 vty_out(vty, " access-list %s imsi-deny %s%s",
78 lst->name, entry->imsi_deny, VTY_NEWLINE);
79 }
80}
81
Jonathan Santos5a45b152011-08-17 15:33:57 -040082static void dump_lac(struct vty *vty, struct llist_head *head)
83{
84 struct bsc_lac_entry *lac;
85 llist_for_each_entry(lac, head, entry)
86 vty_out(vty, " location_area_code %u%s", lac->lac, VTY_NEWLINE);
87}
88
89
90static void write_pgroup_lst(struct vty *vty, struct bsc_nat_paging_group *pgroup)
91{
92 vty_out(vty, " paging-group %d%s", pgroup->nr, VTY_NEWLINE);
93 dump_lac(vty, &pgroup->lists);
94}
95
Jonathan Santos03fd8d02011-05-25 13:54:02 -040096static int config_write_nat(struct vty *vty)
97{
98 struct bsc_nat_acc_lst *lst;
Jonathan Santos5a45b152011-08-17 15:33:57 -040099 struct bsc_nat_paging_group *pgroup;
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400100
101 vty_out(vty, "nat%s", VTY_NEWLINE);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400102 vty_out(vty, " msc ip %s%s", _nat->main_dest->ip, VTY_NEWLINE);
103 vty_out(vty, " msc port %d%s", _nat->main_dest->port, VTY_NEWLINE);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400104 vty_out(vty, " timeout auth %d%s", _nat->auth_timeout, VTY_NEWLINE);
105 vty_out(vty, " timeout ping %d%s", _nat->ping_timeout, VTY_NEWLINE);
106 vty_out(vty, " timeout pong %d%s", _nat->pong_timeout, VTY_NEWLINE);
107 if (_nat->token)
108 vty_out(vty, " token %s%s", _nat->token, VTY_NEWLINE);
109 vty_out(vty, " ip-dscp %d%s", _nat->bsc_ip_dscp, VTY_NEWLINE);
110 if (_nat->acc_lst_name)
111 vty_out(vty, " access-list-name %s%s", _nat->acc_lst_name, VTY_NEWLINE);
112 if (_nat->ussd_lst_name)
113 vty_out(vty, " ussd-list-name %s%s", _nat->ussd_lst_name, VTY_NEWLINE);
114 if (_nat->ussd_query)
115 vty_out(vty, " ussd-query %s%s", _nat->ussd_query, VTY_NEWLINE);
116 if (_nat->ussd_token)
117 vty_out(vty, " ussd-token %s%s", _nat->ussd_token, VTY_NEWLINE);
118 if (_nat->ussd_local)
119 vty_out(vty, " ussd-local-ip %s%s", _nat->ussd_local, VTY_NEWLINE);
120
121 if (_nat->num_rewr_name)
122 vty_out(vty, " number-rewrite %s%s", _nat->num_rewr_name, VTY_NEWLINE);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400123 if (_nat->smsc_rewr_name)
124 vty_out(vty, " rewrite-smsc addr %s%s",
125 _nat->smsc_rewr_name, VTY_NEWLINE);
126 if (_nat->tpdest_match_name)
127 vty_out(vty, " rewrite-smsc tp-dest-match %s%s",
128 _nat->tpdest_match_name, VTY_NEWLINE);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400129
Jonathan Santos5a45b152011-08-17 15:33:57 -0400130 llist_for_each_entry(lst, &_nat->access_lists, list)
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400131 write_acc_lst(vty, lst);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400132 llist_for_each_entry(pgroup, &_nat->paging_groups, entry)
133 write_pgroup_lst(vty, pgroup);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400134
135 return CMD_SUCCESS;
136}
137
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400138static void config_write_bsc_single(struct vty *vty, struct bsc_config *bsc)
139{
140 vty_out(vty, " bsc %u%s", bsc->nr, VTY_NEWLINE);
141 vty_out(vty, " token %s%s", bsc->token, VTY_NEWLINE);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400142 dump_lac(vty, &bsc->lac_list);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400143 if (bsc->description)
144 vty_out(vty, " description %s%s", bsc->description, VTY_NEWLINE);
145 if (bsc->acc_lst_name)
146 vty_out(vty, " access-list-name %s%s", bsc->acc_lst_name, VTY_NEWLINE);
147 vty_out(vty, " max-endpoints %d%s", bsc->max_endpoints, VTY_NEWLINE);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400148 if (bsc->paging_group != -1)
149 vty_out(vty, " paging group %d%s", bsc->paging_group, VTY_NEWLINE);
150 vty_out(vty, " paging forbidden %d%s", bsc->forbid_paging, VTY_NEWLINE);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400151}
152
153static int config_write_bsc(struct vty *vty)
154{
155 struct bsc_config *bsc;
156
157 llist_for_each_entry(bsc, &_nat->bsc_configs, entry)
158 config_write_bsc_single(vty, bsc);
159 return CMD_SUCCESS;
160}
161
162
163DEFUN(show_sccp, show_sccp_cmd, "show sccp connections",
164 SHOW_STR "Display information about current SCCP connections")
165{
166 struct sccp_connections *con;
167 vty_out(vty, "Listing all open SCCP connections%s", VTY_NEWLINE);
168
169 llist_for_each_entry(con, &_nat->sccp_connections, list_entry) {
170 vty_out(vty, "For BSC Nr: %d BSC ref: 0x%x; MUX ref: 0x%x; Network has ref: %d ref: 0x%x MSC/BSC mux: 0x%x/0x%x type: %s%s",
171 con->bsc->cfg ? con->bsc->cfg->nr : -1,
172 sccp_src_ref_to_int(&con->real_ref),
173 sccp_src_ref_to_int(&con->patched_ref),
174 con->has_remote_ref,
175 sccp_src_ref_to_int(&con->remote_ref),
176 con->msc_endp, con->bsc_endp,
177 bsc_con_type_to_string(con->con_type),
178 VTY_NEWLINE);
179 }
180
181 return CMD_SUCCESS;
182}
183
184DEFUN(show_bsc, show_bsc_cmd, "show bsc connections",
185 SHOW_STR "Display information about current BSCs")
186{
187 struct bsc_connection *con;
188 struct sockaddr_in sock;
189 socklen_t len = sizeof(sock);
190
191 llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
192 getpeername(con->write_queue.bfd.fd, (struct sockaddr *) &sock, &len);
193 vty_out(vty, "BSC nr: %d auth: %d fd: %d peername: %s%s",
194 con->cfg ? con->cfg->nr : -1,
195 con->authenticated, con->write_queue.bfd.fd,
196 inet_ntoa(sock.sin_addr), VTY_NEWLINE);
197 }
198
199 return CMD_SUCCESS;
200}
201
202DEFUN(show_bsc_mgcp, show_bsc_mgcp_cmd, "show bsc mgcp NR",
203 SHOW_STR "Display the MGCP status for a given BSC")
204{
205 struct bsc_connection *con;
206 int nr = atoi(argv[0]);
207 int i, j, endp;
208
209 llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
210 int max;
211 if (!con->cfg)
212 continue;
213 if (con->cfg->nr != nr)
214 continue;
215
216 /* this bsc has no audio endpoints yet */
217 if (!con->_endpoint_status)
218 continue;
219
220 vty_out(vty, "MGCP Status for %d%s", con->cfg->nr, VTY_NEWLINE);
221 max = bsc_mgcp_nr_multiplexes(con->max_endpoints);
222 for (i = 0; i < max; ++i) {
223 for (j = 0; j < 32; ++j) {
224 endp = mgcp_timeslot_to_endpoint(i, j);
225 vty_out(vty, " Endpoint 0x%x %s%s", endp,
226 con->_endpoint_status[endp] == 0
227 ? "free" : "allocated",
228 VTY_NEWLINE);
229 }
230 }
231 break;
232 }
233
234 return CMD_SUCCESS;
235}
236
237DEFUN(show_bsc_cfg, show_bsc_cfg_cmd, "show bsc config",
238 SHOW_STR "Display information about known BSC configs")
239{
240 struct bsc_config *conf;
241 llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
242 vty_out(vty, "BSC token: '%s' nr: %u%s",
243 conf->token, conf->nr, VTY_NEWLINE);
244 if (conf->acc_lst_name)
245 vty_out(vty, " access-list: %s%s",
246 conf->acc_lst_name, VTY_NEWLINE);
247 vty_out(vty, " paging forbidden: %d%s",
248 conf->forbid_paging, VTY_NEWLINE);
249 if (conf->description)
250 vty_out(vty, " description: %s%s", conf->description, VTY_NEWLINE);
251 else
252 vty_out(vty, " No description.%s", VTY_NEWLINE);
253
254 }
255
256 return CMD_SUCCESS;
257}
258
259static void dump_stat_total(struct vty *vty, struct bsc_nat *nat)
260{
261 vty_out(vty, "NAT statistics%s", VTY_NEWLINE);
262 vty_out(vty, " SCCP Connections %lu total, %lu calls%s",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400263 osmo_counter_get(nat->stats.sccp.conn),
264 osmo_counter_get(nat->stats.sccp.calls), VTY_NEWLINE);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400265 vty_out(vty, " MSC Connections %lu%s",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400266 osmo_counter_get(nat->stats.msc.reconn), VTY_NEWLINE);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400267 vty_out(vty, " MSC Connected: %d%s",
268 nat->msc_con->is_connected, VTY_NEWLINE);
269 vty_out(vty, " BSC Connections %lu total, %lu auth failed.%s",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400270 osmo_counter_get(nat->stats.bsc.reconn),
271 osmo_counter_get(nat->stats.bsc.auth_fail), VTY_NEWLINE);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400272}
273
274static void dump_stat_bsc(struct vty *vty, struct bsc_config *conf)
275{
276 int connected = 0;
277 struct bsc_connection *con;
278
279 vty_out(vty, " BSC nr: %d%s",
280 conf->nr, VTY_NEWLINE);
281 vty_out_rate_ctr_group(vty, " ", conf->stats.ctrg);
282
283 llist_for_each_entry(con, &conf->nat->bsc_connections, list_entry) {
284 if (con->cfg != conf)
285 continue;
286 connected = 1;
287 break;
288 }
289
290 vty_out(vty, " Connected: %d%s", connected, VTY_NEWLINE);
291}
292
293DEFUN(show_stats,
294 show_stats_cmd,
295 "show statistics [NR]",
296 SHOW_STR "Display network statistics")
297{
298 struct bsc_config *conf;
299
300 int nr = -1;
301
302 if (argc == 1)
303 nr = atoi(argv[0]);
304
305 dump_stat_total(vty, _nat);
306 llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
307 if (argc == 1 && nr != conf->nr)
308 continue;
309 dump_stat_bsc(vty, conf);
310 }
311
312 return CMD_SUCCESS;
313}
314
315DEFUN(show_stats_lac,
316 show_stats_lac_cmd,
317 "show statistics-by-lac <0-65535>",
318 SHOW_STR "Display network statistics by lac\n"
319 "The lac of the BSC\n")
320{
321 int lac;
322 struct bsc_config *conf;
323
324 lac = atoi(argv[0]);
325
326 dump_stat_total(vty, _nat);
327 llist_for_each_entry(conf, &_nat->bsc_configs, entry) {
328 if (!bsc_config_handles_lac(conf, lac))
329 continue;
330 dump_stat_bsc(vty, conf);
331 }
332
333 return CMD_SUCCESS;
334}
335
336DEFUN(show_msc,
337 show_msc_cmd,
338 "show msc connection",
339 SHOW_STR "Show the status of the MSC connection.")
340{
341 if (!_nat->msc_con) {
342 vty_out(vty, "The MSC is not yet configured.\n");
343 return CMD_WARNING;
344 }
345
Jonathan Santos5a45b152011-08-17 15:33:57 -0400346 vty_out(vty, "MSC is connected: %d%s\n",
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400347 _nat->msc_con->is_connected, VTY_NEWLINE);
348 return CMD_SUCCESS;
349}
350
351DEFUN(close_bsc,
352 close_bsc_cmd,
353 "close bsc connection BSC_NR",
354 "Close the connection with the BSC identified by the config number.")
355{
356 struct bsc_connection *bsc;
357 int bsc_nr = atoi(argv[0]);
358
359 llist_for_each_entry(bsc, &_nat->bsc_connections, list_entry) {
360 if (!bsc->cfg || bsc->cfg->nr != bsc_nr)
361 continue;
362 bsc_close_connection(bsc);
363 break;
364 }
365
366 return CMD_SUCCESS;
367}
368
369DEFUN(cfg_nat, cfg_nat_cmd, "nat", "Configute the NAT")
370{
371 vty->index = _nat;
372 vty->node = NAT_NODE;
373
374 return CMD_SUCCESS;
375}
376
377DEFUN(cfg_nat_msc_ip,
378 cfg_nat_msc_ip_cmd,
379 "msc ip A.B.C.D",
380 "Set the IP address of the MSC.")
381{
382 bsc_nat_set_msc_ip(_nat, argv[0]);
383 return CMD_SUCCESS;
384}
385
386DEFUN(cfg_nat_msc_port,
387 cfg_nat_msc_port_cmd,
388 "msc port <1-65500>",
389 "Set the port of the MSC.")
390{
Jonathan Santos5a45b152011-08-17 15:33:57 -0400391 _nat->main_dest->port = atoi(argv[0]);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400392 return CMD_SUCCESS;
393}
394
395DEFUN(cfg_nat_auth_time,
396 cfg_nat_auth_time_cmd,
397 "timeout auth <1-256>",
398 "The time to wait for an auth response.")
399{
400 _nat->auth_timeout = atoi(argv[0]);
401 return CMD_SUCCESS;
402}
403
404DEFUN(cfg_nat_ping_time,
405 cfg_nat_ping_time_cmd,
406 "timeout ping NR",
407 "Send a ping every NR seconds. Negative to disable.")
408{
409 _nat->ping_timeout = atoi(argv[0]);
410 return CMD_SUCCESS;
411}
412
413DEFUN(cfg_nat_pong_time,
414 cfg_nat_pong_time_cmd,
415 "timeout pong NR",
416 "Wait NR seconds for the PONG response. Should be smaller than ping.")
417{
418 _nat->pong_timeout = atoi(argv[0]);
419 return CMD_SUCCESS;
420}
421
422DEFUN(cfg_nat_token, cfg_nat_token_cmd,
423 "token TOKEN",
424 "Set a token for the NAT")
425{
426 bsc_replace_string(_nat, &_nat->token, argv[0]);
427 return CMD_SUCCESS;
428}
429
430DEFUN(cfg_nat_bsc_ip_dscp, cfg_nat_bsc_ip_dscp_cmd,
431 "ip-dscp <0-255>",
432 "Set the IP DSCP for the BSCs to use\n" "Set the IP_TOS attribute")
433{
434 _nat->bsc_ip_dscp = atoi(argv[0]);
435 return CMD_SUCCESS;
436}
437
438ALIAS_DEPRECATED(cfg_nat_bsc_ip_dscp, cfg_nat_bsc_ip_tos_cmd,
439 "ip-tos <0-255>",
440 "Use ip-dscp in the future.\n" "Set the DSCP\n")
441
442
443DEFUN(cfg_nat_acc_lst_name,
444 cfg_nat_acc_lst_name_cmd,
445 "access-list-name NAME",
446 "Set the name of the access list to use.\n"
447 "The name of the to be used access list.")
448{
449 bsc_replace_string(_nat, &_nat->acc_lst_name, argv[0]);
450 return CMD_SUCCESS;
451}
452
Jonathan Santos5a45b152011-08-17 15:33:57 -0400453DEFUN(cfg_nat_no_acc_lst_name,
454 cfg_nat_no_acc_lst_name_cmd,
455 "no access-list-name",
456 NO_STR "Remove the access list from the NAT.\n")
457{
458 if (_nat->acc_lst_name) {
459 talloc_free(_nat->acc_lst_name);
460 _nat->acc_lst_name = NULL;
461 }
462
463 return CMD_SUCCESS;
464}
465
466static int replace_rules(struct bsc_nat *nat, char **name,
467 struct llist_head *head, const char *file)
468{
469 struct osmo_config_list *rewr = NULL;
470
471 bsc_replace_string(nat, name, file);
472 if (*name) {
473 rewr = osmo_config_list_parse(nat, *name);
474 bsc_nat_num_rewr_entry_adapt(nat, head, rewr);
475 talloc_free(rewr);
476 return CMD_SUCCESS;
477 } else {
478 bsc_nat_num_rewr_entry_adapt(nat, head, NULL);
479 return CMD_SUCCESS;
480 }
481}
482
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400483DEFUN(cfg_nat_number_rewrite,
484 cfg_nat_number_rewrite_cmd,
485 "number-rewrite FILENAME",
486 "Set the file with rewriting rules.\n" "Filename")
487{
Jonathan Santos5a45b152011-08-17 15:33:57 -0400488 return replace_rules(_nat, &_nat->num_rewr_name,
489 &_nat->num_rewr, argv[0]);
490}
491
492DEFUN(cfg_nat_smsc_addr,
493 cfg_nat_smsc_addr_cmd,
494 "rewrite-smsc addr FILENAME",
495 SMSC_REWRITE
496 "The SMSC Address to match and replace in RP-DATA\n"
497 "File with rules for the SMSC Address replacing\n")
498{
499 return replace_rules(_nat, &_nat->smsc_rewr_name,
500 &_nat->smsc_rewr, argv[0]);
501}
502
503DEFUN(cfg_nat_smsc_tpdest,
504 cfg_nat_smsc_tpdest_cmd,
505 "rewrite-smsc tp-dest-match FILENAME",
506 SMSC_REWRITE
507 "Match TP-Destination of a SMS.\n"
508 "File with rules for matching MSISDN and TP-DEST\n")
509{
510 return replace_rules(_nat, &_nat->tpdest_match_name,
511 &_nat->tpdest_match, argv[0]);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400512}
513
514DEFUN(cfg_nat_ussd_lst_name,
515 cfg_nat_ussd_lst_name_cmd,
516 "ussd-list-name NAME",
517 "Set the name of the access list to check for IMSIs for USSD message\n"
518 "The name of the access list for HLR USSD handling")
519{
520 bsc_replace_string(_nat, &_nat->ussd_lst_name, argv[0]);
521 return CMD_SUCCESS;
522}
523
524DEFUN(cfg_nat_ussd_query,
525 cfg_nat_ussd_query_cmd,
Jonathan Santos5a45b152011-08-17 15:33:57 -0400526 "ussd-query REGEXP",
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400527 "Set the USSD query to match with the ussd-list-name\n"
528 "The query to match")
529{
Jonathan Santos5a45b152011-08-17 15:33:57 -0400530 if (bsc_parse_reg(_nat, &_nat->ussd_query_re, &_nat->ussd_query, argc, argv) != 0)
531 return CMD_WARNING;
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400532 return CMD_SUCCESS;
533}
534
535DEFUN(cfg_nat_ussd_token,
536 cfg_nat_ussd_token_cmd,
537 "ussd-token TOKEN",
538 "Set the token used to identify the USSD module\n" "Secret key\n")
539{
540 bsc_replace_string(_nat, &_nat->ussd_token, argv[0]);
541 return CMD_SUCCESS;
542}
543
544DEFUN(cfg_nat_ussd_local,
545 cfg_nat_ussd_local_cmd,
546 "ussd-local-ip A.B.C.D",
547 "Set the IP to listen for the USSD Provider\n" "IP Address\n")
548{
549 bsc_replace_string(_nat, &_nat->ussd_local, argv[0]);
550 return CMD_SUCCESS;
551}
552
553/* per BSC configuration */
554DEFUN(cfg_bsc, cfg_bsc_cmd, "bsc BSC_NR", "Select a BSC to configure")
555{
556 int bsc_nr = atoi(argv[0]);
557 struct bsc_config *bsc;
558
559 if (bsc_nr > _nat->num_bsc) {
560 vty_out(vty, "%% The next unused BSC number is %u%s",
561 _nat->num_bsc, VTY_NEWLINE);
562 return CMD_WARNING;
563 } else if (bsc_nr == _nat->num_bsc) {
564 /* allocate a new one */
565 bsc = bsc_config_alloc(_nat, "unknown");
566 } else
567 bsc = bsc_config_num(_nat, bsc_nr);
568
569 if (!bsc)
570 return CMD_WARNING;
571
572 vty->index = bsc;
573 vty->node = NAT_BSC_NODE;
574
575 return CMD_SUCCESS;
576}
577
578DEFUN(cfg_bsc_token, cfg_bsc_token_cmd, "token TOKEN", "Set the token")
579{
580 struct bsc_config *conf = vty->index;
581
582 bsc_replace_string(conf, &conf->token, argv[0]);
583 return CMD_SUCCESS;
584}
585
586DEFUN(cfg_bsc_lac, cfg_bsc_lac_cmd, "location_area_code <0-65535>",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400587 "Add the Location Area Code (LAC) of this BSC\n" "LAC\n")
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400588{
589 struct bsc_config *tmp;
590 struct bsc_config *conf = vty->index;
591
592 int lac = atoi(argv[0]);
593
594 if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
595 vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
596 lac, VTY_NEWLINE);
597 return CMD_WARNING;
598 }
599
600 /* verify that the LACs are unique */
601 llist_for_each_entry(tmp, &_nat->bsc_configs, entry) {
602 if (bsc_config_handles_lac(tmp, lac)) {
603 vty_out(vty, "%% LAC %d is already used.%s", lac, VTY_NEWLINE);
604 return CMD_ERR_INCOMPLETE;
605 }
606 }
607
608 bsc_config_add_lac(conf, lac);
609
610 return CMD_SUCCESS;
611}
612
613DEFUN(cfg_bsc_no_lac, cfg_bsc_no_lac_cmd,
614 "no location_area_code <0-65535>",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400615 NO_STR "Remove the Location Area Code (LAC) of this BSC\n" "LAC\n")
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400616{
617 int lac = atoi(argv[0]);
618 struct bsc_config *conf = vty->index;
619
620 bsc_config_del_lac(conf, lac);
621 return CMD_SUCCESS;
622}
623
624
625
626DEFUN(cfg_lst_imsi_allow,
627 cfg_lst_imsi_allow_cmd,
628 "access-list NAME imsi-allow [REGEXP]",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400629 "Add the regexp to the allowed list\n"
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400630 "The name of the access-list\n"
631 "The regexp of allowed IMSIs\n")
632{
633 struct bsc_nat_acc_lst *acc;
634 struct bsc_nat_acc_lst_entry *entry;
635
636 acc = bsc_nat_acc_lst_get(_nat, argv[0]);
637 if (!acc)
638 return CMD_WARNING;
639
640 entry = bsc_nat_acc_lst_entry_create(acc);
641 if (!entry)
642 return CMD_WARNING;
643
Jonathan Santos5a45b152011-08-17 15:33:57 -0400644 if (bsc_parse_reg(acc, &entry->imsi_allow_re, &entry->imsi_allow, argc - 1, &argv[1]) != 0)
645 return CMD_WARNING;
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400646 return CMD_SUCCESS;
647}
648
649DEFUN(cfg_lst_imsi_deny,
650 cfg_lst_imsi_deny_cmd,
651 "access-list NAME imsi-deny [REGEXP]",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400652 "Add the regexp to the deny list\n"
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400653 "The name of the access-list\n"
654 "The regexp of to be denied IMSIs\n")
655{
656 struct bsc_nat_acc_lst *acc;
657 struct bsc_nat_acc_lst_entry *entry;
658
659 acc = bsc_nat_acc_lst_get(_nat, argv[0]);
660 if (!acc)
661 return CMD_WARNING;
662
663 entry = bsc_nat_acc_lst_entry_create(acc);
664 if (!entry)
665 return CMD_WARNING;
666
Jonathan Santos5a45b152011-08-17 15:33:57 -0400667 if (bsc_parse_reg(acc, &entry->imsi_deny_re, &entry->imsi_deny, argc - 1, &argv[1]) != 0)
668 return CMD_WARNING;
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400669 return CMD_SUCCESS;
670}
671
672/* naming to follow Zebra... */
673DEFUN(cfg_lst_no,
674 cfg_lst_no_cmd,
675 "no access-list NAME",
676 NO_STR "Remove an access-list by name\n"
677 "The access-list to remove\n")
678{
679 struct bsc_nat_acc_lst *acc;
680 acc = bsc_nat_acc_lst_find(_nat, argv[0]);
681 if (!acc)
682 return CMD_WARNING;
683
684 bsc_nat_acc_lst_delete(acc);
685 return CMD_SUCCESS;
686}
687
688DEFUN(show_acc_lst,
689 show_acc_lst_cmd,
690 "show access-list NAME",
691 SHOW_STR "The name of the access list\n")
692{
693 struct bsc_nat_acc_lst *acc;
694 acc = bsc_nat_acc_lst_find(_nat, argv[0]);
695 if (!acc)
696 return CMD_WARNING;
697
698 vty_out(vty, "access-list %s%s", acc->name, VTY_NEWLINE);
699 vty_out_rate_ctr_group(vty, " ", acc->stats);
700
701 return CMD_SUCCESS;
702}
703
704
705DEFUN(cfg_bsc_acc_lst_name,
706 cfg_bsc_acc_lst_name_cmd,
707 "access-list-name NAME",
708 "Set the name of the access list to use.\n"
709 "The name of the to be used access list.")
710{
711 struct bsc_config *conf = vty->index;
712
713 bsc_replace_string(conf, &conf->acc_lst_name, argv[0]);
714 return CMD_SUCCESS;
715}
716
Jonathan Santos5a45b152011-08-17 15:33:57 -0400717DEFUN(cfg_bsc_no_acc_lst_name,
718 cfg_bsc_no_acc_lst_name_cmd,
719 "no access-list-name",
720 NO_STR "Do not use an access-list for the BSC.\n")
721{
722 struct bsc_config *conf = vty->index;
723
724 if (conf->acc_lst_name) {
725 talloc_free(conf->acc_lst_name);
726 conf->acc_lst_name = NULL;
727 }
728
729 return CMD_SUCCESS;
730}
731
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400732DEFUN(cfg_bsc_max_endps, cfg_bsc_max_endps_cmd,
733 "max-endpoints <1-1024>",
734 "Highest endpoint to use (exclusively)\n" "Number of ports\n")
735{
736 struct bsc_config *conf = vty->index;
737
738 conf->max_endpoints = atoi(argv[0]);
739 return CMD_SUCCESS;
740}
741
742DEFUN(cfg_bsc_paging,
743 cfg_bsc_paging_cmd,
744 "paging forbidden (0|1)",
Jonathan Santos5a45b152011-08-17 15:33:57 -0400745 PAGING_STR "Forbid sending PAGING REQUESTS to the BSC.")
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400746{
747 struct bsc_config *conf = vty->index;
748
749 if (strcmp("1", argv[0]) == 0)
750 conf->forbid_paging = 1;
751 else
752 conf->forbid_paging = 0;
753
754 return CMD_SUCCESS;
755}
756
757DEFUN(cfg_bsc_desc,
758 cfg_bsc_desc_cmd,
759 "description DESC",
760 "Provide a description for the given BSC.")
761{
762 struct bsc_config *conf = vty->index;
763
764 bsc_replace_string(conf, &conf->description, argv[0]);
765 return CMD_SUCCESS;
766}
767
Jonathan Santos5a45b152011-08-17 15:33:57 -0400768DEFUN(cfg_bsc_paging_grp,
769 cfg_bsc_paging_grp_cmd,
770 "paging group <0-1000>",
771 PAGING_STR "Use a paging group\n" "Paging Group to use\n")
772{
773 struct bsc_config *conf = vty->index;
774 conf->paging_group = atoi(argv[0]);
775 return CMD_SUCCESS;
776}
777
778ALIAS_DEPRECATED(cfg_bsc_paging_grp, cfg_bsc_old_grp_cmd,
779 "paging-group <0-1000>",
780 "Use a paging group\n" "Paging Group to use\n")
781
782DEFUN(cfg_bsc_no_paging_grp,
783 cfg_bsc_no_paging_grp_cmd,
784 "no paging group",
785 NO_STR PAGING_STR "Disable the usage of a paging group.\n")
786{
787 struct bsc_config *conf = vty->index;
788 conf->paging_group = PAGIN_GROUP_UNASSIGNED;
789 return CMD_SUCCESS;
790}
791
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400792DEFUN(test_regex, test_regex_cmd,
793 "test regex PATTERN STRING",
794 "Check if the string is matching the current pattern.")
795{
796 regex_t reg;
797 char *str = NULL;
798
799 memset(&reg, 0, sizeof(reg));
Jonathan Santos5a45b152011-08-17 15:33:57 -0400800 if (bsc_parse_reg(_nat, &reg, &str, 1, argv) != 0)
801 return CMD_WARNING;
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400802
803 vty_out(vty, "String matches allow pattern: %d%s",
804 regexec(&reg, argv[1], 0, NULL, 0) == 0, VTY_NEWLINE);
805
806 talloc_free(str);
807 regfree(&reg);
808 return CMD_SUCCESS;
809}
810
811DEFUN(set_last_endp, set_last_endp_cmd,
812 "set bsc last-used-endpoint <0-9999999999> <0-1024>",
813 "Set a value\n" "Operate on a BSC\n"
814 "Last used endpoint for an assignment\n" "BSC configuration number\n"
815 "Endpoint number used\n")
816{
817 struct bsc_connection *con;
818 int nr = atoi(argv[0]);
819 int endp = atoi(argv[1]);
820
821
822 llist_for_each_entry(con, &_nat->bsc_connections, list_entry) {
823 if (!con->cfg)
824 continue;
825 if (con->cfg->nr != nr)
826 continue;
827
828 con->last_endpoint = endp;
829 vty_out(vty, "Updated the last endpoint for %d to %d.%s",
830 con->cfg->nr, con->last_endpoint, VTY_NEWLINE);
831 }
832
833 return CMD_SUCCESS;
834}
835
Jonathan Santos5a45b152011-08-17 15:33:57 -0400836DEFUN(block_new_conn, block_new_conn_cmd,
837 "nat-block (block|unblock)",
838 "Block the NAT for new connections\n"
839 "Block\n" "Unblock\n")
840{
841 _nat->blocked = argv[0][0] == 'b';
842 vty_out(vty, "%%Going to %s the NAT.%s",
843 _nat->blocked ? "block" : "unblock", VTY_NEWLINE);
844 return CMD_SUCCESS;
845}
846
847/* paging group */
848DEFUN(cfg_nat_pgroup, cfg_nat_pgroup_cmd,
849 "paging-group <0-1000>",
850 "Create a Paging Group\n" "Number of the Group\n")
851{
852 int group = atoi(argv[0]);
853 struct bsc_nat_paging_group *pgroup;
854 pgroup = bsc_nat_paging_group_num(_nat, group);
855 if (!pgroup)
856 pgroup = bsc_nat_paging_group_create(_nat, group);
857 if (!pgroup) {
858 vty_out(vty, "Failed to create the group.%s", VTY_NEWLINE);
859 return CMD_WARNING;
860 }
861
862 vty->index = pgroup;
863 vty->node = PGROUP_NODE;
864 return CMD_SUCCESS;
865}
866
867DEFUN(cfg_nat_no_pgroup, cfg_nat_no_pgroup_cmd,
868 "no paging-group <0-1000>",
869 NO_STR "Delete paging-group\n")
870{
871 int group = atoi(argv[0]);
872 struct bsc_nat_paging_group *pgroup;
873 pgroup = bsc_nat_paging_group_num(_nat, group);
874 if (!pgroup) {
875 vty_out(vty, "No such paging group %d.%s", group, VTY_NEWLINE);
876 return CMD_WARNING;
877 }
878
879 bsc_nat_paging_group_delete(pgroup);
880 return CMD_SUCCESS;
881}
882
883DEFUN(cfg_pgroup_lac, cfg_pgroup_lac_cmd,
884 "location_area_code <0-65535>",
885 "Add the Location Area Code (LAC)\n" "LAC\n")
886{
887 struct bsc_nat_paging_group *pgroup = vty->index;
888
889 int lac = atoi(argv[0]);
890 if (lac == GSM_LAC_RESERVED_DETACHED || lac == GSM_LAC_RESERVED_ALL_BTS) {
891 vty_out(vty, "%% LAC %d is reserved by GSM 04.08%s",
892 lac, VTY_NEWLINE);
893 return CMD_WARNING;
894 }
895
896 bsc_nat_paging_group_add_lac(pgroup, lac);
897 return CMD_SUCCESS;
898}
899
900DEFUN(cfg_pgroup_no_lac, cfg_pgroup_no_lac_cmd,
901 "no location_area_code <0-65535>",
902 NO_STR "Remove the Location Area Code (LAC)\n" "LAC\n")
903{
904 int lac = atoi(argv[0]);
905 struct bsc_nat_paging_group *pgroup = vty->index;
906
907 bsc_nat_paging_group_del_lac(pgroup, lac);
908 return CMD_SUCCESS;
909}
910
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400911int bsc_nat_vty_init(struct bsc_nat *nat)
912{
913 _nat = nat;
914
915 /* show commands */
916 install_element_ve(&show_sccp_cmd);
917 install_element_ve(&show_bsc_cmd);
918 install_element_ve(&show_bsc_cfg_cmd);
919 install_element_ve(&show_stats_cmd);
920 install_element_ve(&show_stats_lac_cmd);
921 install_element_ve(&close_bsc_cmd);
922 install_element_ve(&show_msc_cmd);
923 install_element_ve(&test_regex_cmd);
924 install_element_ve(&show_bsc_mgcp_cmd);
925 install_element_ve(&show_acc_lst_cmd);
926
927 install_element(ENABLE_NODE, &set_last_endp_cmd);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400928 install_element(ENABLE_NODE, &block_new_conn_cmd);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400929
930 /* nat group */
931 install_element(CONFIG_NODE, &cfg_nat_cmd);
932 install_node(&nat_node, config_write_nat);
933 install_default(NAT_NODE);
934 install_element(NAT_NODE, &ournode_exit_cmd);
935 install_element(NAT_NODE, &ournode_end_cmd);
936 install_element(NAT_NODE, &cfg_nat_msc_ip_cmd);
937 install_element(NAT_NODE, &cfg_nat_msc_port_cmd);
938 install_element(NAT_NODE, &cfg_nat_auth_time_cmd);
939 install_element(NAT_NODE, &cfg_nat_ping_time_cmd);
940 install_element(NAT_NODE, &cfg_nat_pong_time_cmd);
941 install_element(NAT_NODE, &cfg_nat_token_cmd);
942 install_element(NAT_NODE, &cfg_nat_bsc_ip_dscp_cmd);
943 install_element(NAT_NODE, &cfg_nat_bsc_ip_tos_cmd);
944 install_element(NAT_NODE, &cfg_nat_acc_lst_name_cmd);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400945 install_element(NAT_NODE, &cfg_nat_no_acc_lst_name_cmd);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400946 install_element(NAT_NODE, &cfg_nat_ussd_lst_name_cmd);
947 install_element(NAT_NODE, &cfg_nat_ussd_query_cmd);
948 install_element(NAT_NODE, &cfg_nat_ussd_token_cmd);
949 install_element(NAT_NODE, &cfg_nat_ussd_local_cmd);
950
951 /* access-list */
952 install_element(NAT_NODE, &cfg_lst_imsi_allow_cmd);
953 install_element(NAT_NODE, &cfg_lst_imsi_deny_cmd);
954 install_element(NAT_NODE, &cfg_lst_no_cmd);
955
956 /* number rewriting */
957 install_element(NAT_NODE, &cfg_nat_number_rewrite_cmd);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400958 install_element(NAT_NODE, &cfg_nat_smsc_addr_cmd);
959 install_element(NAT_NODE, &cfg_nat_smsc_tpdest_cmd);
960
961 install_element(NAT_NODE, &cfg_nat_pgroup_cmd);
962 install_element(NAT_NODE, &cfg_nat_no_pgroup_cmd);
963 install_node(&pgroup_node, config_write_pgroup);
964 install_default(PGROUP_NODE);
965 install_element(PGROUP_NODE, &cfg_pgroup_lac_cmd);
966 install_element(PGROUP_NODE, &cfg_pgroup_no_lac_cmd);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400967
968 /* BSC subgroups */
969 install_element(NAT_NODE, &cfg_bsc_cmd);
970 install_node(&bsc_node, config_write_bsc);
971 install_default(NAT_BSC_NODE);
972 install_element(NAT_BSC_NODE, &ournode_exit_cmd);
973 install_element(NAT_BSC_NODE, &ournode_end_cmd);
974 install_element(NAT_BSC_NODE, &cfg_bsc_token_cmd);
975 install_element(NAT_BSC_NODE, &cfg_bsc_lac_cmd);
976 install_element(NAT_BSC_NODE, &cfg_bsc_no_lac_cmd);
977 install_element(NAT_BSC_NODE, &cfg_bsc_paging_cmd);
978 install_element(NAT_BSC_NODE, &cfg_bsc_desc_cmd);
979 install_element(NAT_BSC_NODE, &cfg_bsc_acc_lst_name_cmd);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400980 install_element(NAT_BSC_NODE, &cfg_bsc_no_acc_lst_name_cmd);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400981 install_element(NAT_BSC_NODE, &cfg_bsc_max_endps_cmd);
Jonathan Santos5a45b152011-08-17 15:33:57 -0400982 install_element(NAT_BSC_NODE, &cfg_bsc_old_grp_cmd);
983 install_element(NAT_BSC_NODE, &cfg_bsc_paging_grp_cmd);
984 install_element(NAT_BSC_NODE, &cfg_bsc_no_paging_grp_cmd);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400985
986 mgcp_vty_init();
987
988 return 0;
989}
990
991
992/* called by the telnet interface... we have our own init above */
Jonathan Santos5a45b152011-08-17 15:33:57 -0400993int bsc_vty_init(const struct log_info *cat)
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400994{
Jonathan Santos5a45b152011-08-17 15:33:57 -0400995 logging_vty_add_cmds(cat);
Jonathan Santos03fd8d02011-05-25 13:54:02 -0400996 return 0;
997}