blob: 9acb6215319154bb8b4a823954e42c426ab8fab4 [file] [log] [blame]
Neels Hofmeyr87203f22017-10-31 01:15:45 +01001/* MGCP client interface to quagga VTY */
Vadim Yanitskiye3624562023-05-18 17:22:26 +07002/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
Neels Hofmeyre9920f22017-07-10 15:07:22 +02003 * 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>
Pau Espin Pedrol563386e2023-06-14 12:20:49 +020031#include <osmocom/core/timer.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020032
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +020033#include <osmocom/mgcp_client/mgcp_client.h>
Philipp Maier3f2c15f2021-07-22 11:53:07 +020034#include <osmocom/mgcp_client/mgcp_client_internal.h>
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020035#include <osmocom/mgcp_client/mgcp_client_pool_internal.h>
Pau Espin Pedrol5d8b5b02022-10-13 17:52:40 +020036#include <osmocom/mgcp_client/mgcp_client_pool.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020037
Neels Hofmeyre6d8e912018-08-23 16:36:48 +020038#define MGW_STR MGCP_CLIENT_MGW_STR
Neels Hofmeyre9920f22017-07-10 15:07:22 +020039
Pau Espin Pedrolf6333022022-10-13 13:20:10 +020040/* Only common (non-pooled) VTY commands will use this talloc context. All
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020041 * pooled VTY commands will use the pool (global_mgcp_client_pool) as
42 * talloc context. */
43static void *global_mgcp_client_ctx = NULL;
44
45/* MGCP Client configuration used with mgcp_client_vty_init(). (This pointer
46 * points to user provided memory, so it cannot be used as talloc context.) */
47static struct mgcp_client_conf *global_mgcp_client_conf = NULL;
48
49/* Pointer to the MGCP pool that is managed by mgcp_client_pool_vty_init() */
50static struct mgcp_client_pool *global_mgcp_client_pool = NULL;
51
Pau Espin Pedrol563386e2023-06-14 12:20:49 +020052static struct mgcp_client_conf *get_mgcp_client_config(struct vty *vty)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020053{
54 if (global_mgcp_client_pool && vty->node == global_mgcp_client_pool->vty_node->node)
55 return vty->index;
Pau Espin Pedrol80dd5762022-10-17 17:26:43 +020056
57 /* Global single MGCP config, deprecated: */
58 vty_out(vty, "%% MGCP commands outside of 'mgw' nodes are deprecated. "
Harald Welte1a7048d2023-01-04 15:37:00 +010059 "You should consider reading the User Manual and migrating to 'mgw' node.%s",
Pau Espin Pedrol80dd5762022-10-17 17:26:43 +020060 VTY_NEWLINE);
61
62 return global_mgcp_client_conf;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020063}
Neels Hofmeyre9920f22017-07-10 15:07:22 +020064
Pau Espin Pedrol563386e2023-06-14 12:20:49 +020065static struct mgcp_client *get_mgcp_client(struct vty *vty)
66{
67 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
68 struct mgcp_client_pool_member *pool_member;
69
70 if (global_mgcp_client_pool && vty->node == global_mgcp_client_pool->vty_node->node) {
71 llist_for_each_entry(pool_member, &global_mgcp_client_pool->member_list, list) {
72 /* Find matching the conf pointer: */
73 if (&pool_member->conf != conf)
74 continue;
75 return pool_member->client;
76 }
77 }
78
79 /* Global single MGCP config, deprecated: */
80 vty_out(vty, "%% MGCP commands outside of 'mgw' nodes are deprecated. "
81 "You should consider reading the User Manual and migrating to 'mgw' node.%s",
82 VTY_NEWLINE);
83
84 /* There's no way to obtain the struct mgcp_client in old interface, but anyway it's deprecated. */
85 return NULL;
86}
87
88
Neels Hofmeyr87203f22017-10-31 01:15:45 +010089DEFUN(cfg_mgw_local_ip, cfg_mgw_local_ip_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +020090 "local-ip " VTY_IPV46_CMD,
91 "local bind to connect to MGW from\n"
Pau Espin Pedrol531470a2020-08-31 17:06:55 +020092 "local bind IPv4 address\n"
93 "local bind IPv6 address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +020094{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020095 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
96
Neels Hofmeyrc3132fd2018-12-19 00:30:34 +010097 osmo_talloc_replace_string(global_mgcp_client_ctx,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +020098 (char **)&conf->local_addr,
Neels Hofmeyrc3132fd2018-12-19 00:30:34 +010099 argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200100 return CMD_SUCCESS;
101}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100102ALIAS_DEPRECATED(cfg_mgw_local_ip, cfg_mgcpgw_local_ip_cmd,
103 "mgcpgw local-ip A.B.C.D",
104 MGW_STR "local bind to connect to MGCP gateway with\n"
105 "local bind IP address\n")
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200106ALIAS_DEPRECATED(cfg_mgw_local_ip,
107 cfg_mgw_mgw_local_ip_cmd,
108 "mgw local-ip " VTY_IPV46_CMD,
109 MGW_STR "local bind to connect to MGW from\n"
110 "local bind IPv4 address\n"
111 "local bind IPv6 address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200112
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100113DEFUN(cfg_mgw_local_port, cfg_mgw_local_port_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200114 "local-port <0-65535>",
115 "local port to connect to MGW from\n"
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200116 "local bind port\n")
117{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200118 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
119
120 conf->local_port = atoi(argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200121 return CMD_SUCCESS;
122}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100123ALIAS_DEPRECATED(cfg_mgw_local_port, cfg_mgcpgw_local_port_cmd,
124 "mgcpgw local-port <0-65535>",
125 MGW_STR "local bind to connect to MGCP gateway with\n"
126 "local bind port\n")
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200127ALIAS_DEPRECATED(cfg_mgw_local_port,
128 cfg_mgw_mgw_local_port_cmd,
129 "mgw local-port <0-65535>",
130 MGW_STR "local port to connect to MGW from\n"
131 "local bind port\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200132
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100133DEFUN(cfg_mgw_remote_ip, cfg_mgw_remote_ip_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200134 "remote-ip " VTY_IPV46_CMD,
135 "remote IP address to reach the MGW at\n"
Pau Espin Pedrol531470a2020-08-31 17:06:55 +0200136 "remote IPv4 address\n"
137 "remote IPv6 address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200138{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200139 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
140
Neels Hofmeyrc3132fd2018-12-19 00:30:34 +0100141 osmo_talloc_replace_string(global_mgcp_client_ctx,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200142 (char **)&conf->remote_addr, argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200143 return CMD_SUCCESS;
144}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100145ALIAS_DEPRECATED(cfg_mgw_remote_ip, cfg_mgcpgw_remote_ip_cmd,
146 "mgcpgw remote-ip A.B.C.D",
147 MGW_STR "remote bind to connect to MGCP gateway with\n"
148 "remote bind IP address\n")
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200149ALIAS_DEPRECATED(cfg_mgw_remote_ip,
150 cfg_mgw_mgw_remote_ip_cmd,
151 "mgw remote-ip " VTY_IPV46_CMD,
152 MGW_STR "remote IP address to reach the MGW at\n"
153 "remote IPv4 address\n"
154 "remote IPv6 address\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200155
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100156DEFUN(cfg_mgw_remote_port, cfg_mgw_remote_port_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200157 "remote-port <0-65535>",
158 "remote port to reach the MGW at\n"
Neels Hofmeyr54dd4b32017-10-31 01:18:33 +0100159 "remote port\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200160{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200161 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
162
163 conf->remote_port = atoi(argv[0]);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200164 return CMD_SUCCESS;
165}
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100166ALIAS_DEPRECATED(cfg_mgw_remote_port, cfg_mgcpgw_remote_port_cmd,
167 "mgcpgw remote-port <0-65535>",
168 MGW_STR "remote bind to connect to MGCP gateway with\n"
169 "remote bind port\n")
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200170ALIAS_DEPRECATED(cfg_mgw_remote_port,
171 cfg_mgw_mgw_remote_port_cmd,
172 "mgw remote-port <0-65535>",
173 MGW_STR "remote port to reach the MGW at\n"
174 "remote port\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200175
Pau Espin Pedrol2172f402022-10-19 16:13:01 +0200176DEFUN_DEPRECATED(cfg_mgw_mgw_endpoint_range, cfg_mgw_mgw_endpoint_range_cmd,
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100177 "mgw endpoint-range <1-65534> <1-65534>",
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100178 MGW_STR "DEPRECATED: the endpoint range cannot be defined by the client\n"
179 "-\n" "-\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200180{
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100181 vty_out(vty, "Please do not use legacy config 'mgw endpoint-range'"
182 " (the range can no longer be defined by the MGCP client)%s",
183 VTY_NEWLINE);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200184 return CMD_SUCCESS;
185}
Pau Espin Pedrol2172f402022-10-19 16:13:01 +0200186ALIAS_DEPRECATED(cfg_mgw_mgw_endpoint_range, cfg_mgcpgw_endpoint_range_cmd,
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100187 "mgcpgw endpoint-range <1-65534> <1-65534>",
188 MGW_STR "usable range of endpoint identifiers\n"
189 "set first useable endpoint identifier\n"
190 "set the last useable endpoint identifier\n")
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200191
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000192#define BTS_START_STR "First UDP port allocated for the BTS side\n"
193#define UDP_PORT_STR "UDP Port number\n"
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100194DEFUN_DEPRECATED(cfg_mgw_rtp_bts_base_port,
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000195 cfg_mgw_rtp_bts_base_port_cmd,
196 "mgw bts-base <0-65534>",
197 MGW_STR
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100198 "DEPRECATED: there is no explicit BTS side in current osmo-mgw\n" "-\n")
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000199{
Neels Hofmeyr72bc8da2018-12-19 00:44:37 +0100200 vty_out(vty, "Please do not use legacy config 'mgw bts-base'"
201 " (there is no explicit BTS side in an MGW anymore)%s",
202 VTY_NEWLINE);
Neels Hofmeyrc0dcc3c2017-12-02 18:31:34 +0000203 return CMD_SUCCESS;
204}
205ALIAS_DEPRECATED(cfg_mgw_rtp_bts_base_port,
206 cfg_mgcpgw_rtp_bts_base_port_cmd,
207 "mgcpgw bts-base <0-65534>",
208 MGW_STR
209 BTS_START_STR
210 UDP_PORT_STR)
211
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100212DEFUN(cfg_mgw_endpoint_domain_name,
213 cfg_mgw_endpoint_domain_name_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200214 "endpoint-domain NAME",
215 "Set the domain name to send in MGCP messages, e.g. the part 'foo' in 'rtpbridge/*@foo'.\n"
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100216 "Domain name, should be alphanumeric.\n")
217{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200218 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
219
220 if (osmo_strlcpy(conf->endpoint_domain_name, argv[0], sizeof(conf->endpoint_domain_name))
221 >= sizeof(conf->endpoint_domain_name)) {
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100222 vty_out(vty, "%% Error: 'mgw endpoint-domain' name too long, max length is %zu: '%s'%s",
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200223 sizeof(conf->endpoint_domain_name) - 1, argv[0], VTY_NEWLINE);
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100224 return CMD_WARNING;
225 }
226 return CMD_SUCCESS;
227}
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200228ALIAS_DEPRECATED(cfg_mgw_endpoint_domain_name,
229 cfg_mgw_mgw_endpoint_domain_name_cmd,
230 "mgw endpoint-domain NAME",
231 MGW_STR "Set the domain name to send in MGCP messages, e.g. the part 'foo' in 'rtpbridge/*@foo'.\n"
232 "Domain name, should be alphanumeric.\n")
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100233
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200234DEFUN(cfg_mgw_reset_ep_name,
235 cfg_mgw_reset_ep_name_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200236 "reset-endpoint NAME",
237 "Add an endpoint name that should be reset (DLCX) on connect to the reset-endpoint list,"
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200238 "e.g. 'rtpbridge/*'\n"
239 "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
240{
241 int rc;
242 struct reset_ep *reset_ep;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200243 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200244
245 /* stop when the address is already in the list */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200246 llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200247 if (strcmp(argv[0], reset_ep->name) == 0) {
248 vty_out(vty, "%% duplicate endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
249 return CMD_WARNING;
250 }
251 }
252
253 /* the domain name is not part of the actual endpoint name */
254 if (strchr(argv[0], '@')) {
255 vty_out(vty, "%% the endpoint name must be given without domain name ('%s')%s",
256 argv[0], VTY_NEWLINE);
257 return CMD_WARNING;
258 }
259
260 reset_ep = talloc_zero(global_mgcp_client_ctx, struct reset_ep);
261 OSMO_ASSERT(reset_ep);
262
263 rc = osmo_strlcpy(reset_ep->name, argv[0], sizeof(reset_ep->name));
264 if (rc >= sizeof(reset_ep->name)) {
265 vty_out(vty, "%% Error: 'mgw reset-endpoint' name too long, max length is %zu: '%s'%s",
266 sizeof(reset_ep->name) - 1, argv[0], VTY_NEWLINE);
267 talloc_free(reset_ep);
268 return CMD_WARNING;
269 }
270
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200271 llist_add_tail(&reset_ep->list, &conf->reset_epnames);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200272
273 return CMD_SUCCESS;
274}
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200275ALIAS_DEPRECATED(cfg_mgw_reset_ep_name,
276 cfg_mgw_mgw_reset_ep_name_cmd,
277 "mgw reset-endpoint NAME",
278 MGW_STR "Add an endpoint name that should be reset (DLCX) on connect to the reset-endpoint list,"
279 "e.g. 'rtpbridge/*'\n"
280 "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200281
282DEFUN(cfg_mgw_no_reset_ep_name,
283 cfg_mgw_no_reset_ep_name_cmd,
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200284 "no reset-endpoint NAME",
285 NO_STR "remove an endpoint name from the reset-endpoint list, e.g. 'rtpbridge/*'\n"
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200286 "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
287{
288 struct reset_ep *reset_ep;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200289 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200290
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200291 llist_for_each_entry(reset_ep, &conf->reset_epnames, list) {
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200292 if (strcmp(argv[0], reset_ep->name) == 0) {
293 llist_del(&reset_ep->list);
294 talloc_free(reset_ep);
295 return CMD_SUCCESS;
296 }
297 }
298
299 vty_out(vty, "%% no such endpoint name configured ('%s')%s", argv[0], VTY_NEWLINE);
300 return CMD_WARNING;
301}
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200302ALIAS_DEPRECATED(cfg_mgw_no_reset_ep_name,
303 cfg_mgw_mgw_no_reset_ep_name_cmd,
304 "no mgw reset-endpoint NAME",
305 NO_STR MGW_STR "remove an endpoint name from the reset-endpoint list, e.g. 'rtpbridge/*'\n"
306 "Endpoint name, e.g. 'rtpbridge/*' or 'ds/e1-0/s-3/su16-4'.\n")
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200307
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200308DEFUN(cfg_mgw_mgw_keepalive_req_interval,
309 cfg_mgw_mgw_keepalive_req_interval_cmd,
310 "keepalive request-interval <0-4294967295>",
311 "Monitor if the MGCP link against MGW is still usable\n"
312 "Send an MGCP command to the MGW at given interval if no other commands are sent\n"
313 "The interval at which send MGCP commands (s), 0 to disable\n")
314{
315 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
316 struct mgcp_client *mgcp = get_mgcp_client(vty);
317
318 conf->keepalive.req_interval_sec = atoi(argv[0]);
319
320 if (!mgcp)
321 return CMD_SUCCESS;
322
323 /* If client already exists, apply the change immediately if possible: */
324 mgcp->actual.keepalive.req_interval_sec = atoi(argv[0]);
Harald Welte28fd2362024-03-02 11:09:58 +0100325 if (mgcp->iofd) { /* UDP MGCP socket connected */
Pau Espin Pedrol10d9f8d2023-06-26 18:49:33 +0200326 if (mgcp->actual.keepalive.req_interval_sec > 0) {
327 /* Re-schedule: */
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200328 osmo_timer_schedule(&mgcp->keepalive_tx_timer, mgcp->actual.keepalive.req_interval_sec, 0);
Pau Espin Pedrol10d9f8d2023-06-26 18:49:33 +0200329 } else {
330 if (osmo_timer_pending(&mgcp->keepalive_tx_timer))
331 osmo_timer_del(&mgcp->keepalive_tx_timer);
332 /* Assume link is UP by default, so that this MGW can be selected: */
333 mgcp->conn_up = true;
334 }
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200335 } /* else: wait until connect() to do first scheduling */
336
337 return CMD_SUCCESS;
338}
339
340DEFUN(cfg_mgw_mgw_keepalive_req_endpoint,
341 cfg_mgw_mgw_keepalive_req_endpoint_cmd,
342 "keepalive request-endpoint NAME",
343 "Monitor if the MGCP link against MGW is still usable\n"
344 "Use a given endpoint name when sending an MGCP command to the MGW for keepalive purposes\n"
345 "The name of the endpoint to use\n")
346{
347 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
348 struct mgcp_client *mgcp = get_mgcp_client(vty);
349
350 OSMO_STRLCPY_ARRAY(conf->keepalive.req_endpoint_name, argv[0]);
351
352 if (!mgcp)
353 return CMD_SUCCESS;
354
355 /* If client already exists, apply the change immediately if possible: */
356 OSMO_STRLCPY_ARRAY(mgcp->actual.keepalive.req_endpoint_name, argv[0]);
357
358 return CMD_SUCCESS;
359}
360
361DEFUN(cfg_mgw_mgw_keepalive_timeout,
362 cfg_mgw_mgw_keepalive_timeout_cmd,
363 "keepalive timeout <0-4294967295>",
364 "Monitor if the MGCP link against MGW is still usable\n"
365 "Consider the link to the MGW to be down after time without receiving any message from it\n"
366 "The timeout (s), 0 to disable\n")
367{
368 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
369 struct mgcp_client *mgcp = get_mgcp_client(vty);
370
371 conf->keepalive.timeout_sec = atoi(argv[0]);
372
373 if (!mgcp)
374 return CMD_SUCCESS;
375
376 /* If client already exists, apply the change immediately if possible: */
377 mgcp->actual.keepalive.timeout_sec = atoi(argv[0]);
Harald Welte28fd2362024-03-02 11:09:58 +0100378 if (mgcp->iofd) { /* UDP MGCP socket connected */
Pau Espin Pedrol10d9f8d2023-06-26 18:49:33 +0200379 if (mgcp->actual.keepalive.timeout_sec > 0) {
380 /* Re-schedule: */
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200381 osmo_timer_schedule(&mgcp->keepalive_rx_timer, mgcp->actual.keepalive.timeout_sec, 0);
Pau Espin Pedrol10d9f8d2023-06-26 18:49:33 +0200382 } else {
383 if (osmo_timer_pending(&mgcp->keepalive_rx_timer))
384 osmo_timer_del(&mgcp->keepalive_rx_timer);
385 /* Assume link is UP by default, so that this MGW can be selected: */
386 mgcp->conn_up = true;
387 }
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200388 } /* else: wait until connect() to do first scheduling */
389
390 return CMD_SUCCESS;
391}
392
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200393static int config_write(struct vty *vty, const char *indent, struct mgcp_client_conf *conf)
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200394{
395 const char *addr;
396 int port;
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200397 struct reset_ep *reset_ep;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200398
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200399 /* If caller doesn't the MGW pool API (mgcp_client_pool_vty_init was never called),
400 * then the "mgw" cmd prefix must be added since the old node always contained it.
401 */
402 const char *mgw_prefix = global_mgcp_client_pool ? "" : "mgw ";
403
404 if (conf->description) /* description never had "mgw" prefix even on old node: */
Philipp Maierdf9192e2021-09-03 17:50:51 +0200405 vty_out(vty, "%sdescription %s%s", indent, conf->description, VTY_NEWLINE);
406
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200407 addr = conf->local_addr;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200408 if (addr)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200409 vty_out(vty, "%s%slocal-ip %s%s", indent, mgw_prefix, addr, VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200410 port = conf->local_port;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200411 if (port >= 0)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200412 vty_out(vty, "%s%slocal-port %u%s", indent, mgw_prefix,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200413 (uint16_t)port, VTY_NEWLINE);
414
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200415 addr = conf->remote_addr;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200416 if (addr)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200417 vty_out(vty, "%s%sremote-ip %s%s", indent, mgw_prefix, addr, VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200418 port = conf->remote_port;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200419 if (port >= 0)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200420 vty_out(vty, "%s%sremote-port %u%s", indent, mgw_prefix,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200421 (uint16_t)port, VTY_NEWLINE);
422
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200423 if (conf->endpoint_domain_name[0])
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200424 vty_out(vty, "%s%sendpoint-domain %s%s", indent, mgw_prefix,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200425 conf->endpoint_domain_name, VTY_NEWLINE);
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100426
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200427 llist_for_each_entry(reset_ep, &conf->reset_epnames, list)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200428 vty_out(vty, "%s%sreset-endpoint %s%s", indent, mgw_prefix, reset_ep->name, VTY_NEWLINE);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200429
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200430 if (conf->keepalive.req_interval_sec != 0)
431 vty_out(vty, "%s%skeepalive request-interval %u%s", indent, mgw_prefix,
432 conf->keepalive.req_interval_sec, VTY_NEWLINE);
433 if (strncmp(conf->keepalive.req_endpoint_name, MGCP_CLIENT_KEEPALIVE_DEFAULT_ENDP,
434 sizeof(conf->keepalive.req_endpoint_name)) != 0)
435 vty_out(vty, "%s%skeepalive request-endpoint %s%s", indent, mgw_prefix,
436 conf->keepalive.req_endpoint_name, VTY_NEWLINE);
437 if (conf->keepalive.timeout_sec != 0)
438 vty_out(vty, "%s%skeepalive timeout %u%s", indent, mgw_prefix,
439 conf->keepalive.timeout_sec, VTY_NEWLINE);
440
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200441 return CMD_SUCCESS;
442}
443
Philipp Maierd6a7e172021-08-03 16:03:27 +0200444/*! Write out MGCP client config to VTY.
445 * \param[in] vty VTY to which we should print.
446 * \param[in] string used for indentation (e.g. " ").
447 * \returns CMD_SUCCESS on success, CMD_WARNING on error */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200448int mgcp_client_config_write(struct vty *vty, const char *indent)
449{
Pau Espin Pedrold17a9de2022-10-18 12:34:20 +0200450 /* If caller supports MGW pool API (mgcp_client_pool_vty_init was
451 * called), then skip printing any config in this node and print it when
452 * the whole 'mgw' node is printed. */
453 if (global_mgcp_client_pool)
454 return CMD_SUCCESS;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200455 return config_write(vty, indent, global_mgcp_client_conf);
456}
457
458static void vty_init_common(void *talloc_ctx, int node)
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200459{
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200460 global_mgcp_client_ctx = talloc_ctx;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200461
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200462 /* deprecated 'mgw' commands ('mgw' prepended as first arg) */
463 install_lib_element(node, &cfg_mgw_mgw_local_ip_cmd);
464 install_lib_element(node, &cfg_mgw_mgw_local_port_cmd);
465 install_lib_element(node, &cfg_mgw_mgw_remote_ip_cmd);
466 install_lib_element(node, &cfg_mgw_mgw_remote_port_cmd);
Pau Espin Pedrol2172f402022-10-19 16:13:01 +0200467 install_lib_element(node, &cfg_mgw_mgw_endpoint_range_cmd);
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200468 install_lib_element(node, &cfg_mgw_mgw_endpoint_domain_name_cmd);
469 install_lib_element(node, &cfg_mgw_mgw_reset_ep_name_cmd);
470 install_lib_element(node, &cfg_mgw_mgw_no_reset_ep_name_cmd);
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200471 install_lib_element(node, &cfg_mgw_mgw_keepalive_req_interval_cmd);
472 install_lib_element(node, &cfg_mgw_mgw_keepalive_req_endpoint_cmd);
473 install_lib_element(node, &cfg_mgw_mgw_keepalive_timeout_cmd);
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100474
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200475 osmo_fsm_vty_add_cmds();
476}
477
Philipp Maierd6a7e172021-08-03 16:03:27 +0200478/*! Set up MGCP client VTY
479 * (called once at startup by the application process).
480 * \param[in] talloc_ctx talloc context to be used by the VTY for allocating memory.
481 * \param[in] node identifier of the node on which the VTY commands should be installed.
482 * \param[in] conf user provided memory to to store the MGCP client configuration data. */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200483void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf)
484{
485 global_mgcp_client_conf = conf;
486
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100487 /* deprecated 'mgcpgw' commands */
Vadim Yanitskiy3ba40952020-10-04 16:42:04 +0700488 install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);
489 install_lib_element(node, &cfg_mgcpgw_local_port_cmd);
490 install_lib_element(node, &cfg_mgcpgw_remote_ip_cmd);
491 install_lib_element(node, &cfg_mgcpgw_remote_port_cmd);
492 install_lib_element(node, &cfg_mgcpgw_endpoint_range_cmd);
493 install_lib_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
Stefan Sperling29248252018-02-22 18:09:28 +0100494
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200495 vty_init_common(talloc_ctx, node);
496}
497
Pau Espin Pedrol3a914e32022-10-19 17:13:20 +0200498/* Mark whether user called mgcp_client_pool_config_write() and hence support new API */
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200499static bool mgcp_client_pool_config_write_called = false;
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200500
Pau Espin Pedrol3a914e32022-10-19 17:13:20 +0200501static int _mgcp_client_pool_config_write(struct vty *vty, const char *indent)
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200502{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200503 struct mgcp_client_pool *pool = global_mgcp_client_pool;
504 struct mgcp_client_pool_member *pool_member;
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200505 unsigned int subindent_buf_len;
506 char *subindent;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200507
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200508 if (!indent)
509 indent = pool->vty_indent ? : "";
510 subindent_buf_len = strlen(indent) + 1 + 1;
511 subindent = talloc_zero_size(vty, subindent_buf_len);
512
513 snprintf(subindent, subindent_buf_len, "%s ", indent);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200514
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200515 llist_for_each_entry(pool_member, &pool->member_list, list) {
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200516 vty_out(vty, "%smgw %u%s", indent, pool_member->nr, VTY_NEWLINE);
517 config_write(vty, subindent, &pool_member->conf);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200518 }
519
Pau Espin Pedrold17a9de2022-10-18 12:34:20 +0200520 /* MGW pool API is supported by user (global_mgcp_client_pool is set
521 * because mgcp_client_pool_vty_init was called). If single MGW was
522 * configured through old VTY and no mgw in the new MGW pool VTY is
523 * replacing it, then output the single MGW converted to the new MGW
524 * pool VTY. */
525 if (llist_empty(&pool->member_list) && pool->mgcp_client_single) {
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200526 vty_out(vty, "%smgw 0%s", indent, VTY_NEWLINE);
527 config_write(vty, subindent, global_mgcp_client_conf);
Pau Espin Pedrold17a9de2022-10-18 12:34:20 +0200528 }
529
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200530 talloc_free(subindent);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200531 return CMD_SUCCESS;
532}
533
Pau Espin Pedrol3a914e32022-10-19 17:13:20 +0200534/* Deprecated, used for backward compatibility with older users which didn't call
535 * mgcp_client_pool_config_write(): */
536static int config_write_pool(struct vty *vty)
537{
538 if (mgcp_client_pool_config_write_called)
539 return CMD_SUCCESS;
540
541 return _mgcp_client_pool_config_write(vty, NULL);
542}
543
544/*! Write out MGCP client config to VTY.
545 * \param[in] vty VTY to which we should print.
546 * \param[in] indent string used for indentation (e.g. " ").
547 If NULL, indentation passed during mgcp_client_pool_vty_init() will be used.
548 * \returns CMD_SUCCESS on success, CMD_WARNING on error */
549int mgcp_client_pool_config_write(struct vty *vty, const char *indent)
550{
551 /* Tell internal node write function that the user supports calling proper API: */
552 mgcp_client_pool_config_write_called = true;
553 return _mgcp_client_pool_config_write(vty, indent);
554}
555
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200556DEFUN_ATTR(cfg_mgw,
Philipp Maierd55be052021-08-19 14:58:31 +0200557 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 +0200558{
559 int nr = atoi(argv[0]);
560 struct mgcp_client_pool_member *pool_member;
561
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200562 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200563 if (!pool_member) {
Pau Espin Pedrol6ddc79b2022-10-13 17:03:42 +0200564 pool_member = mgcp_client_pool_member_alloc(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200565 OSMO_ASSERT(pool_member);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200566 }
567
568 vty->index = &pool_member->conf;
Philipp Maierdf9192e2021-09-03 17:50:51 +0200569 vty->index_sub = &pool_member->conf.description;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200570 vty->node = global_mgcp_client_pool->vty_node->node;
571
572 return CMD_SUCCESS;
573}
574
575DEFUN_ATTR(cfg_no_mgw,
576 cfg_no_mgw_cmd,
Philipp Maier74e83d32021-08-20 09:57:27 +0200577 "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 +0200578{
579 int nr = atoi(argv[0]);
580 struct mgcp_client_pool_member *pool_member;
581
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200582 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200583 if (!pool_member) {
584 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
585 return CMD_WARNING;
586 }
587
588 /* Make sure that there are no ongoing calls */
589 if (pool_member->refcount > 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200590 vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't remove it now!%s",
591 mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200592 return CMD_WARNING;
593 }
594
Pau Espin Pedrol6ddc79b2022-10-13 17:03:42 +0200595 mgcp_client_pool_member_free(pool_member);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200596
597 return CMD_SUCCESS;
598}
599
600DEFUN_ATTR(mgw_reconnect, mgw_reconnect_cmd,
601 "mgw <0-255> reconnect",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200602 MGW_STR "reference number\n" "reconfigure and reconnect MGCP client\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200603{
604 int nr = atoi(argv[0]);
605 struct mgcp_client_pool_member *pool_member = NULL;
606
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200607 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200608 if (!pool_member) {
609 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
610 return CMD_WARNING;
611 }
612
613 /* Make sure that there are no ongoing calls */
614 if (pool_member->refcount > 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200615 vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't reconnect it now!%s",
616 mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200617 return CMD_WARNING;
618 }
619
Pau Espin Pedrol35bd2522022-10-13 17:26:33 +0200620 if (mgcp_client_pool_member_reinit_client(pool_member) < 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200621 LOGP(DLMGCP, LOGL_ERROR, "(manual) MGW %s connect failed at (%s:%u)\n",
622 mgcp_client_pool_member_name(pool_member), pool_member->conf.remote_addr,
623 pool_member->conf.remote_port);
Philipp Maierdf9192e2021-09-03 17:50:51 +0200624 vty_out(vty, "%% MGCP client (MGW %s) initalization failed ('%s')%s",
625 mgcp_client_pool_member_name(pool_member), argv[0], VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200626 return CMD_WARNING;
627 }
628
629 return CMD_SUCCESS;
630}
631
632DEFUN_ATTR(mgw_block, mgw_block_cmd,
633 "mgw <0-255> block",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200634 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 +0200635{
636 int nr = atoi(argv[0]);
637 struct mgcp_client_pool_member *pool_member = NULL;
638
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200639 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200640 if (!pool_member) {
641 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
642 return CMD_WARNING;
643 }
644
645 pool_member->blocked = true;
646 return CMD_SUCCESS;
647}
648
649DEFUN_ATTR(mgw_unblock, mgw_unblock_cmd,
650 "mgw <0-255> unblock",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200651 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 +0200652{
653 int nr = atoi(argv[0]);
654 struct mgcp_client_pool_member *pool_member = NULL;
655
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200656 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200657 if (!pool_member) {
658 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
659 return CMD_WARNING;
660 }
661
662 pool_member->blocked = false;
663 return CMD_SUCCESS;
664}
665
Pau Espin Pedrola6917fe2022-10-13 14:40:56 +0200666DEFUN(mgw_show, mgw_show_cmd, "show mgw-pool", SHOW_STR "Display information about the MGW-Pool\n")
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200667{
668 vty_out(vty, "%% MGW-Pool:%s", VTY_NEWLINE);
669 struct mgcp_client_pool_member *pool_member;
670
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200671 if (llist_empty(&global_mgcp_client_pool->member_list) && global_mgcp_client_pool->mgcp_client_single) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200672 vty_out(vty, "%% (pool is empty, single MGCP client will be used)%s", VTY_NEWLINE);
673 return CMD_SUCCESS;
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200674 } else if (llist_empty(&global_mgcp_client_pool->member_list)) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200675 vty_out(vty, "%% (pool is empty)%s", VTY_NEWLINE);
676 return CMD_SUCCESS;
677 }
678
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200679 llist_for_each_entry(pool_member, &global_mgcp_client_pool->member_list, list) {
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200680 const struct mgcp_client *cli = pool_member->client;
Philipp Maierdf9192e2021-09-03 17:50:51 +0200681 vty_out(vty, "%% MGW %s%s", mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200682 vty_out(vty, "%% MGCP link: %s,%s%s",
Harald Welte28fd2362024-03-02 11:09:58 +0100683 cli && cli->iofd ? "connected" : "disconnected",
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200684 cli && cli->conn_up ?
685 ((cli->actual.keepalive.timeout_sec > 0) ? "UP" : "MAYBE") :
686 "DOWN",
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200687 VTY_NEWLINE);
688 vty_out(vty, "%% service: %s%s", pool_member->blocked ? "blocked" : "unblocked", VTY_NEWLINE);
689 vty_out(vty, "%% ongoing calls: %u%s", pool_member->refcount, VTY_NEWLINE);
690 }
691 return CMD_SUCCESS;
692}
693
694/*! Set up MGCP client VTY (pooled)
695 * (called once at startup by the application process).
696 * \param[in] parent_node identifier of the parent node on which the mgw node appears.
697 * \param[in] mgw_node identifier that should be used with the newly installed MGW node.
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200698 * \param[in] indent indentation string to match the indentation in the VTY config.
699 If NULL, it must be passed explicitly each time mgcp_client_pool_config_write() is called.
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200700 * \param[in] pool user provided memory to store the configured MGCP client (MGW) pool. */
701void mgcp_client_pool_vty_init(int parent_node, int mgw_node, const char *indent, struct mgcp_client_pool *pool)
702{
Philipp Maierda3a5752021-08-19 14:24:14 +0200703 /* A pool must be allocated before this function can be called */
704 OSMO_ASSERT(pool);
705
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200706 /* Never allow this function to be called twice on the same pool */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200707 OSMO_ASSERT(!pool->vty_node);
708
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200709 if (indent) {
710 pool->vty_indent = talloc_strdup(pool, indent);
711 OSMO_ASSERT(pool->vty_indent);
712 }
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200713 pool->vty_node = talloc_zero(pool, struct cmd_node);
714 OSMO_ASSERT(pool->vty_node);
715 pool->vty_node->node = mgw_node;
716 pool->vty_node->vtysh = 1;
717 pool->vty_node->prompt = talloc_strdup(pool->vty_node, "%s(config-mgw)# ");
718
719 install_lib_element(parent_node, &cfg_mgw_cmd);
720 install_lib_element(parent_node, &cfg_no_mgw_cmd);
721
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200722 /* Note: config_write_pool is deprecated and user is expected to
723 * manually call mgcp_client_pool_config_write() when printing the VTY
724 * config */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200725 install_node(pool->vty_node, config_write_pool);
726 vty_init_common(pool, mgw_node);
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200727 install_lib_element(mgw_node, &cfg_mgw_local_ip_cmd);
728 install_lib_element(mgw_node, &cfg_mgw_local_port_cmd);
729 install_lib_element(mgw_node, &cfg_mgw_remote_ip_cmd);
730 install_lib_element(mgw_node, &cfg_mgw_remote_port_cmd);
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200731 install_lib_element(mgw_node, &cfg_mgw_rtp_bts_base_port_cmd);
732 install_lib_element(mgw_node, &cfg_mgw_endpoint_domain_name_cmd);
733 install_lib_element(mgw_node, &cfg_mgw_reset_ep_name_cmd);
734 install_lib_element(mgw_node, &cfg_mgw_no_reset_ep_name_cmd);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200735
Philipp Maierdf9192e2021-09-03 17:50:51 +0200736 install_element(mgw_node, &cfg_description_cmd);
737
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200738 install_lib_element(ENABLE_NODE, &mgw_reconnect_cmd);
739 install_lib_element(ENABLE_NODE, &mgw_block_cmd);
740 install_lib_element(ENABLE_NODE, &mgw_unblock_cmd);
741
Pau Espin Pedrola6917fe2022-10-13 14:40:56 +0200742 install_lib_element_ve(&mgw_show_cmd);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200743
744 global_mgcp_client_pool = pool;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200745}