blob: a1646377b676386ccec826bb80776538ba526579 [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]);
325 if (mgcp->wq.bfd.fd != -1) { /* UDP MGCP socket connected */
326 if (mgcp->actual.keepalive.req_interval_sec > 0) /* Re-schedule: */
327 osmo_timer_schedule(&mgcp->keepalive_tx_timer, mgcp->actual.keepalive.req_interval_sec, 0);
328 else if (osmo_timer_pending(&mgcp->keepalive_tx_timer))
329 osmo_timer_del(&mgcp->keepalive_tx_timer);
330 } /* else: wait until connect() to do first scheduling */
331
332 return CMD_SUCCESS;
333}
334
335DEFUN(cfg_mgw_mgw_keepalive_req_endpoint,
336 cfg_mgw_mgw_keepalive_req_endpoint_cmd,
337 "keepalive request-endpoint NAME",
338 "Monitor if the MGCP link against MGW is still usable\n"
339 "Use a given endpoint name when sending an MGCP command to the MGW for keepalive purposes\n"
340 "The name of the endpoint to use\n")
341{
342 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
343 struct mgcp_client *mgcp = get_mgcp_client(vty);
344
345 OSMO_STRLCPY_ARRAY(conf->keepalive.req_endpoint_name, argv[0]);
346
347 if (!mgcp)
348 return CMD_SUCCESS;
349
350 /* If client already exists, apply the change immediately if possible: */
351 OSMO_STRLCPY_ARRAY(mgcp->actual.keepalive.req_endpoint_name, argv[0]);
352
353 return CMD_SUCCESS;
354}
355
356DEFUN(cfg_mgw_mgw_keepalive_timeout,
357 cfg_mgw_mgw_keepalive_timeout_cmd,
358 "keepalive timeout <0-4294967295>",
359 "Monitor if the MGCP link against MGW is still usable\n"
360 "Consider the link to the MGW to be down after time without receiving any message from it\n"
361 "The timeout (s), 0 to disable\n")
362{
363 struct mgcp_client_conf *conf = get_mgcp_client_config(vty);
364 struct mgcp_client *mgcp = get_mgcp_client(vty);
365
366 conf->keepalive.timeout_sec = atoi(argv[0]);
367
368 if (!mgcp)
369 return CMD_SUCCESS;
370
371 /* If client already exists, apply the change immediately if possible: */
372 mgcp->actual.keepalive.timeout_sec = atoi(argv[0]);
373 if (mgcp->wq.bfd.fd != -1) { /* UDP MGCP socket connected */
374 if (mgcp->actual.keepalive.timeout_sec > 0) /* Re-schedule: */
375 osmo_timer_schedule(&mgcp->keepalive_rx_timer, mgcp->actual.keepalive.timeout_sec, 0);
376 else if (osmo_timer_pending(&mgcp->keepalive_rx_timer))
377 osmo_timer_del(&mgcp->keepalive_rx_timer);
378 } /* else: wait until connect() to do first scheduling */
379
380 return CMD_SUCCESS;
381}
382
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200383static int config_write(struct vty *vty, const char *indent, struct mgcp_client_conf *conf)
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200384{
385 const char *addr;
386 int port;
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200387 struct reset_ep *reset_ep;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200388
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200389 /* If caller doesn't the MGW pool API (mgcp_client_pool_vty_init was never called),
390 * then the "mgw" cmd prefix must be added since the old node always contained it.
391 */
392 const char *mgw_prefix = global_mgcp_client_pool ? "" : "mgw ";
393
394 if (conf->description) /* description never had "mgw" prefix even on old node: */
Philipp Maierdf9192e2021-09-03 17:50:51 +0200395 vty_out(vty, "%sdescription %s%s", indent, conf->description, VTY_NEWLINE);
396
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200397 addr = conf->local_addr;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200398 if (addr)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200399 vty_out(vty, "%s%slocal-ip %s%s", indent, mgw_prefix, addr, VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200400 port = conf->local_port;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200401 if (port >= 0)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200402 vty_out(vty, "%s%slocal-port %u%s", indent, mgw_prefix,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200403 (uint16_t)port, VTY_NEWLINE);
404
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200405 addr = conf->remote_addr;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200406 if (addr)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200407 vty_out(vty, "%s%sremote-ip %s%s", indent, mgw_prefix, addr, VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200408 port = conf->remote_port;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200409 if (port >= 0)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200410 vty_out(vty, "%s%sremote-port %u%s", indent, mgw_prefix,
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200411 (uint16_t)port, VTY_NEWLINE);
412
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200413 if (conf->endpoint_domain_name[0])
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200414 vty_out(vty, "%s%sendpoint-domain %s%s", indent, mgw_prefix,
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200415 conf->endpoint_domain_name, VTY_NEWLINE);
Neels Hofmeyrac69ea92018-12-19 00:27:50 +0100416
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200417 llist_for_each_entry(reset_ep, &conf->reset_epnames, list)
Pau Espin Pedrol103e50a2022-10-19 17:22:46 +0200418 vty_out(vty, "%s%sreset-endpoint %s%s", indent, mgw_prefix, reset_ep->name, VTY_NEWLINE);
Philipp Maier3f2c15f2021-07-22 11:53:07 +0200419
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200420 if (conf->keepalive.req_interval_sec != 0)
421 vty_out(vty, "%s%skeepalive request-interval %u%s", indent, mgw_prefix,
422 conf->keepalive.req_interval_sec, VTY_NEWLINE);
423 if (strncmp(conf->keepalive.req_endpoint_name, MGCP_CLIENT_KEEPALIVE_DEFAULT_ENDP,
424 sizeof(conf->keepalive.req_endpoint_name)) != 0)
425 vty_out(vty, "%s%skeepalive request-endpoint %s%s", indent, mgw_prefix,
426 conf->keepalive.req_endpoint_name, VTY_NEWLINE);
427 if (conf->keepalive.timeout_sec != 0)
428 vty_out(vty, "%s%skeepalive timeout %u%s", indent, mgw_prefix,
429 conf->keepalive.timeout_sec, VTY_NEWLINE);
430
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200431 return CMD_SUCCESS;
432}
433
Philipp Maierd6a7e172021-08-03 16:03:27 +0200434/*! Write out MGCP client config to VTY.
435 * \param[in] vty VTY to which we should print.
436 * \param[in] string used for indentation (e.g. " ").
437 * \returns CMD_SUCCESS on success, CMD_WARNING on error */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200438int mgcp_client_config_write(struct vty *vty, const char *indent)
439{
Pau Espin Pedrold17a9de2022-10-18 12:34:20 +0200440 /* If caller supports MGW pool API (mgcp_client_pool_vty_init was
441 * called), then skip printing any config in this node and print it when
442 * the whole 'mgw' node is printed. */
443 if (global_mgcp_client_pool)
444 return CMD_SUCCESS;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200445 return config_write(vty, indent, global_mgcp_client_conf);
446}
447
448static void vty_init_common(void *talloc_ctx, int node)
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200449{
Neels Hofmeyr3a8e7232017-09-04 01:02:56 +0200450 global_mgcp_client_ctx = talloc_ctx;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200451
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200452 /* deprecated 'mgw' commands ('mgw' prepended as first arg) */
453 install_lib_element(node, &cfg_mgw_mgw_local_ip_cmd);
454 install_lib_element(node, &cfg_mgw_mgw_local_port_cmd);
455 install_lib_element(node, &cfg_mgw_mgw_remote_ip_cmd);
456 install_lib_element(node, &cfg_mgw_mgw_remote_port_cmd);
Pau Espin Pedrol2172f402022-10-19 16:13:01 +0200457 install_lib_element(node, &cfg_mgw_mgw_endpoint_range_cmd);
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200458 install_lib_element(node, &cfg_mgw_mgw_endpoint_domain_name_cmd);
459 install_lib_element(node, &cfg_mgw_mgw_reset_ep_name_cmd);
460 install_lib_element(node, &cfg_mgw_mgw_no_reset_ep_name_cmd);
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200461 install_lib_element(node, &cfg_mgw_mgw_keepalive_req_interval_cmd);
462 install_lib_element(node, &cfg_mgw_mgw_keepalive_req_endpoint_cmd);
463 install_lib_element(node, &cfg_mgw_mgw_keepalive_timeout_cmd);
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100464
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200465 osmo_fsm_vty_add_cmds();
466}
467
Philipp Maierd6a7e172021-08-03 16:03:27 +0200468/*! Set up MGCP client VTY
469 * (called once at startup by the application process).
470 * \param[in] talloc_ctx talloc context to be used by the VTY for allocating memory.
471 * \param[in] node identifier of the node on which the VTY commands should be installed.
472 * \param[in] conf user provided memory to to store the MGCP client configuration data. */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200473void mgcp_client_vty_init(void *talloc_ctx, int node, struct mgcp_client_conf *conf)
474{
475 global_mgcp_client_conf = conf;
476
Neels Hofmeyr87203f22017-10-31 01:15:45 +0100477 /* deprecated 'mgcpgw' commands */
Vadim Yanitskiy3ba40952020-10-04 16:42:04 +0700478 install_lib_element(node, &cfg_mgcpgw_local_ip_cmd);
479 install_lib_element(node, &cfg_mgcpgw_local_port_cmd);
480 install_lib_element(node, &cfg_mgcpgw_remote_ip_cmd);
481 install_lib_element(node, &cfg_mgcpgw_remote_port_cmd);
482 install_lib_element(node, &cfg_mgcpgw_endpoint_range_cmd);
483 install_lib_element(node, &cfg_mgcpgw_rtp_bts_base_port_cmd);
Stefan Sperling29248252018-02-22 18:09:28 +0100484
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200485 vty_init_common(talloc_ctx, node);
486}
487
Pau Espin Pedrol3a914e32022-10-19 17:13:20 +0200488/* Mark whether user called mgcp_client_pool_config_write() and hence support new API */
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200489static bool mgcp_client_pool_config_write_called = false;
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200490
Pau Espin Pedrol3a914e32022-10-19 17:13:20 +0200491static int _mgcp_client_pool_config_write(struct vty *vty, const char *indent)
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200492{
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200493 struct mgcp_client_pool *pool = global_mgcp_client_pool;
494 struct mgcp_client_pool_member *pool_member;
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200495 unsigned int subindent_buf_len;
496 char *subindent;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200497
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200498 if (!indent)
499 indent = pool->vty_indent ? : "";
500 subindent_buf_len = strlen(indent) + 1 + 1;
501 subindent = talloc_zero_size(vty, subindent_buf_len);
502
503 snprintf(subindent, subindent_buf_len, "%s ", indent);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200504
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200505 llist_for_each_entry(pool_member, &pool->member_list, list) {
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200506 vty_out(vty, "%smgw %u%s", indent, pool_member->nr, VTY_NEWLINE);
507 config_write(vty, subindent, &pool_member->conf);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200508 }
509
Pau Espin Pedrold17a9de2022-10-18 12:34:20 +0200510 /* MGW pool API is supported by user (global_mgcp_client_pool is set
511 * because mgcp_client_pool_vty_init was called). If single MGW was
512 * configured through old VTY and no mgw in the new MGW pool VTY is
513 * replacing it, then output the single MGW converted to the new MGW
514 * pool VTY. */
515 if (llist_empty(&pool->member_list) && pool->mgcp_client_single) {
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200516 vty_out(vty, "%smgw 0%s", indent, VTY_NEWLINE);
517 config_write(vty, subindent, global_mgcp_client_conf);
Pau Espin Pedrold17a9de2022-10-18 12:34:20 +0200518 }
519
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200520 talloc_free(subindent);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200521 return CMD_SUCCESS;
522}
523
Pau Espin Pedrol3a914e32022-10-19 17:13:20 +0200524/* Deprecated, used for backward compatibility with older users which didn't call
525 * mgcp_client_pool_config_write(): */
526static int config_write_pool(struct vty *vty)
527{
528 if (mgcp_client_pool_config_write_called)
529 return CMD_SUCCESS;
530
531 return _mgcp_client_pool_config_write(vty, NULL);
532}
533
534/*! Write out MGCP client config to VTY.
535 * \param[in] vty VTY to which we should print.
536 * \param[in] indent string used for indentation (e.g. " ").
537 If NULL, indentation passed during mgcp_client_pool_vty_init() will be used.
538 * \returns CMD_SUCCESS on success, CMD_WARNING on error */
539int mgcp_client_pool_config_write(struct vty *vty, const char *indent)
540{
541 /* Tell internal node write function that the user supports calling proper API: */
542 mgcp_client_pool_config_write_called = true;
543 return _mgcp_client_pool_config_write(vty, indent);
544}
545
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200546DEFUN_ATTR(cfg_mgw,
Philipp Maierd55be052021-08-19 14:58:31 +0200547 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 +0200548{
549 int nr = atoi(argv[0]);
550 struct mgcp_client_pool_member *pool_member;
551
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200552 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200553 if (!pool_member) {
Pau Espin Pedrol6ddc79b2022-10-13 17:03:42 +0200554 pool_member = mgcp_client_pool_member_alloc(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200555 OSMO_ASSERT(pool_member);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200556 }
557
558 vty->index = &pool_member->conf;
Philipp Maierdf9192e2021-09-03 17:50:51 +0200559 vty->index_sub = &pool_member->conf.description;
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200560 vty->node = global_mgcp_client_pool->vty_node->node;
561
562 return CMD_SUCCESS;
563}
564
565DEFUN_ATTR(cfg_no_mgw,
566 cfg_no_mgw_cmd,
Philipp Maier74e83d32021-08-20 09:57:27 +0200567 "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 +0200568{
569 int nr = atoi(argv[0]);
570 struct mgcp_client_pool_member *pool_member;
571
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200572 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200573 if (!pool_member) {
574 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
575 return CMD_WARNING;
576 }
577
578 /* Make sure that there are no ongoing calls */
579 if (pool_member->refcount > 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200580 vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't remove it now!%s",
581 mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200582 return CMD_WARNING;
583 }
584
Pau Espin Pedrol6ddc79b2022-10-13 17:03:42 +0200585 mgcp_client_pool_member_free(pool_member);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200586
587 return CMD_SUCCESS;
588}
589
590DEFUN_ATTR(mgw_reconnect, mgw_reconnect_cmd,
591 "mgw <0-255> reconnect",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200592 MGW_STR "reference number\n" "reconfigure and reconnect MGCP client\n", CMD_ATTR_IMMEDIATE)
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200593{
594 int nr = atoi(argv[0]);
595 struct mgcp_client_pool_member *pool_member = NULL;
596
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200597 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200598 if (!pool_member) {
599 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
600 return CMD_WARNING;
601 }
602
603 /* Make sure that there are no ongoing calls */
604 if (pool_member->refcount > 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200605 vty_out(vty, "%% MGCP client (MGW %s) is still serving ongoing calls -- can't reconnect it now!%s",
606 mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200607 return CMD_WARNING;
608 }
609
Pau Espin Pedrol35bd2522022-10-13 17:26:33 +0200610 if (mgcp_client_pool_member_reinit_client(pool_member) < 0) {
Philipp Maierdf9192e2021-09-03 17:50:51 +0200611 LOGP(DLMGCP, LOGL_ERROR, "(manual) MGW %s connect failed at (%s:%u)\n",
612 mgcp_client_pool_member_name(pool_member), pool_member->conf.remote_addr,
613 pool_member->conf.remote_port);
Philipp Maierdf9192e2021-09-03 17:50:51 +0200614 vty_out(vty, "%% MGCP client (MGW %s) initalization failed ('%s')%s",
615 mgcp_client_pool_member_name(pool_member), argv[0], VTY_NEWLINE);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200616 return CMD_WARNING;
617 }
618
619 return CMD_SUCCESS;
620}
621
622DEFUN_ATTR(mgw_block, mgw_block_cmd,
623 "mgw <0-255> block",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200624 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 +0200625{
626 int nr = atoi(argv[0]);
627 struct mgcp_client_pool_member *pool_member = NULL;
628
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200629 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200630 if (!pool_member) {
631 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
632 return CMD_WARNING;
633 }
634
635 pool_member->blocked = true;
636 return CMD_SUCCESS;
637}
638
639DEFUN_ATTR(mgw_unblock, mgw_unblock_cmd,
640 "mgw <0-255> unblock",
Philipp Maier8f91a7f2021-08-19 14:55:56 +0200641 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 +0200642{
643 int nr = atoi(argv[0]);
644 struct mgcp_client_pool_member *pool_member = NULL;
645
Pau Espin Pedrolff592152022-10-13 16:46:25 +0200646 pool_member = mgcp_client_pool_find_member_by_nr(global_mgcp_client_pool, nr);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200647 if (!pool_member) {
648 vty_out(vty, "%% no such MGCP client configured ('%s')%s", argv[0], VTY_NEWLINE);
649 return CMD_WARNING;
650 }
651
652 pool_member->blocked = false;
653 return CMD_SUCCESS;
654}
655
Pau Espin Pedrola6917fe2022-10-13 14:40:56 +0200656DEFUN(mgw_show, mgw_show_cmd, "show mgw-pool", SHOW_STR "Display information about the MGW-Pool\n")
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200657{
658 vty_out(vty, "%% MGW-Pool:%s", VTY_NEWLINE);
659 struct mgcp_client_pool_member *pool_member;
660
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200661 if (llist_empty(&global_mgcp_client_pool->member_list) && global_mgcp_client_pool->mgcp_client_single) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200662 vty_out(vty, "%% (pool is empty, single MGCP client will be used)%s", VTY_NEWLINE);
663 return CMD_SUCCESS;
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200664 } else if (llist_empty(&global_mgcp_client_pool->member_list)) {
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200665 vty_out(vty, "%% (pool is empty)%s", VTY_NEWLINE);
666 return CMD_SUCCESS;
667 }
668
Pau Espin Pedrold4ad77d2022-10-13 16:37:12 +0200669 llist_for_each_entry(pool_member, &global_mgcp_client_pool->member_list, list) {
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200670 const struct mgcp_client *cli = pool_member->client;
Philipp Maierdf9192e2021-09-03 17:50:51 +0200671 vty_out(vty, "%% MGW %s%s", mgcp_client_pool_member_name(pool_member), VTY_NEWLINE);
Pau Espin Pedrol563386e2023-06-14 12:20:49 +0200672 vty_out(vty, "%% MGCP link: %s,%s%s",
673 cli && cli->wq.bfd.fd != -1 ? "connected" : "disconnected",
674 cli && cli->conn_up ?
675 ((cli->actual.keepalive.timeout_sec > 0) ? "UP" : "MAYBE") :
676 "DOWN",
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200677 VTY_NEWLINE);
678 vty_out(vty, "%% service: %s%s", pool_member->blocked ? "blocked" : "unblocked", VTY_NEWLINE);
679 vty_out(vty, "%% ongoing calls: %u%s", pool_member->refcount, VTY_NEWLINE);
680 }
681 return CMD_SUCCESS;
682}
683
684/*! Set up MGCP client VTY (pooled)
685 * (called once at startup by the application process).
686 * \param[in] parent_node identifier of the parent node on which the mgw node appears.
687 * \param[in] mgw_node identifier that should be used with the newly installed MGW node.
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200688 * \param[in] indent indentation string to match the indentation in the VTY config.
689 If NULL, it must be passed explicitly each time mgcp_client_pool_config_write() is called.
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200690 * \param[in] pool user provided memory to store the configured MGCP client (MGW) pool. */
691void mgcp_client_pool_vty_init(int parent_node, int mgw_node, const char *indent, struct mgcp_client_pool *pool)
692{
Philipp Maierda3a5752021-08-19 14:24:14 +0200693 /* A pool must be allocated before this function can be called */
694 OSMO_ASSERT(pool);
695
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200696 /* Never allow this function to be called twice on the same pool */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200697 OSMO_ASSERT(!pool->vty_node);
698
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200699 if (indent) {
700 pool->vty_indent = talloc_strdup(pool, indent);
701 OSMO_ASSERT(pool->vty_indent);
702 }
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200703 pool->vty_node = talloc_zero(pool, struct cmd_node);
704 OSMO_ASSERT(pool->vty_node);
705 pool->vty_node->node = mgw_node;
706 pool->vty_node->vtysh = 1;
707 pool->vty_node->prompt = talloc_strdup(pool->vty_node, "%s(config-mgw)# ");
708
709 install_lib_element(parent_node, &cfg_mgw_cmd);
710 install_lib_element(parent_node, &cfg_no_mgw_cmd);
711
Pau Espin Pedrol7881f7d2022-10-18 14:13:04 +0200712 /* Note: config_write_pool is deprecated and user is expected to
713 * manually call mgcp_client_pool_config_write() when printing the VTY
714 * config */
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200715 install_node(pool->vty_node, config_write_pool);
716 vty_init_common(pool, mgw_node);
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200717 install_lib_element(mgw_node, &cfg_mgw_local_ip_cmd);
718 install_lib_element(mgw_node, &cfg_mgw_local_port_cmd);
719 install_lib_element(mgw_node, &cfg_mgw_remote_ip_cmd);
720 install_lib_element(mgw_node, &cfg_mgw_remote_port_cmd);
Pau Espin Pedrol8c138fe2022-10-19 12:47:31 +0200721 install_lib_element(mgw_node, &cfg_mgw_rtp_bts_base_port_cmd);
722 install_lib_element(mgw_node, &cfg_mgw_endpoint_domain_name_cmd);
723 install_lib_element(mgw_node, &cfg_mgw_reset_ep_name_cmd);
724 install_lib_element(mgw_node, &cfg_mgw_no_reset_ep_name_cmd);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200725
Philipp Maierdf9192e2021-09-03 17:50:51 +0200726 install_element(mgw_node, &cfg_description_cmd);
727
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200728 install_lib_element(ENABLE_NODE, &mgw_reconnect_cmd);
729 install_lib_element(ENABLE_NODE, &mgw_block_cmd);
730 install_lib_element(ENABLE_NODE, &mgw_unblock_cmd);
731
Pau Espin Pedrola6917fe2022-10-13 14:40:56 +0200732 install_lib_element_ve(&mgw_show_cmd);
Philipp Maier3f4a4cb2021-07-26 13:20:05 +0200733
734 global_mgcp_client_pool = pool;
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200735}