blob: 76f8c4ff548f595ba62a1869c44b26ebf59a4215 [file] [log] [blame]
Neels Hofmeyr87203f22017-10-31 01:15:45 +01001/* MGCP client interface to quagga VTY */
Neels Hofmeyre9920f22017-07-10 15:07:22 +02002/* (C) 2016 by sysmocom s.m.f.c. GmbH <info@sysmocom.de>
3 * Based on OpenBSC interface to quagga VTY (libmsc/vty_interface_layer3.c)
4 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2009-2011 by Holger Hans Peter Freyther
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte220f4872018-02-04 09:04:16 +01009 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
Neels Hofmeyre9920f22017-07-10 15:07:22 +020011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte220f4872018-02-04 09:04:16 +010016 * GNU General Public License for more details.
Neels Hofmeyre9920f22017-07-10 15:07:22 +020017 *
Harald Welte220f4872018-02-04 09:04:16 +010018 * You should have received a copy of the GNU General Public License
Neels Hofmeyre9920f22017-07-10 15:07:22 +020019 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include <inttypes.h>
24#include <stdlib.h>
25#include <talloc.h>
26
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020027#include <osmocom/vty/vty.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020028#include <osmocom/vty/command.h>
Stefan Sperling29248252018-02-22 18:09:28 +010029#include <osmocom/vty/misc.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020030#include <osmocom/core/utils.h>
31
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +020032#include <osmocom/mgcp_client/mgcp_client.h>
Philipp Maier3f2c15f2021-07-22 11:53:07 +020033#include <osmocom/mgcp_client/mgcp_client_internal.h>
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020034#include <osmocom/mgcp_client/mgcp_client_pool_internal.h>
Pau Espin Pedrol5d8b5b02022-10-13 17:52:40 +020035#include <osmocom/mgcp_client/mgcp_client_pool.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020036
Neels Hofmeyre6d8e912018-08-23 16:36:48 +020037#define MGW_STR MGCP_CLIENT_MGW_STR
Neels Hofmeyre9920f22017-07-10 15:07:22 +020038
Pau Espin Pedrolf6333022022-10-13 13:20:10 +020039/* Only common (non-pooled) VTY commands will use this talloc context. All
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020040 * pooled VTY commands will use the pool (global_mgcp_client_pool) as
41 * talloc context. */
42static void *global_mgcp_client_ctx = NULL;
43
44/* MGCP Client configuration used with mgcp_client_vty_init(). (This pointer
45 * points to user provided memory, so it cannot be used as talloc context.) */
46static struct mgcp_client_conf *global_mgcp_client_conf = NULL;
47
48/* Pointer to the MGCP pool that is managed by mgcp_client_pool_vty_init() */
49static struct mgcp_client_pool *global_mgcp_client_pool = NULL;
50
51struct mgcp_client_conf *get_mgcp_client_config(struct vty *vty)
52{
53 if (global_mgcp_client_pool && vty->node == global_mgcp_client_pool->vty_node->node)
54 return vty->index;
Pau Espin Pedrol80dd5762022-10-17 17:26:43 +020055
56 /* Global single MGCP config, deprecated: */
57 vty_out(vty, "%% MGCP commands outside of 'mgw' nodes are deprecated. "
58 "You should consider reading User Manual and migrating to 'mgw' node.%s",
59 VTY_NEWLINE);
60
61 return global_mgcp_client_conf;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020062}
Neels Hofmeyre9920f22017-07-10 15:07:22 +020063
Neels Hofmeyr87203f22017-10-31 01:15:45 +010064DEFUN(cfg_mgw_local_ip, cfg_mgw_local_ip_cmd,
Pau Espin Pedrol531470a2020-08-31 17:06:55 +020065 "mgw local-ip " VTY_IPV46_CMD,
Neels Hofmeyr54dd4b32017-10-31 01:18:33 +010066 MGW_STR "local bind to connect to MGW from\n"
Pau Espin Pedrol531470a2020-08-31 17:06:55 +020067 "local bind IPv4 address\n"
68 "local bind IPv6 address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +020069{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020070 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
71
Neels Hofmeyrc3132fd2018-12-19 00:30:34 +010072 osmo_talloc_replace_string(global_mgcp_client_ctx,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020073 (char **)&conf->local_addr,
Neels Hofmeyrc3132fd2018-12-19 00:30:34 +010074 argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +020075 return CMD_SUCCESS;
76}
Neels Hofmeyr87203f22017-10-31 01:15:45 +010077ALIAS_DEPRECATED(cfg_mgw_local_ip, cfg_mgcpgw_local_ip_cmd,
78 "mgcpgw local-ip A.B.C.D",
79 MGW_STR "local bind to connect to MGCP gateway with\n"
80 "local bind IP address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +020081
Neels Hofmeyr87203f22017-10-31 01:15:45 +010082DEFUN(cfg_mgw_local_port, cfg_mgw_local_port_cmd,
83 "mgw local-port <0-65535>",
Neels Hofmeyr54dd4b32017-10-31 01:18:33 +010084 MGW_STR "local port to connect to MGW from\n"
Neels Hofmeyre9920f22017-07-10 15:07:22 +020085 "local bind port\n")
86{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020087 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
88
89 conf->local_port = atoi(argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +020090 return CMD_SUCCESS;
91}
Neels Hofmeyr87203f22017-10-31 01:15:45 +010092ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
93 "mgcpgw local-port <0-65535>",
94 MGW_STR "local bind to connect to MGCP gateway with\n"
95 "local bind port\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +020096
Neels Hofmeyr87203f22017-10-31 01:15:45 +010097DEFUN(cfg_mgw_remote_ip, cfg_mgw_remote_ip_cmd,
Pau Espin Pedrol531470a2020-08-31 17:06:55 +020098 "mgw remote-ip " VTY_IPV46_CMD,
Neels Hofmeyr54dd4b32017-10-31 01:18:33 +010099 MGW_STR "remote IP address to reach the MGW at\n"
Pau Espin Pedrol531470a2020-08-31 17:06:55 +0200100 "remote IPv4 address\n"
101 "remote IPv6 address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200102{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200103 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
104
Neels Hofmeyrc3132fd2018-12-19 00:30:34 +0100105 osmo_talloc_replace_string(global_mgcp_client_ctx,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200106 (char **)&conf->remote_addr, argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200107 return CMD_SUCCESS;
108}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100109ALIAS_DEPRECATED(cfg_mgw_remote_ip, cfg_mgcpgw_remote_ip_cmd,
110 "mgcpgw remote-ip A.B.C.D",
111 MGW_STR "remote bind to connect to MGCP gateway with\n"
112 "remote bind IP address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200113
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100114DEFUN(cfg_mgw_remote_port, cfg_mgw_remote_port_cmd,
115 "mgw remote-port <0-65535>",
Neels Hofmeyr54dd4b32017-10-31 01:18:33 +0100116 MGW_STR "remote port to reach the MGW at\n"
117 "remote port\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200118{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200119 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
120
121 conf->remote_port = atoi(argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200122 return CMD_SUCCESS;
123}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100124ALIAS_DEPRECATED(cfg_mgw_remote_port, cfg_mgcpgw_remote_port_cmd,
125 "mgcpgw remote-port <0-65535>",
126 MGW_STR "remote bind to connect to MGCP gateway with\n"
127 "remote bind port\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200128
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100129DEFUN_DEPRECATED(cfg_mgw_endpoint_range, cfg_mgw_endpoint_range_cmd,
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100130 "mgw endpoint-range <1-65534> <1-65534>",
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100131 MGW_STR "DEPRECATED: the endpoint range cannot be defined by the client\n"
132 "-\n" "-\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200133{
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100134 vty_out(vty, "Please do not use legacy config 'mgw endpoint-range'"
135 " (the range can no longer be defined by the MGCP client)%s",
136 VTY_NEWLINE);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200137 return CMD_SUCCESS;
138}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100139ALIAS_DEPRECATED(cfg_mgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
140 "mgcpgw endpoint-range <1-65534> <1-65534>",
141 MGW_STR "usable range of endpoint identifiers\n"
142 "set first useable endpoint identifier\n"
143 "set the last useable endpoint identifier\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200144
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000145#define BTS_START_STR "First UDP port allocated for the BTS side\n"
146#define UDP_PORT_STR "UDP Port number\n"
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100147DEFUN_DEPRECATED(cfg_mgw_rtp_bts_base_port,
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000148 cfg_mgw_rtp_bts_base_port_cmd,
149 "mgw bts-base <0-65534>",
150 MGW_STR
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100151 "DEPRECATED: there is no explicit BTS side in current osmo-mgw\n" "-\n")
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000152{
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100153 vty_out(vty, "Please do not use legacy config 'mgw bts-base'"
154 " (there is no explicit BTS side in an MGW anymore)%s",
155 VTY_NEWLINE);
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000156 return CMD_SUCCESS;
157}
158ALIAS_DEPRECATED(cfg_mgw_rtp_bts_base_port,
159 cfg_mgcpgw_rtp_bts_base_port_cmd,
160 "mgcpgw bts-base <0-65534>",
161 MGW_STR
162 BTS_START_STR
163 UDP_PORT_STR)
164
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100165DEFUN(cfg_mgw_endpoint_domain_name,
166 cfg_mgw_endpoint_domain_name_cmd,
167 "mgw endpoint-domain NAME",
168 MGW_STR "Set the domain name to send in MGCP messages, e.g. the part 'foo' in 'rtpbridge/*@foo'.\n"
169 "Domain name, should be alphanumeric.\n")
170{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200171 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
172
173 if (osmo_strlcpy(conf->endpoint_domain_name, argv[0], sizeof(conf->endpoint_domain_name))
174 >= sizeof(conf->endpoint_domain_name)) {
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100175 vty_out(vty, "%% Error: 'mgw endpoint-domain' name too long, max length is %zu: '%s'%s",
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200176 sizeof(conf->endpoint_domain_name) - 1, argv[0], VTY_NEWLINE);
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100177 return CMD_WARNING;
178 }
179 return CMD_SUCCESS;
180}
181
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200182DEFUN(cfg_mgw_reset_ep_name,
183 cfg_mgw_reset_ep_name_cmd,
184 "mgw reset-endpoint NAME",
185 MGW_STR "Add an endpoint name that should be reset (DLCX) on connect to the reset-endpoint list,"
186 "e.g. 'rtpbridge/*'\n"
187 "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
188{
189 int rc;
190 struct reset_ep *reset_ep;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200191 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200192
193 /* stop when the address is already in the list */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200194 llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200195 if (strcmp(argv[0], reset_ep->name) == 0) {
196 vty_out(vty, "%% duplicate endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
197 return CMD_WARNING;
198 }
199 }
200
201 /* the domain name is not part of the actual endpoint name */
202 if (strchr(argv[0], '@')) {
203 vty_out(vty, "%% the endpoint name must be given without domain name ('%s')%s",
204 argv[0], VTY_NEWLINE);
205 return CMD_WARNING;
206 }
207
208 reset_ep = talloc_zero(global_mgcp_client_ctx, struct reset_ep);
209 OSMO_ASSERT(reset_ep);
210
211 rc = osmo_strlcpy(reset_ep->name, argv[0], sizeof(reset_ep->name));
212 if (rc >= sizeof(reset_ep->name)) {
213 vty_out(vty, "%% Error: 'mgw reset-endpoint' name too long, max length is %zu: '%s'%s",
214 sizeof(reset_ep->name) - 1, argv[0], VTY_NEWLINE);
215 talloc_free(reset_ep);
216 return CMD_WARNING;
217 }
218
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200219 llist_add_tail(&reset_ep->list, &conf->reset_epnames);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200220
221 return CMD_SUCCESS;
222}
223
224DEFUN(cfg_mgw_no_reset_ep_name,
225 cfg_mgw_no_reset_ep_name_cmd,
226 "no mgw reset-endpoint NAME",
Oliver Smith29e671f2021-08-18 08:44:47 +0200227 NO_STR MGW_STR "remove an endpoint name from the reset-endpoint list, e.g. 'rtpbridge/*'\n"
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200228 "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
229{
230 struct reset_ep *reset_ep;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200231 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200232
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200233 llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200234 if (strcmp(argv[0], reset_ep->name) == 0) {
235 llist_del(&reset_ep->list);
236 talloc_free(reset_ep);
237 return CMD_SUCCESS;
238 }
239 }
240
241 vty_out(vty, "%% no such endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
242 return CMD_WARNING;
243}
244
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200245static int config_write(struct vty *vty, const char *indent, struct mgcp_client_conf *conf)
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200246{
247 const char *addr;
248 int port;
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200249 struct reset_ep *reset_ep;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200250
Philipp Maierdf9192e2021-09-03 17:50:51 +0200251 if (conf->description)
252 vty_out(vty, "%sdescription %s%s", indent, conf->description, VTY_NEWLINE);
253
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200254 addr = conf->local_addr;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200255 if (addr)
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100256 vty_out(vty, "%smgw local-ip %s%s", indent, addr,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200257 VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200258 port = conf->local_port;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200259 if (port >= 0)
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100260 vty_out(vty, "%smgw local-port %u%s", indent,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200261 (uint16_t)port, VTY_NEWLINE);
262
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200263 addr = conf->remote_addr;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200264 if (addr)
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100265 vty_out(vty, "%smgw remote-ip %s%s", indent, addr,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200266 VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200267 port = conf->remote_port;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200268 if (port >= 0)
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100269 vty_out(vty, "%smgw remote-port %u%s", indent,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200270 (uint16_t)port, VTY_NEWLINE);
271
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200272 if (conf->endpoint_domain_name[0])
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100273 vty_out(vty, "%smgw endpoint-domain %s%s", indent,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200274 conf->endpoint_domain_name, VTY_NEWLINE);
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100275
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200276 llist_for_each_entry(reset_ep, &conf->reset_epnames, list)
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200277 vty_out(vty, "%smgw reset-endpoint %s%s", indent, reset_ep->name, VTY_NEWLINE);
278
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200279 return CMD_SUCCESS;
280}
281
Philipp Maierd6a7e172021-08-03 16:03:27 +0200282/*! Write out MGCP client config to VTY.
283 * \param[in] vty VTY to which we should print.
284 * \param[in] string used for indentation (e.g. " ").
285 * \returns CMD_SUCCESS on success, CMD_WARNING on error */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200286int mgcp_client_config_write(struct vty *vty, const char *indent)
287{
288 return config_write(vty, indent, global_mgcp_client_conf);
289}
290
291static void vty_init_common(void *talloc_ctx, int node)
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200292{
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200293 global_mgcp_client_ctx = talloc_ctx;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200294
Vadim Yanitskiy3ba40952020-10-04 16:42:04 +0700295 install_lib_element(node, &cfg_mgw_local_ip_cmd);
296 install_lib_element(node, &cfg_mgw_local_port_cmd);
297 install_lib_element(node, &cfg_mgw_remote_ip_cmd);
298 install_lib_element(node, &cfg_mgw_remote_port_cmd);
299 install_lib_element(node, &cfg_mgw_endpoint_range_cmd);
300 install_lib_element(node, &cfg_mgw_rtp_bts_base_port_cmd);
301 install_lib_element(node, &cfg_mgw_endpoint_domain_name_cmd);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200302 install_lib_element(node, &cfg_mgw_reset_ep_name_cmd);
303 install_lib_element(node, &cfg_mgw_no_reset_ep_name_cmd);
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100304
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200305 osmo_fsm_vty_add_cmds();
306}
307
Philipp Maierd6a7e172021-08-03 16:03:27 +0200308/*! Set up MGCP client VTY
309 * (called once at startup by the application process).
310 * \param[in] talloc_ctx talloc context to be used by the VTY for allocating memory.
311 * \param[in] node identifier of the node on which the VTY commands should be installed.
312 * \param[in] conf user provided memory to to store the MGCP client configuration data. */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200313void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf)
314{
315 global_mgcp_client_conf = conf;
316
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100317 /* deprecated 'mgcpgw' commands */
Vadim Yanitskiy3ba40952020-10-04 16:42:04 +0700318 install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);
319 install_lib_element(node, &cfg_mgcpgw_local_port_cmd);
320 install_lib_element(node, &cfg_mgcpgw_remote_ip_cmd);
321 install_lib_element(node, &cfg_mgcpgw_remote_port_cmd);
322 install_lib_element(node, &cfg_mgcpgw_endpoint_range_cmd);
323 install_lib_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
Stefan Sperling29248252018-02-22 18:09:28 +0100324
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200325 vty_init_common(talloc_ctx, node);
326}
327
328static int config_write_pool(struct vty *vty)
329{
330 struct mgcp_client_pool *pool = global_mgcp_client_pool;
331 struct mgcp_client_pool_member *pool_member;
332 unsigned int indent_buf_len = strlen(pool->vty_indent) + 1 + 1;
333 char *indent = talloc_zero_size(vty, indent_buf_len);
334
335 snprintf(indent, indent_buf_len, "%s ", pool->vty_indent);
336
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200337 llist_for_each_entry(pool_member, &pool->member_list, list) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200338 vty_out(vty, "%smgw %u%s", pool->vty_indent, pool_member->nr, VTY_NEWLINE);
339 config_write(vty, indent, &pool_member->conf);
340 }
341
342 talloc_free(indent);
343 return CMD_SUCCESS;
344}
345
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200346DEFUN_ATTR(cfg_mgw,
Philipp Maierd55be052021-08-19 14:58:31 +0200347 cfg_mgw_cmd, "mgw <0-255>", "Select a MGCP client config to setup\n" "reference number\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200348{
349 int nr = atoi(argv[0]);
350 struct mgcp_client_pool_member *pool_member;
351
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200352 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200353 if (!pool_member) {
Pau Espin Pedrol6ddc79b2022-10-13 17:03:42 +0200354 pool_member = mgcp_client_pool_member_alloc(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200355 OSMO_ASSERT(pool_member);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200356 }
357
358 vty->index = &pool_member->conf;
Philipp Maierdf9192e2021-09-03 17:50:51 +0200359 vty->index_sub = &pool_member->conf.description;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200360 vty->node = global_mgcp_client_pool->vty_node->node;
361
362 return CMD_SUCCESS;
363}
364
365DEFUN_ATTR(cfg_no_mgw,
366 cfg_no_mgw_cmd,
Philipp Maier74e83d32021-08-20 09:57:27 +0200367 "no mgw <0-255>", NO_STR "Select a MGCP client config to remove\n" "reference number\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200368{
369 int nr = atoi(argv[0]);
370 struct mgcp_client_pool_member *pool_member;
371
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200372 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200373 if (!pool_member) {
374 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
375 return CMD_WARNING;
376 }
377
378 /* Make sure that there are no ongoing calls */
379 if (pool_member->refcount > 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200380 vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't remove it now!%s",
381 mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200382 return CMD_WARNING;
383 }
384
Pau Espin Pedrol6ddc79b2022-10-13 17:03:42 +0200385 mgcp_client_pool_member_free(pool_member);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200386
387 return CMD_SUCCESS;
388}
389
390DEFUN_ATTR(mgw_reconnect, mgw_reconnect_cmd,
391 "mgw <0-255> reconnect",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200392 MGW_STR "reference number\n" "reconfigure and reconnect MGCP client\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200393{
394 int nr = atoi(argv[0]);
395 struct mgcp_client_pool_member *pool_member = NULL;
396
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200397 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200398 if (!pool_member) {
399 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
400 return CMD_WARNING;
401 }
402
403 /* Make sure that there are no ongoing calls */
404 if (pool_member->refcount > 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200405 vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't reconnect it now!%s",
406 mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200407 return CMD_WARNING;
408 }
409
Pau Espin Pedrol35bd2522022-10-13 17:26:33 +0200410 if (mgcp_client_pool_member_reinit_client(pool_member) < 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200411 LOGP(DLMGCP, LOGL_ERROR, "(manual) MGW %s connect failed at (%s:%u)\n",
412 mgcp_client_pool_member_name(pool_member), pool_member->conf.remote_addr,
413 pool_member->conf.remote_port);
Philipp Maierdf9192e2021-09-03 17:50:51 +0200414 vty_out(vty, "%% MGCP client (MGW %s) initalization failed ('%s')%s",
415 mgcp_client_pool_member_name(pool_member), argv[0], VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200416 return CMD_WARNING;
417 }
418
419 return CMD_SUCCESS;
420}
421
422DEFUN_ATTR(mgw_block, mgw_block_cmd,
423 "mgw <0-255> block",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200424 MGW_STR "reference number\n" "block MGCP client so that it won't be used for new calls\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200425{
426 int nr = atoi(argv[0]);
427 struct mgcp_client_pool_member *pool_member = NULL;
428
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200429 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200430 if (!pool_member) {
431 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
432 return CMD_WARNING;
433 }
434
435 pool_member->blocked = true;
436 return CMD_SUCCESS;
437}
438
439DEFUN_ATTR(mgw_unblock, mgw_unblock_cmd,
440 "mgw <0-255> unblock",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200441 MGW_STR "reference number\n" "unblock MGCP client so that it will be available for new calls\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200442{
443 int nr = atoi(argv[0]);
444 struct mgcp_client_pool_member *pool_member = NULL;
445
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200446 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200447 if (!pool_member) {
448 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
449 return CMD_WARNING;
450 }
451
452 pool_member->blocked = false;
453 return CMD_SUCCESS;
454}
455
Pau Espin Pedrola6917fe2022-10-13 14:40:56 +0200456DEFUN(mgw_show, mgw_show_cmd, "show mgw-pool", SHOW_STR "Display information about the MGW-Pool\n")
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200457{
458 vty_out(vty, "%% MGW-Pool:%s", VTY_NEWLINE);
459 struct mgcp_client_pool_member *pool_member;
460
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200461 if (llist_empty(&global_mgcp_client_pool->member_list) && global_mgcp_client_pool->mgcp_client_single) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200462 vty_out(vty, "%% (pool is empty, single MGCP client will be used)%s", VTY_NEWLINE);
463 return CMD_SUCCESS;
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200464 } else if (llist_empty(&global_mgcp_client_pool->member_list)) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200465 vty_out(vty, "%% (pool is empty)%s", VTY_NEWLINE);
466 return CMD_SUCCESS;
467 }
468
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200469 llist_for_each_entry(pool_member, &global_mgcp_client_pool->member_list, list) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200470 vty_out(vty, "%% MGW %s%s", mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200471 vty_out(vty, "%% mgcp-client: %s%s", pool_member->client ? "connected" : "disconnected",
472 VTY_NEWLINE);
473 vty_out(vty, "%% service: %s%s", pool_member->blocked ? "blocked" : "unblocked", VTY_NEWLINE);
474 vty_out(vty, "%% ongoing calls: %u%s", pool_member->refcount, VTY_NEWLINE);
475 }
476 return CMD_SUCCESS;
477}
478
479/*! Set up MGCP client VTY (pooled)
480 * (called once at startup by the application process).
481 * \param[in] parent_node identifier of the parent node on which the mgw node appears.
482 * \param[in] mgw_node identifier that should be used with the newly installed MGW node.
483 * \param[in] indent indentation string to match the indentation in the VTY config
484 * \param[in] pool user provided memory to store the configured MGCP client (MGW) pool. */
485void mgcp_client_pool_vty_init(int parent_node, int mgw_node, const char *indent, struct mgcp_client_pool *pool)
486{
Philipp Maierda3a5752021-08-19 14:24:14 +0200487 /* A pool must be allocated before this function can be called */
488 OSMO_ASSERT(pool);
489
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200490 /* Never allow this function to be called twice on the same pool */
491 OSMO_ASSERT(!pool->vty_indent);
492 OSMO_ASSERT(!pool->vty_node);
493
494 pool->vty_indent = talloc_strdup(pool, indent);
495 OSMO_ASSERT(pool->vty_indent);
496 pool->vty_node = talloc_zero(pool, struct cmd_node);
497 OSMO_ASSERT(pool->vty_node);
498 pool->vty_node->node = mgw_node;
499 pool->vty_node->vtysh = 1;
500 pool->vty_node->prompt = talloc_strdup(pool->vty_node, "%s(config-mgw)# ");
501
502 install_lib_element(parent_node, &cfg_mgw_cmd);
503 install_lib_element(parent_node, &cfg_no_mgw_cmd);
504
505 install_node(pool->vty_node, config_write_pool);
506 vty_init_common(pool, mgw_node);
507
Philipp Maierdf9192e2021-09-03 17:50:51 +0200508 install_element(mgw_node, &cfg_description_cmd);
509
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200510 install_lib_element(ENABLE_NODE, &mgw_reconnect_cmd);
511 install_lib_element(ENABLE_NODE, &mgw_block_cmd);
512 install_lib_element(ENABLE_NODE, &mgw_unblock_cmd);
513
Pau Espin Pedrola6917fe2022-10-13 14:40:56 +0200514 install_lib_element_ve(&mgw_show_cmd);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200515
516 global_mgcp_client_pool = pool;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200517}