blob: ef63b044e516670bde419ad7d28b7ae45f51f18e [file] [log] [blame]
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The protocol implementation */
3
4/*
5 * (C) 2009-2014 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2011 by On-Waves
7 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020024#include <osmocom/core/talloc.h>
Stefan Sperling1e174872018-10-25 18:36:10 +020025#include <osmocom/vty/misc.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020026#include <osmocom/mgcp/mgcp.h>
Neels Hofmeyr67793542017-09-08 04:25:16 +020027#include <osmocom/mgcp/mgcp_common.h>
Philipp Maier87bd9be2017-08-22 16:35:41 +020028#include <osmocom/mgcp/mgcp_internal.h>
29#include <osmocom/mgcp/vty.h>
30#include <osmocom/mgcp/mgcp_conn.h>
Philipp Maier37d11c82018-02-01 14:38:12 +010031#include <osmocom/mgcp/mgcp_endp.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020032
33#include <string.h>
Philipp Maierbca0ef62018-07-09 17:20:51 +020034#include <inttypes.h>
Stefan Sperling12086582018-06-26 15:26:28 +020035#include <limits.h>
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020036
37#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
38#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
39#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
40
41static struct mgcp_config *g_cfg = NULL;
42
43static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
44{
45 struct mgcp_trunk_config *trunk;
46
47 if (nr == 0)
48 trunk = &cfg->trunk;
49 else
50 trunk = mgcp_trunk_num(cfg, nr);
51
52 return trunk;
53}
54
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020055struct cmd_node mgcp_node = {
56 MGCP_NODE,
57 "%s(config-mgcp)# ",
58 1,
59};
60
61struct cmd_node trunk_node = {
62 TRUNK_NODE,
63 "%s(config-mgcp-trunk)# ",
64 1,
65};
66
67static int config_write_mgcp(struct vty *vty)
68{
69 vty_out(vty, "mgcp%s", VTY_NEWLINE);
Philipp Maier12943ea2018-01-17 15:40:25 +010070 vty_out(vty, " domain %s%s", g_cfg->domain, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020071 if (g_cfg->local_ip)
72 vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020073 vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
74 vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
Philipp Maierf1889d82017-11-08 14:59:39 +010075 vty_out(vty, " rtp port-range %u %u%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +020076 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end,
77 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020078 if (g_cfg->net_ports.bind_addr)
Philipp Maierf1889d82017-11-08 14:59:39 +010079 vty_out(vty, " rtp bind-ip %s%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +020080 g_cfg->net_ports.bind_addr, VTY_NEWLINE);
Philipp Maier1cb1e382017-11-02 17:16:04 +010081 if (g_cfg->net_ports.bind_addr_probe)
82 vty_out(vty, " rtp ip-probing%s", VTY_NEWLINE);
83 else
84 vty_out(vty, " no rtp ip-probing%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020085 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
86 if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE)
87 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
88 else if (g_cfg->trunk.keepalive_interval)
89 vty_out(vty, " rtp keep-alive %d%s",
90 g_cfg->trunk.keepalive_interval, VTY_NEWLINE);
91 else
92 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
93
94 if (g_cfg->trunk.omit_rtcp)
95 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
96 else
97 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +020098 if (g_cfg->trunk.force_constant_ssrc
99 || g_cfg->trunk.force_aligned_timing) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200100 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200101 g_cfg->trunk.force_constant_ssrc ? "" : "no ",
102 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200103 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200104 g_cfg->trunk.force_aligned_timing ? "" : "no ",
105 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200106 } else
107 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
108 if (g_cfg->trunk.audio_payload != -1)
109 vty_out(vty, " sdp audio-payload number %d%s",
110 g_cfg->trunk.audio_payload, VTY_NEWLINE);
111 if (g_cfg->trunk.audio_name)
112 vty_out(vty, " sdp audio-payload name %s%s",
113 g_cfg->trunk.audio_name, VTY_NEWLINE);
114 if (g_cfg->trunk.audio_fmtp_extra)
115 vty_out(vty, " sdp audio fmtp-extra %s%s",
116 g_cfg->trunk.audio_fmtp_extra, VTY_NEWLINE);
117 vty_out(vty, " %ssdp audio-payload send-ptime%s",
118 g_cfg->trunk.audio_send_ptime ? "" : "no ", VTY_NEWLINE);
119 vty_out(vty, " %ssdp audio-payload send-name%s",
120 g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200121 vty_out(vty, " loop %u%s", ! !g_cfg->trunk.audio_loop, VTY_NEWLINE);
122 vty_out(vty, " number endpoints %u%s",
Philipp Maierfcd06552017-11-10 17:32:22 +0100123 g_cfg->trunk.vty_number_endpoints - 1, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200124 vty_out(vty, " %sallow-transcoding%s",
125 g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE);
126 if (g_cfg->call_agent_addr)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200127 vty_out(vty, " call-agent ip %s%s", g_cfg->call_agent_addr,
128 VTY_NEWLINE);
129 if (g_cfg->force_ptime > 0)
130 vty_out(vty, " rtp force-ptime %d%s", g_cfg->force_ptime,
131 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200132
133 switch (g_cfg->osmux) {
134 case OSMUX_USAGE_ON:
135 vty_out(vty, " osmux on%s", VTY_NEWLINE);
136 break;
137 case OSMUX_USAGE_ONLY:
138 vty_out(vty, " osmux only%s", VTY_NEWLINE);
139 break;
140 case OSMUX_USAGE_OFF:
141 default:
142 vty_out(vty, " osmux off%s", VTY_NEWLINE);
143 break;
144 }
145 if (g_cfg->osmux) {
146 vty_out(vty, " osmux bind-ip %s%s",
147 g_cfg->osmux_addr, VTY_NEWLINE);
148 vty_out(vty, " osmux batch-factor %d%s",
149 g_cfg->osmux_batch, VTY_NEWLINE);
150 vty_out(vty, " osmux batch-size %u%s",
151 g_cfg->osmux_batch_size, VTY_NEWLINE);
152 vty_out(vty, " osmux port %u%s",
153 g_cfg->osmux_port, VTY_NEWLINE);
154 vty_out(vty, " osmux dummy %s%s",
155 g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
156 }
Oliver Smithe36b7752019-01-22 16:31:36 +0100157
158 if (g_cfg->conn_timeout)
159 vty_out(vty, " conn-timeout %u%s", g_cfg->conn_timeout, VTY_NEWLINE);
160
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200161 return CMD_SUCCESS;
162}
163
Philipp Maiercede2a42018-07-03 14:14:21 +0200164static void dump_rtp_end(struct vty *vty, struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200165{
Philipp Maiercede2a42018-07-03 14:14:21 +0200166 struct mgcp_rtp_state *state = &conn->state;
167 struct mgcp_rtp_end *end = &conn->end;
Philipp Maierbc0346e2018-06-07 09:52:16 +0200168 struct mgcp_rtp_codec *codec = end->codec;
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100169 struct rate_ctr *tx_packets, *tx_bytes;
170 struct rate_ctr *rx_packets, *rx_bytes;
Philipp Maiercede2a42018-07-03 14:14:21 +0200171 struct rate_ctr *dropped_packets;
172
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100173 tx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR];
174 tx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR];
175 rx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
176 rx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR];
Philipp Maiercede2a42018-07-03 14:14:21 +0200177 dropped_packets = &conn->rate_ctr_group->ctr[RTP_DROPPED_PACKETS_CTR];
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200178
179 vty_out(vty,
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100180 " Packets Sent: %" PRIu64 " (%" PRIu64 " bytes total)%s"
181 " Packets Received: %" PRIu64 " (%" PRIu64 " bytes total)%s"
Philipp Maierbca0ef62018-07-09 17:20:51 +0200182 " Timestamp Errs: %" PRIu64 "->%" PRIu64 "%s"
183 " Dropped Packets: %" PRIu64 "%s"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200184 " Payload Type: %d Rate: %u Channels: %d %s"
185 " Frame Duration: %u Frame Denominator: %u%s"
186 " FPP: %d Packet Duration: %u%s"
187 " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
188 " Output-Enabled: %d Force-PTIME: %d%s",
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100189 tx_packets->current, tx_bytes->current, VTY_NEWLINE,
190 rx_packets->current, rx_bytes->current, VTY_NEWLINE,
Philipp Maier9e1d1642018-05-09 16:26:34 +0200191 state->in_stream.err_ts_ctr->current,
192 state->out_stream.err_ts_ctr->current,
193 VTY_NEWLINE,
Philipp Maiercede2a42018-07-03 14:14:21 +0200194 dropped_packets->current, VTY_NEWLINE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200195 codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200196 codec->frame_duration_num, codec->frame_duration_den,
197 VTY_NEWLINE, end->frames_per_packet, end->packet_duration_ms,
198 VTY_NEWLINE, end->fmtp_extra, codec->audio_name,
199 codec->subtype_name, VTY_NEWLINE, end->output_enabled,
200 end->force_output_ptime, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200201}
202
Stefan Sperling12086582018-06-26 15:26:28 +0200203static void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp, int epidx,
204 int trunk_nr, enum mgcp_trunk_type trunk_type, int show_stats)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200205{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200206 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200207
Stefan Sperling12086582018-06-26 15:26:28 +0200208 vty_out(vty, "%s trunk %d endpoint %s%.2x:%s",
209 trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr,
210 trunk_type == MGCP_TRUNK_VIRTUAL ? MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK : "",
211 epidx, VTY_NEWLINE);
212
213 if (llist_empty(&endp->conns)) {
214 vty_out(vty, " No active connections%s", VTY_NEWLINE);
215 return;
216 }
217
218 llist_for_each_entry(conn, &endp->conns, entry) {
219 vty_out(vty, " CONN: %s%s", mgcp_conn_dump(conn), VTY_NEWLINE);
220
221 if (show_stats) {
Oliver Smithe36b7752019-01-22 16:31:36 +0100222 if (endp->cfg->conn_timeout) {
223 struct timeval remaining;
224 osmo_timer_remaining(&conn->watchdog, NULL, &remaining);
225 vty_out(vty, " Currently remaining timeout (seconds): %d.%06d%s",
226 (int)remaining.tv_sec, (int)remaining.tv_usec, VTY_NEWLINE);
227 }
228
Stefan Sperling12086582018-06-26 15:26:28 +0200229 /* FIXME: Also add verbosity for other
230 * connection types (E1) as soon as
231 * the implementation is available */
232 if (conn->type == MGCP_CONN_TYPE_RTP) {
233 dump_rtp_end(vty, &conn->u.rtp);
234 }
235 }
236 }
237}
238
239static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int show_stats)
240{
241 int i;
242
243 vty_out(vty, "%s trunk %d with %d endpoints:%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200244 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
245 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
246
247 if (!cfg->endpoints) {
248 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
249 return;
250 }
251
252 for (i = 1; i < cfg->number_endpoints; ++i) {
253 struct mgcp_endpoint *endp = &cfg->endpoints[i];
Stefan Sperling12086582018-06-26 15:26:28 +0200254 dump_endpoint(vty, endp, i, cfg->trunk_nr, cfg->trunk_type, show_stats);
255 if (i < cfg->number_endpoints - 1)
256 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200257 }
Stefan Sperling1e174872018-10-25 18:36:10 +0200258
259 if (show_stats && cfg->mgcp_crcx_ctr_group) {
260 vty_out(vty, " %s:%s", cfg->mgcp_crcx_ctr_group->desc->group_description, VTY_NEWLINE);
261 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_crcx_ctr_group);
262 }
Stefan Sperling8ab3fbb2018-10-30 14:57:25 +0100263 if (show_stats && cfg->mgcp_dlcx_ctr_group) {
264 vty_out(vty, " %s:%s", cfg->mgcp_dlcx_ctr_group->desc->group_description, VTY_NEWLINE);
265 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_dlcx_ctr_group);
266 }
Stefan Sperlingaa823bf2018-10-29 14:51:41 +0100267 if (show_stats && cfg->mgcp_mdcx_ctr_group) {
268 vty_out(vty, " %s:%s", cfg->mgcp_mdcx_ctr_group->desc->group_description, VTY_NEWLINE);
269 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_mdcx_ctr_group);
270 }
Stefan Sperlingba25eab2018-10-30 14:32:31 +0100271 if (show_stats && cfg->all_rtp_conn_stats) {
272 vty_out(vty, " %s:%s", cfg->all_rtp_conn_stats->desc->group_description, VTY_NEWLINE);
273 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->all_rtp_conn_stats);
274 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200275}
276
Stefan Sperling12086582018-06-26 15:26:28 +0200277#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
278
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200279DEFUN(show_mcgp, show_mgcp_cmd,
280 "show mgcp [stats]",
281 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200282 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200283 "Include Statistics\n")
284{
285 struct mgcp_trunk_config *trunk;
286 int show_stats = argc >= 1;
287
288 dump_trunk(vty, &g_cfg->trunk, show_stats);
289
290 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200291 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200292
293 if (g_cfg->osmux)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200294 vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(),
295 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200296
297 return CMD_SUCCESS;
298}
299
Stefan Sperling12086582018-06-26 15:26:28 +0200300static void
301dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk_config *trunk, const char *epname)
302{
303 const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
304 unsigned long epidx;
305 char *endp;
306 int i;
307
308 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)
309 epname += virt_prefix_len;
310 errno = 0;
311 epidx = strtoul(epname, &endp, 16);
312 if (epname[0] == '\0' || *endp != '\0') {
313 vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);
314 return;
315 }
316 if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */
317 || epidx >= trunk->number_endpoints) {
318 vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);
319 return;
320 }
321
322 for (i = 0; i < trunk->number_endpoints; ++i) {
323 struct mgcp_endpoint *endp = &trunk->endpoints[i];
324 if (i == epidx) {
325 dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);
326 break;
327 }
328 }
329}
330
331DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
332 "show mgcp endpoint NAME",
333 SHOW_STR
334 SHOW_MGCP_STR
335 "Display information about an endpoint\n" "The name of the endpoint\n")
336{
337 struct mgcp_trunk_config *trunk;
338
339 dump_mgcp_endpoint(vty, &g_cfg->trunk, argv[0]);
340 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
341 dump_mgcp_endpoint(vty, trunk, argv[0]);
342
343 return CMD_SUCCESS;
344}
345
346DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
347 "show mgcp trunk <0-64> endpoint NAME",
348 SHOW_STR
349 SHOW_MGCP_STR
350 "Display information about a trunk\n" "Trunk number\n"
351 "Display information about an endpoint\n" "The name of the endpoint\n")
352{
353 struct mgcp_trunk_config *trunk;
354 int trunkidx = atoi(argv[0]);
355
356 trunk = find_trunk(g_cfg, trunkidx);
357 if (!trunk) {
358 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
359 return CMD_WARNING;
360 }
361
362 dump_mgcp_endpoint(vty, trunk, argv[1]);
363 return CMD_SUCCESS;
364}
365
Philipp Maier87bd9be2017-08-22 16:35:41 +0200366DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200367{
368 vty->node = MGCP_NODE;
369 return CMD_SUCCESS;
370}
371
372DEFUN(cfg_mgcp_local_ip,
373 cfg_mgcp_local_ip_cmd,
374 "local ip A.B.C.D",
375 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200376 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200377{
378 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
379 return CMD_SUCCESS;
380}
381
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200382#define BIND_STR "Listen/Bind related socket option\n"
383DEFUN(cfg_mgcp_bind_ip,
384 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200385 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200386{
387 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
388 return CMD_SUCCESS;
389}
390
391DEFUN(cfg_mgcp_bind_port,
392 cfg_mgcp_bind_port_cmd,
393 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200394 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200395{
396 unsigned int port = atoi(argv[0]);
397 g_cfg->source_port = port;
398 return CMD_SUCCESS;
399}
400
401DEFUN(cfg_mgcp_bind_early,
402 cfg_mgcp_bind_early_cmd,
403 "bind early (0|1)",
404 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200405 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200406{
407 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
408 return CMD_WARNING;
409}
410
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200411#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200412#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200413#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200414#define RANGE_START_STR "Start of the range of ports\n"
415#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200416
Philipp Maierf1889d82017-11-08 14:59:39 +0100417DEFUN(cfg_mgcp_rtp_port_range,
418 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200419 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200420 RTP_STR "Range of ports to use for the NET side\n"
421 RANGE_START_STR RANGE_END_STR)
422{
Philipp Maiera19547b2018-05-22 13:44:34 +0200423 int start;
424 int end;
425
426 start = atoi(argv[0]);
427 end = atoi(argv[1]);
428
429 if (end < start) {
430 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
431 end, start, VTY_NEWLINE);
432 return CMD_WARNING;
433 }
434
435 if (start & 1) {
436 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
437 start, start & 0xFFFE, VTY_NEWLINE);
438 start &= 0xFFFE;
439 }
440
441 if ((end & 1) == 0) {
442 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
443 end, end | 1, VTY_NEWLINE);
444 end |= 1;
445 }
446
447 g_cfg->net_ports.range_start = start;
448 g_cfg->net_ports.range_end = end;
449 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
450
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200451 return CMD_SUCCESS;
452}
Philipp Maierf1889d82017-11-08 14:59:39 +0100453ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
454 cfg_mgcp_rtp_net_range_cmd,
455 "rtp net-range <0-65534> <0-65534>",
456 RTP_STR "Range of ports to use for the NET side\n"
457 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200458
Philipp Maierf1889d82017-11-08 14:59:39 +0100459DEFUN(cfg_mgcp_rtp_bind_ip,
460 cfg_mgcp_rtp_bind_ip_cmd,
461 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200462 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
463{
464 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
465 return CMD_SUCCESS;
466}
Philipp Maierf1889d82017-11-08 14:59:39 +0100467ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
468 cfg_mgcp_rtp_net_bind_ip_cmd,
469 "rtp net-bind-ip A.B.C.D",
470 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200471
Philipp Maierf1889d82017-11-08 14:59:39 +0100472DEFUN(cfg_mgcp_rtp_no_bind_ip,
473 cfg_mgcp_rtp_no_bind_ip_cmd,
474 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200475 NO_STR RTP_STR "Bind endpoints facing the Network\n"
476 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200477{
478 talloc_free(g_cfg->net_ports.bind_addr);
479 g_cfg->net_ports.bind_addr = NULL;
480 return CMD_SUCCESS;
481}
Philipp Maierf1889d82017-11-08 14:59:39 +0100482ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
483 cfg_mgcp_rtp_no_net_bind_ip_cmd,
484 "no rtp net-bind-ip",
485 NO_STR RTP_STR "Bind endpoints facing the Network\n"
486 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200487
Philipp Maier1cb1e382017-11-02 17:16:04 +0100488DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
489 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
490 "rtp ip-probing",
491 RTP_STR "automatic rtp bind ip selection\n")
492{
493 g_cfg->net_ports.bind_addr_probe = true;
494 return CMD_SUCCESS;
495}
496
497DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
498 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
499 "no rtp ip-probing",
500 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
501{
502 g_cfg->net_ports.bind_addr_probe = false;
503 return CMD_SUCCESS;
504}
505
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200506DEFUN(cfg_mgcp_rtp_ip_dscp,
507 cfg_mgcp_rtp_ip_dscp_cmd,
508 "rtp ip-dscp <0-255>",
509 RTP_STR
510 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
511{
512 int dscp = atoi(argv[0]);
513 g_cfg->endp_dscp = dscp;
514 return CMD_SUCCESS;
515}
516
517ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200518 "rtp ip-tos <0-255>",
519 RTP_STR
520 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
521#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
522 DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200523 cfg_mgcp_rtp_force_ptime_cmd,
524 "rtp force-ptime (10|20|40)",
525 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200526 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200527{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200528 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200529 return CMD_SUCCESS;
530}
531
532DEFUN(cfg_mgcp_no_rtp_force_ptime,
533 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200534 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200535{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200536 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200537 return CMD_SUCCESS;
538}
539
540DEFUN(cfg_mgcp_sdp_fmtp_extra,
541 cfg_mgcp_sdp_fmtp_extra_cmd,
542 "sdp audio fmtp-extra .NAME",
543 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
544 "Extra Information\n")
545{
546 char *txt = argv_concat(argv, argc, 0);
547 if (!txt)
548 return CMD_WARNING;
549
550 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
551 talloc_free(txt);
552 return CMD_SUCCESS;
553}
554
555DEFUN(cfg_mgcp_allow_transcoding,
556 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200557 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200558{
559 g_cfg->trunk.no_audio_transcoding = 0;
560 return CMD_SUCCESS;
561}
562
563DEFUN(cfg_mgcp_no_allow_transcoding,
564 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200565 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200566{
567 g_cfg->trunk.no_audio_transcoding = 1;
568 return CMD_SUCCESS;
569}
570
571#define SDP_STR "SDP File related options\n"
572#define AUDIO_STR "Audio payload options\n"
573DEFUN(cfg_mgcp_sdp_payload_number,
574 cfg_mgcp_sdp_payload_number_cmd,
575 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200576 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200577{
578 unsigned int payload = atoi(argv[0]);
579 g_cfg->trunk.audio_payload = payload;
580 return CMD_SUCCESS;
581}
582
Philipp Maier87bd9be2017-08-22 16:35:41 +0200583ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
584 cfg_mgcp_sdp_payload_number_cmd_old,
585 "sdp audio payload number <0-255>",
586 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200587
Philipp Maier87bd9be2017-08-22 16:35:41 +0200588 DEFUN(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200589 cfg_mgcp_sdp_payload_name_cmd,
590 "sdp audio-payload name NAME",
591 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
592{
593 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
594 return CMD_SUCCESS;
595}
596
597ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200598 "sdp audio payload name NAME",
599 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200600
Philipp Maier87bd9be2017-08-22 16:35:41 +0200601 DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200602 cfg_mgcp_sdp_payload_send_ptime_cmd,
603 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200604 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200605{
606 g_cfg->trunk.audio_send_ptime = 1;
607 return CMD_SUCCESS;
608}
609
610DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
611 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
612 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200613 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200614{
615 g_cfg->trunk.audio_send_ptime = 0;
616 return CMD_SUCCESS;
617}
618
619DEFUN(cfg_mgcp_sdp_payload_send_name,
620 cfg_mgcp_sdp_payload_send_name_cmd,
621 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200622 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200623{
624 g_cfg->trunk.audio_send_name = 1;
625 return CMD_SUCCESS;
626}
627
628DEFUN(cfg_mgcp_no_sdp_payload_send_name,
629 cfg_mgcp_no_sdp_payload_send_name_cmd,
630 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200631 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200632{
633 g_cfg->trunk.audio_send_name = 0;
634 return CMD_SUCCESS;
635}
636
637DEFUN(cfg_mgcp_loop,
638 cfg_mgcp_loop_cmd,
639 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200640 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200641{
642 if (g_cfg->osmux) {
643 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
644 return CMD_WARNING;
645 }
646 g_cfg->trunk.audio_loop = atoi(argv[0]);
647 return CMD_SUCCESS;
648}
649
650DEFUN(cfg_mgcp_force_realloc,
651 cfg_mgcp_force_realloc_cmd,
652 "force-realloc (0|1)",
653 "Force endpoint reallocation when the endpoint is still seized\n"
654 "Don't force reallocation\n" "force reallocation\n")
655{
656 g_cfg->trunk.force_realloc = atoi(argv[0]);
657 return CMD_SUCCESS;
658}
659
Philipp Maier87bd9be2017-08-22 16:35:41 +0200660DEFUN(cfg_mgcp_rtp_accept_all,
661 cfg_mgcp_rtp_accept_all_cmd,
662 "rtp-accept-all (0|1)",
663 "Accept all RTP packets, even when the originating IP/Port does not match\n"
664 "enable filter\n" "disable filter\n")
665{
666 g_cfg->trunk.rtp_accept_all = atoi(argv[0]);
667 return CMD_SUCCESS;
668}
669
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200670DEFUN(cfg_mgcp_number_endp,
671 cfg_mgcp_number_endp_cmd,
672 "number endpoints <0-65534>",
673 "Number options\n" "Endpoints available\n" "Number endpoints\n")
674{
675 /* + 1 as we start counting at one */
Philipp Maierfcd06552017-11-10 17:32:22 +0100676 g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200677 return CMD_SUCCESS;
678}
679
Philipp Maier87bd9be2017-08-22 16:35:41 +0200680DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200681{
682 g_cfg->trunk.omit_rtcp = 1;
683 return CMD_SUCCESS;
684}
685
686DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200687 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200688{
689 g_cfg->trunk.omit_rtcp = 0;
690 return CMD_SUCCESS;
691}
692
693DEFUN(cfg_mgcp_patch_rtp_ssrc,
694 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200695 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200696{
697 g_cfg->trunk.force_constant_ssrc = 1;
698 return CMD_SUCCESS;
699}
700
701DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
702 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200703 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200704{
705 g_cfg->trunk.force_constant_ssrc = 0;
706 return CMD_SUCCESS;
707}
708
709DEFUN(cfg_mgcp_patch_rtp_ts,
710 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200711 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200712{
713 g_cfg->trunk.force_aligned_timing = 1;
714 return CMD_SUCCESS;
715}
716
717DEFUN(cfg_mgcp_no_patch_rtp_ts,
718 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200719 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200720{
721 g_cfg->trunk.force_aligned_timing = 0;
722 return CMD_SUCCESS;
723}
724
725DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200726 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200727{
728 g_cfg->trunk.force_constant_ssrc = 0;
729 g_cfg->trunk.force_aligned_timing = 0;
730 return CMD_SUCCESS;
731}
732
733DEFUN(cfg_mgcp_rtp_keepalive,
734 cfg_mgcp_rtp_keepalive_cmd,
735 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200736 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200737{
738 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
739 return CMD_SUCCESS;
740}
741
742DEFUN(cfg_mgcp_rtp_keepalive_once,
743 cfg_mgcp_rtp_keepalive_once_cmd,
744 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200745 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200746{
747 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
748 return CMD_SUCCESS;
749}
750
751DEFUN(cfg_mgcp_no_rtp_keepalive,
752 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200753 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200754{
Philipp Maiere726d4f2017-11-01 10:41:34 +0100755 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200756 return CMD_SUCCESS;
757}
758
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200759#define CALL_AGENT_STR "Callagent information\n"
760DEFUN(cfg_mgcp_agent_addr,
761 cfg_mgcp_agent_addr_cmd,
762 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200763 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200764{
765 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
766 return CMD_SUCCESS;
767}
768
769ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200770 "call agent ip A.B.C.D",
771 CALL_AGENT_STR CALL_AGENT_STR IP_STR
772 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200773
Philipp Maier87bd9be2017-08-22 16:35:41 +0200774 DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
775 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200776{
777 struct mgcp_trunk_config *trunk;
778 int index = atoi(argv[0]);
779
780 trunk = mgcp_trunk_num(g_cfg, index);
781 if (!trunk)
782 trunk = mgcp_trunk_alloc(g_cfg, index);
783
784 if (!trunk) {
785 vty_out(vty, "%%Unable to allocate trunk %u.%s",
786 index, VTY_NEWLINE);
787 return CMD_WARNING;
788 }
789
790 vty->node = TRUNK_NODE;
791 vty->index = trunk;
792 return CMD_SUCCESS;
793}
794
795static int config_write_trunk(struct vty *vty)
796{
797 struct mgcp_trunk_config *trunk;
798
799 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
800 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
801 vty_out(vty, " sdp audio-payload number %d%s",
802 trunk->audio_payload, VTY_NEWLINE);
803 vty_out(vty, " sdp audio-payload name %s%s",
804 trunk->audio_name, VTY_NEWLINE);
805 vty_out(vty, " %ssdp audio-payload send-ptime%s",
806 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
807 vty_out(vty, " %ssdp audio-payload send-name%s",
808 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
809
810 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
811 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
812 else if (trunk->keepalive_interval)
813 vty_out(vty, " rtp keep-alive %d%s",
814 trunk->keepalive_interval, VTY_NEWLINE);
815 else
816 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200817 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200818 vty_out(vty, " force-realloc %d%s",
819 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200820 vty_out(vty, " rtp-accept-all %d%s",
821 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200822 if (trunk->omit_rtcp)
823 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
824 else
825 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
826 if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
827 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200828 trunk->force_constant_ssrc ? "" : "no ",
829 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200830 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200831 trunk->force_aligned_timing ? "" : "no ",
832 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200833 } else
834 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
835 if (trunk->audio_fmtp_extra)
836 vty_out(vty, " sdp audio fmtp-extra %s%s",
837 trunk->audio_fmtp_extra, VTY_NEWLINE);
838 vty_out(vty, " %sallow-transcoding%s",
839 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
840 }
841
842 return CMD_SUCCESS;
843}
844
845DEFUN(cfg_trunk_sdp_fmtp_extra,
846 cfg_trunk_sdp_fmtp_extra_cmd,
847 "sdp audio fmtp-extra .NAME",
848 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
849 "Extra Information\n")
850{
851 struct mgcp_trunk_config *trunk = vty->index;
852 char *txt = argv_concat(argv, argc, 0);
853 if (!txt)
854 return CMD_WARNING;
855
856 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
857 talloc_free(txt);
858 return CMD_SUCCESS;
859}
860
861DEFUN(cfg_trunk_payload_number,
862 cfg_trunk_payload_number_cmd,
863 "sdp audio-payload number <0-255>",
864 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
865{
866 struct mgcp_trunk_config *trunk = vty->index;
867 unsigned int payload = atoi(argv[0]);
868
869 trunk->audio_payload = payload;
870 return CMD_SUCCESS;
871}
872
873ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200874 "sdp audio payload number <0-255>",
875 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200876
Philipp Maier87bd9be2017-08-22 16:35:41 +0200877 DEFUN(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200878 cfg_trunk_payload_name_cmd,
879 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200880 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200881{
882 struct mgcp_trunk_config *trunk = vty->index;
883
884 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
885 return CMD_SUCCESS;
886}
887
888ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200889 "sdp audio payload name NAME",
890 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200891
Philipp Maier87bd9be2017-08-22 16:35:41 +0200892 DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200893 cfg_trunk_loop_cmd,
894 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200895 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200896{
897 struct mgcp_trunk_config *trunk = vty->index;
898
899 if (g_cfg->osmux) {
900 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
901 return CMD_WARNING;
902 }
903 trunk->audio_loop = atoi(argv[0]);
904 return CMD_SUCCESS;
905}
906
907DEFUN(cfg_trunk_sdp_payload_send_ptime,
908 cfg_trunk_sdp_payload_send_ptime_cmd,
909 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200910 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200911{
912 struct mgcp_trunk_config *trunk = vty->index;
913 trunk->audio_send_ptime = 1;
914 return CMD_SUCCESS;
915}
916
917DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
918 cfg_trunk_no_sdp_payload_send_ptime_cmd,
919 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200920 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200921{
922 struct mgcp_trunk_config *trunk = vty->index;
923 trunk->audio_send_ptime = 0;
924 return CMD_SUCCESS;
925}
926
927DEFUN(cfg_trunk_sdp_payload_send_name,
928 cfg_trunk_sdp_payload_send_name_cmd,
929 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200930 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200931{
932 struct mgcp_trunk_config *trunk = vty->index;
933 trunk->audio_send_name = 1;
934 return CMD_SUCCESS;
935}
936
937DEFUN(cfg_trunk_no_sdp_payload_send_name,
938 cfg_trunk_no_sdp_payload_send_name_cmd,
939 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200940 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200941{
942 struct mgcp_trunk_config *trunk = vty->index;
943 trunk->audio_send_name = 0;
944 return CMD_SUCCESS;
945}
946
Philipp Maier87bd9be2017-08-22 16:35:41 +0200947DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200948{
949 struct mgcp_trunk_config *trunk = vty->index;
950 trunk->omit_rtcp = 1;
951 return CMD_SUCCESS;
952}
953
954DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200955 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200956{
957 struct mgcp_trunk_config *trunk = vty->index;
958 trunk->omit_rtcp = 0;
959 return CMD_SUCCESS;
960}
961
962DEFUN(cfg_trunk_patch_rtp_ssrc,
963 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200964 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200965{
966 struct mgcp_trunk_config *trunk = vty->index;
967 trunk->force_constant_ssrc = 1;
968 return CMD_SUCCESS;
969}
970
971DEFUN(cfg_trunk_no_patch_rtp_ssrc,
972 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200973 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200974{
975 struct mgcp_trunk_config *trunk = vty->index;
976 trunk->force_constant_ssrc = 0;
977 return CMD_SUCCESS;
978}
979
980DEFUN(cfg_trunk_patch_rtp_ts,
981 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200982 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200983{
984 struct mgcp_trunk_config *trunk = vty->index;
985 trunk->force_aligned_timing = 1;
986 return CMD_SUCCESS;
987}
988
989DEFUN(cfg_trunk_no_patch_rtp_ts,
990 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200991 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200992{
993 struct mgcp_trunk_config *trunk = vty->index;
994 trunk->force_aligned_timing = 0;
995 return CMD_SUCCESS;
996}
997
998DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200999 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001000{
1001 struct mgcp_trunk_config *trunk = vty->index;
1002 trunk->force_constant_ssrc = 0;
1003 trunk->force_aligned_timing = 0;
1004 return CMD_SUCCESS;
1005}
1006
1007DEFUN(cfg_trunk_rtp_keepalive,
1008 cfg_trunk_rtp_keepalive_cmd,
1009 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001010 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001011{
1012 struct mgcp_trunk_config *trunk = vty->index;
1013 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
1014 return CMD_SUCCESS;
1015}
1016
1017DEFUN(cfg_trunk_rtp_keepalive_once,
1018 cfg_trunk_rtp_keepalive_once_cmd,
1019 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001020 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001021{
1022 struct mgcp_trunk_config *trunk = vty->index;
1023 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1024 return CMD_SUCCESS;
1025}
1026
1027DEFUN(cfg_trunk_no_rtp_keepalive,
1028 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001029 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001030{
1031 struct mgcp_trunk_config *trunk = vty->index;
1032 mgcp_trunk_set_keepalive(trunk, 0);
1033 return CMD_SUCCESS;
1034}
1035
1036DEFUN(cfg_trunk_allow_transcoding,
1037 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001038 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001039{
1040 struct mgcp_trunk_config *trunk = vty->index;
1041 trunk->no_audio_transcoding = 0;
1042 return CMD_SUCCESS;
1043}
1044
1045DEFUN(cfg_trunk_no_allow_transcoding,
1046 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001047 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001048{
1049 struct mgcp_trunk_config *trunk = vty->index;
1050 trunk->no_audio_transcoding = 1;
1051 return CMD_SUCCESS;
1052}
1053
Philipp Maier87bd9be2017-08-22 16:35:41 +02001054DEFUN(loop_conn,
1055 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001056 "loop-endpoint <0-64> NAME (0|1)",
1057 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001058 "The name in hex of the endpoint\n" "Disable the loop\n"
1059 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001060{
1061 struct mgcp_trunk_config *trunk;
1062 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001063 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001064
1065 trunk = find_trunk(g_cfg, atoi(argv[0]));
1066 if (!trunk) {
1067 vty_out(vty, "%%Trunk %d not found in the config.%s",
1068 atoi(argv[0]), VTY_NEWLINE);
1069 return CMD_WARNING;
1070 }
1071
1072 if (!trunk->endpoints) {
1073 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1074 trunk->trunk_nr, VTY_NEWLINE);
1075 return CMD_WARNING;
1076 }
1077
1078 int endp_no = strtoul(argv[1], NULL, 16);
1079 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1080 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001081 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001082 return CMD_WARNING;
1083 }
1084
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001085 endp = &trunk->endpoints[endp_no];
1086 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001087 llist_for_each_entry(conn, &endp->conns, entry) {
1088 if (conn->type == MGCP_CONN_TYPE_RTP)
1089 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1090 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1091 else {
1092 /* FIXME: Introduce support for other connection (E1)
1093 * types when implementation is available */
1094 vty_out(vty, "%%Can't enable SSRC patching,"
1095 "connection %s is not an RTP connection.%s",
1096 mgcp_conn_dump(conn), VTY_NEWLINE);
1097 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001098
Philipp Maier87bd9be2017-08-22 16:35:41 +02001099 if (loop)
1100 conn->mode = MGCP_CONN_LOOPBACK;
1101 else
1102 conn->mode = conn->mode_orig;
1103 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001104
1105 return CMD_SUCCESS;
1106}
1107
Philipp Maier87bd9be2017-08-22 16:35:41 +02001108DEFUN(tap_rtp,
1109 tap_rtp_cmd,
1110 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001111 "Forward data on endpoint to a different system\n" "Trunk number\n"
1112 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001113 "The connection id in hex\n"
1114 "Forward incoming data\n"
1115 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001116 "destination IP of the data\n" "destination port\n")
1117{
1118 struct mgcp_rtp_tap *tap;
1119 struct mgcp_trunk_config *trunk;
1120 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001121 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001122 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001123
1124 trunk = find_trunk(g_cfg, atoi(argv[0]));
1125 if (!trunk) {
1126 vty_out(vty, "%%Trunk %d not found in the config.%s",
1127 atoi(argv[0]), VTY_NEWLINE);
1128 return CMD_WARNING;
1129 }
1130
1131 if (!trunk->endpoints) {
1132 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1133 trunk->trunk_nr, VTY_NEWLINE);
1134 return CMD_WARNING;
1135 }
1136
1137 int endp_no = strtoul(argv[1], NULL, 16);
1138 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1139 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001140 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001141 return CMD_WARNING;
1142 }
1143
1144 endp = &trunk->endpoints[endp_no];
1145
Philipp Maier01d24a32017-11-21 17:26:09 +01001146 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001147 conn = mgcp_conn_get_rtp(endp, conn_id);
1148 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001149 vty_out(vty, "Conn ID %s is invalid.%s",
1150 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001151 return CMD_WARNING;
1152 }
1153
1154 if (strcmp(argv[3], "in") == 0)
1155 tap = &conn->tap_in;
1156 else if (strcmp(argv[3], "out") == 0)
1157 tap = &conn->tap_out;
1158 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001159 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1160 return CMD_WARNING;
1161 }
1162
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001163 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001164 inet_aton(argv[4], &tap->forward.sin_addr);
1165 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001166 tap->enabled = 1;
1167 return CMD_SUCCESS;
1168}
1169
1170DEFUN(free_endp, free_endp_cmd,
1171 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001172 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001173{
1174 struct mgcp_trunk_config *trunk;
1175 struct mgcp_endpoint *endp;
1176
1177 trunk = find_trunk(g_cfg, atoi(argv[0]));
1178 if (!trunk) {
1179 vty_out(vty, "%%Trunk %d not found in the config.%s",
1180 atoi(argv[0]), VTY_NEWLINE);
1181 return CMD_WARNING;
1182 }
1183
1184 if (!trunk->endpoints) {
1185 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1186 trunk->trunk_nr, VTY_NEWLINE);
1187 return CMD_WARNING;
1188 }
1189
1190 int endp_no = strtoul(argv[1], NULL, 16);
1191 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1192 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001193 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001194 return CMD_WARNING;
1195 }
1196
1197 endp = &trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001198 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001199 return CMD_SUCCESS;
1200}
1201
1202DEFUN(reset_endp, reset_endp_cmd,
1203 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001204 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001205{
1206 struct mgcp_trunk_config *trunk;
1207 struct mgcp_endpoint *endp;
1208 int endp_no, rc;
1209
1210 trunk = find_trunk(g_cfg, atoi(argv[0]));
1211 if (!trunk) {
1212 vty_out(vty, "%%Trunk %d not found in the config.%s",
1213 atoi(argv[0]), VTY_NEWLINE);
1214 return CMD_WARNING;
1215 }
1216
1217 if (!trunk->endpoints) {
1218 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1219 trunk->trunk_nr, VTY_NEWLINE);
1220 return CMD_WARNING;
1221 }
1222
1223 endp_no = strtoul(argv[1], NULL, 16);
1224 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1225 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001226 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001227 return CMD_WARNING;
1228 }
1229
1230 endp = &trunk->endpoints[endp_no];
1231 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1232 if (rc < 0) {
1233 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1234 return CMD_WARNING;
1235 }
1236 return CMD_SUCCESS;
1237}
1238
1239DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001240 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001241{
1242 int rc;
1243
1244 rc = mgcp_send_reset_all(g_cfg);
1245 if (rc < 0) {
1246 vty_out(vty, "Error %d during endpoint reset.%s",
1247 rc, VTY_NEWLINE);
1248 return CMD_WARNING;
1249 }
1250 return CMD_SUCCESS;
1251}
1252
1253#define OSMUX_STR "RTP multiplexing\n"
1254DEFUN(cfg_mgcp_osmux,
1255 cfg_mgcp_osmux_cmd,
1256 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001257 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001258{
1259 if (strcmp(argv[0], "off") == 0) {
1260 g_cfg->osmux = OSMUX_USAGE_OFF;
1261 return CMD_SUCCESS;
1262 }
1263
Philipp Maier87bd9be2017-08-22 16:35:41 +02001264 /* Since OSMUX support is not finished, we do not
1265 * allow to turn it on yet. */
1266 vty_out(vty, "OSMUX currently unavailable in this software version.%s", VTY_NEWLINE);
1267 return CMD_WARNING;
Philipp Maier2982e422017-11-07 12:27:48 +01001268#if 0
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001269 if (strcmp(argv[0], "on") == 0)
1270 g_cfg->osmux = OSMUX_USAGE_ON;
1271 else if (strcmp(argv[0], "only") == 0)
1272 g_cfg->osmux = OSMUX_USAGE_ONLY;
1273
1274 if (g_cfg->trunk.audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001275 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001276 return CMD_WARNING;
1277 }
1278
1279 return CMD_SUCCESS;
Philipp Maier2982e422017-11-07 12:27:48 +01001280#endif
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001281}
1282
1283DEFUN(cfg_mgcp_osmux_ip,
1284 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001285 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001286{
1287 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1288 return CMD_SUCCESS;
1289}
1290
1291DEFUN(cfg_mgcp_osmux_batch_factor,
1292 cfg_mgcp_osmux_batch_factor_cmd,
1293 "osmux batch-factor <1-8>",
1294 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1295{
1296 g_cfg->osmux_batch = atoi(argv[0]);
1297 return CMD_SUCCESS;
1298}
1299
1300DEFUN(cfg_mgcp_osmux_batch_size,
1301 cfg_mgcp_osmux_batch_size_cmd,
1302 "osmux batch-size <1-65535>",
1303 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1304{
1305 g_cfg->osmux_batch_size = atoi(argv[0]);
1306 return CMD_SUCCESS;
1307}
1308
1309DEFUN(cfg_mgcp_osmux_port,
1310 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001311 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001312{
1313 g_cfg->osmux_port = atoi(argv[0]);
1314 return CMD_SUCCESS;
1315}
1316
1317DEFUN(cfg_mgcp_osmux_dummy,
1318 cfg_mgcp_osmux_dummy_cmd,
1319 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001320 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1321 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001322{
1323 if (strcmp(argv[0], "on") == 0)
1324 g_cfg->osmux_dummy = 1;
1325 else if (strcmp(argv[0], "off") == 0)
1326 g_cfg->osmux_dummy = 0;
1327
1328 return CMD_SUCCESS;
1329}
1330
Philipp Maier12943ea2018-01-17 15:40:25 +01001331DEFUN(cfg_mgcp_domain,
1332 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001333 "domain NAME",
1334 "Set the domain part expected in MGCP messages' endpoint names\n"
1335 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001336{
1337 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1338 return CMD_SUCCESS;
1339}
1340
Oliver Smithe36b7752019-01-22 16:31:36 +01001341DEFUN(cfg_mgcp_conn_timeout,
1342 cfg_mgcp_conn_timeout_cmd,
1343 "conn-timeout <1-65534>",
1344 "Set a time after which inactive connections (CIs) are closed. This can be used to work around interoperability"
1345 " problems causing connections to stay open forever, and slowly exhausting all available ports. Do not enable"
1346 " when LCLS is used (connections in LCLS state appear to be inactive)!\n"
1347 "Timeout value (sec.)\n")
1348{
1349 g_cfg->conn_timeout = strtoul(argv[0], NULL, 10);
1350 return CMD_SUCCESS;
1351}
1352
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001353int mgcp_vty_init(void)
1354{
1355 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001356 install_element_ve(&show_mgcp_endpoint_cmd);
1357 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001358 install_element(ENABLE_NODE, &loop_conn_cmd);
1359 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001360 install_element(ENABLE_NODE, &free_endp_cmd);
1361 install_element(ENABLE_NODE, &reset_endp_cmd);
1362 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1363
1364 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1365 install_node(&mgcp_node, config_write_mgcp);
1366
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001367 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001368 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1369 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1370 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001371 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001372 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001373 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001374 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001375 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001376 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001377 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1378 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001379 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1380 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1381 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1382 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1383 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1384 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1385 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1386 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1387 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001388 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1389 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1390 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1391 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1392 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1393 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001394 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001395 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1396 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1397 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1398 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1399 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1400 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1401 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1402 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
1403 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1404 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1405 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1406 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1407 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1408 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1409 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1410 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1411 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1412 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1413 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1414 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1415 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001416 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Oliver Smithe36b7752019-01-22 16:31:36 +01001417 install_element(MGCP_NODE, &cfg_mgcp_conn_timeout_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001418
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001419 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1420 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001421 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1422 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1423 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1424 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1425 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1426 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1427 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1428 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1429 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1430 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1431 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1432 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1433 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
1434 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1435 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1436 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1437 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1438 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1439 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1440 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1441 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1442 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1443
1444 return 0;
1445}
1446
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001447int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1448 enum mgcp_role role)
1449{
1450 int rc;
1451 struct mgcp_trunk_config *trunk;
1452
1453 cfg->osmux_port = OSMUX_PORT;
1454 cfg->osmux_batch = 4;
1455 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1456
1457 g_cfg = cfg;
1458 rc = vty_read_config_file(config_file, NULL);
1459 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001460 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1461 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001462 return rc;
1463 }
1464
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001465 if (!g_cfg->source_addr) {
1466 fprintf(stderr, "You need to specify a bind address.\n");
1467 return -1;
1468 }
1469
Philipp Maier48454982017-11-10 16:46:41 +01001470 if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001471 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001472 "Failed to initialize the virtual trunk (%d endpoints)\n",
1473 g_cfg->trunk.number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001474 return -1;
1475 }
1476
1477 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maier48454982017-11-10 16:46:41 +01001478 if (mgcp_endpoints_allocate(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001479 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001480 "Failed to initialize trunk %d (%d endpoints)\n",
1481 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001482 return -1;
1483 }
1484 }
1485 cfg->role = role;
1486
1487 return 0;
1488}