blob: 83f845a15f6b0dcbdfc7a773b3f72657c62450ce [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 }
157 return CMD_SUCCESS;
158}
159
Philipp Maiercede2a42018-07-03 14:14:21 +0200160static void dump_rtp_end(struct vty *vty, struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200161{
Philipp Maiercede2a42018-07-03 14:14:21 +0200162 struct mgcp_rtp_state *state = &conn->state;
163 struct mgcp_rtp_end *end = &conn->end;
Philipp Maierbc0346e2018-06-07 09:52:16 +0200164 struct mgcp_rtp_codec *codec = end->codec;
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100165 struct rate_ctr *tx_packets, *tx_bytes;
166 struct rate_ctr *rx_packets, *rx_bytes;
Philipp Maiercede2a42018-07-03 14:14:21 +0200167 struct rate_ctr *dropped_packets;
168
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100169 tx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR];
170 tx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR];
171 rx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
172 rx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR];
Philipp Maiercede2a42018-07-03 14:14:21 +0200173 dropped_packets = &conn->rate_ctr_group->ctr[RTP_DROPPED_PACKETS_CTR];
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200174
175 vty_out(vty,
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100176 " Packets Sent: %" PRIu64 " (%" PRIu64 " bytes total)%s"
177 " Packets Received: %" PRIu64 " (%" PRIu64 " bytes total)%s"
Philipp Maierbca0ef62018-07-09 17:20:51 +0200178 " Timestamp Errs: %" PRIu64 "->%" PRIu64 "%s"
179 " Dropped Packets: %" PRIu64 "%s"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200180 " Payload Type: %d Rate: %u Channels: %d %s"
181 " Frame Duration: %u Frame Denominator: %u%s"
182 " FPP: %d Packet Duration: %u%s"
183 " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
184 " Output-Enabled: %d Force-PTIME: %d%s",
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100185 tx_packets->current, tx_bytes->current, VTY_NEWLINE,
186 rx_packets->current, rx_bytes->current, VTY_NEWLINE,
Philipp Maier9e1d1642018-05-09 16:26:34 +0200187 state->in_stream.err_ts_ctr->current,
188 state->out_stream.err_ts_ctr->current,
189 VTY_NEWLINE,
Philipp Maiercede2a42018-07-03 14:14:21 +0200190 dropped_packets->current, VTY_NEWLINE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200191 codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200192 codec->frame_duration_num, codec->frame_duration_den,
193 VTY_NEWLINE, end->frames_per_packet, end->packet_duration_ms,
194 VTY_NEWLINE, end->fmtp_extra, codec->audio_name,
195 codec->subtype_name, VTY_NEWLINE, end->output_enabled,
196 end->force_output_ptime, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200197}
198
Stefan Sperling12086582018-06-26 15:26:28 +0200199static void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp, int epidx,
200 int trunk_nr, enum mgcp_trunk_type trunk_type, int show_stats)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200201{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200202 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200203
Stefan Sperling12086582018-06-26 15:26:28 +0200204 vty_out(vty, "%s trunk %d endpoint %s%.2x:%s",
205 trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr,
206 trunk_type == MGCP_TRUNK_VIRTUAL ? MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK : "",
207 epidx, VTY_NEWLINE);
208
209 if (llist_empty(&endp->conns)) {
210 vty_out(vty, " No active connections%s", VTY_NEWLINE);
211 return;
212 }
213
214 llist_for_each_entry(conn, &endp->conns, entry) {
215 vty_out(vty, " CONN: %s%s", mgcp_conn_dump(conn), VTY_NEWLINE);
216
217 if (show_stats) {
218 /* FIXME: Also add verbosity for other
219 * connection types (E1) as soon as
220 * the implementation is available */
221 if (conn->type == MGCP_CONN_TYPE_RTP) {
222 dump_rtp_end(vty, &conn->u.rtp);
223 }
224 }
225 }
226}
227
228static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int show_stats)
229{
230 int i;
231
232 vty_out(vty, "%s trunk %d with %d endpoints:%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200233 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
234 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
235
236 if (!cfg->endpoints) {
237 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
238 return;
239 }
240
241 for (i = 1; i < cfg->number_endpoints; ++i) {
242 struct mgcp_endpoint *endp = &cfg->endpoints[i];
Stefan Sperling12086582018-06-26 15:26:28 +0200243 dump_endpoint(vty, endp, i, cfg->trunk_nr, cfg->trunk_type, show_stats);
244 if (i < cfg->number_endpoints - 1)
245 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200246 }
Stefan Sperling1e174872018-10-25 18:36:10 +0200247
248 if (show_stats && cfg->mgcp_crcx_ctr_group) {
249 vty_out(vty, " %s:%s", cfg->mgcp_crcx_ctr_group->desc->group_description, VTY_NEWLINE);
250 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_crcx_ctr_group);
251 }
Stefan Sperling8ab3fbb2018-10-30 14:57:25 +0100252 if (show_stats && cfg->mgcp_dlcx_ctr_group) {
253 vty_out(vty, " %s:%s", cfg->mgcp_dlcx_ctr_group->desc->group_description, VTY_NEWLINE);
254 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_dlcx_ctr_group);
255 }
Stefan Sperlingaa823bf2018-10-29 14:51:41 +0100256 if (show_stats && cfg->mgcp_mdcx_ctr_group) {
257 vty_out(vty, " %s:%s", cfg->mgcp_mdcx_ctr_group->desc->group_description, VTY_NEWLINE);
258 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_mdcx_ctr_group);
259 }
Stefan Sperlingba25eab2018-10-30 14:32:31 +0100260 if (show_stats && cfg->all_rtp_conn_stats) {
261 vty_out(vty, " %s:%s", cfg->all_rtp_conn_stats->desc->group_description, VTY_NEWLINE);
262 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->all_rtp_conn_stats);
263 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200264}
265
Stefan Sperling12086582018-06-26 15:26:28 +0200266#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
267
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200268DEFUN(show_mcgp, show_mgcp_cmd,
269 "show mgcp [stats]",
270 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200271 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200272 "Include Statistics\n")
273{
274 struct mgcp_trunk_config *trunk;
275 int show_stats = argc >= 1;
276
277 dump_trunk(vty, &g_cfg->trunk, show_stats);
278
279 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200280 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200281
282 if (g_cfg->osmux)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200283 vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(),
284 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200285
286 return CMD_SUCCESS;
287}
288
Stefan Sperling12086582018-06-26 15:26:28 +0200289static void
290dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk_config *trunk, const char *epname)
291{
292 const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
293 unsigned long epidx;
294 char *endp;
295 int i;
296
297 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)
298 epname += virt_prefix_len;
299 errno = 0;
300 epidx = strtoul(epname, &endp, 16);
301 if (epname[0] == '\0' || *endp != '\0') {
302 vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);
303 return;
304 }
305 if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */
306 || epidx >= trunk->number_endpoints) {
307 vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);
308 return;
309 }
310
311 for (i = 0; i < trunk->number_endpoints; ++i) {
312 struct mgcp_endpoint *endp = &trunk->endpoints[i];
313 if (i == epidx) {
314 dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);
315 break;
316 }
317 }
318}
319
320DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
321 "show mgcp endpoint NAME",
322 SHOW_STR
323 SHOW_MGCP_STR
324 "Display information about an endpoint\n" "The name of the endpoint\n")
325{
326 struct mgcp_trunk_config *trunk;
327
328 dump_mgcp_endpoint(vty, &g_cfg->trunk, argv[0]);
329 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
330 dump_mgcp_endpoint(vty, trunk, argv[0]);
331
332 return CMD_SUCCESS;
333}
334
335DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
336 "show mgcp trunk <0-64> endpoint NAME",
337 SHOW_STR
338 SHOW_MGCP_STR
339 "Display information about a trunk\n" "Trunk number\n"
340 "Display information about an endpoint\n" "The name of the endpoint\n")
341{
342 struct mgcp_trunk_config *trunk;
343 int trunkidx = atoi(argv[0]);
344
345 trunk = find_trunk(g_cfg, trunkidx);
346 if (!trunk) {
347 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
348 return CMD_WARNING;
349 }
350
351 dump_mgcp_endpoint(vty, trunk, argv[1]);
352 return CMD_SUCCESS;
353}
354
Philipp Maier87bd9be2017-08-22 16:35:41 +0200355DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200356{
357 vty->node = MGCP_NODE;
358 return CMD_SUCCESS;
359}
360
361DEFUN(cfg_mgcp_local_ip,
362 cfg_mgcp_local_ip_cmd,
363 "local ip A.B.C.D",
364 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200365 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200366{
367 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
368 return CMD_SUCCESS;
369}
370
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200371#define BIND_STR "Listen/Bind related socket option\n"
372DEFUN(cfg_mgcp_bind_ip,
373 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200374 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200375{
376 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
377 return CMD_SUCCESS;
378}
379
380DEFUN(cfg_mgcp_bind_port,
381 cfg_mgcp_bind_port_cmd,
382 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200383 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200384{
385 unsigned int port = atoi(argv[0]);
386 g_cfg->source_port = port;
387 return CMD_SUCCESS;
388}
389
390DEFUN(cfg_mgcp_bind_early,
391 cfg_mgcp_bind_early_cmd,
392 "bind early (0|1)",
393 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200394 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200395{
396 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
397 return CMD_WARNING;
398}
399
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200400#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200401#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200402#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200403#define RANGE_START_STR "Start of the range of ports\n"
404#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200405
Philipp Maierf1889d82017-11-08 14:59:39 +0100406DEFUN(cfg_mgcp_rtp_port_range,
407 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200408 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200409 RTP_STR "Range of ports to use for the NET side\n"
410 RANGE_START_STR RANGE_END_STR)
411{
Philipp Maiera19547b2018-05-22 13:44:34 +0200412 int start;
413 int end;
414
415 start = atoi(argv[0]);
416 end = atoi(argv[1]);
417
418 if (end < start) {
419 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
420 end, start, VTY_NEWLINE);
421 return CMD_WARNING;
422 }
423
424 if (start & 1) {
425 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
426 start, start & 0xFFFE, VTY_NEWLINE);
427 start &= 0xFFFE;
428 }
429
430 if ((end & 1) == 0) {
431 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
432 end, end | 1, VTY_NEWLINE);
433 end |= 1;
434 }
435
436 g_cfg->net_ports.range_start = start;
437 g_cfg->net_ports.range_end = end;
438 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
439
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200440 return CMD_SUCCESS;
441}
Philipp Maierf1889d82017-11-08 14:59:39 +0100442ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
443 cfg_mgcp_rtp_net_range_cmd,
444 "rtp net-range <0-65534> <0-65534>",
445 RTP_STR "Range of ports to use for the NET side\n"
446 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200447
Philipp Maierf1889d82017-11-08 14:59:39 +0100448DEFUN(cfg_mgcp_rtp_bind_ip,
449 cfg_mgcp_rtp_bind_ip_cmd,
450 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200451 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
452{
453 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
454 return CMD_SUCCESS;
455}
Philipp Maierf1889d82017-11-08 14:59:39 +0100456ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
457 cfg_mgcp_rtp_net_bind_ip_cmd,
458 "rtp net-bind-ip A.B.C.D",
459 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200460
Philipp Maierf1889d82017-11-08 14:59:39 +0100461DEFUN(cfg_mgcp_rtp_no_bind_ip,
462 cfg_mgcp_rtp_no_bind_ip_cmd,
463 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200464 NO_STR RTP_STR "Bind endpoints facing the Network\n"
465 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200466{
467 talloc_free(g_cfg->net_ports.bind_addr);
468 g_cfg->net_ports.bind_addr = NULL;
469 return CMD_SUCCESS;
470}
Philipp Maierf1889d82017-11-08 14:59:39 +0100471ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
472 cfg_mgcp_rtp_no_net_bind_ip_cmd,
473 "no rtp net-bind-ip",
474 NO_STR RTP_STR "Bind endpoints facing the Network\n"
475 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200476
Philipp Maier1cb1e382017-11-02 17:16:04 +0100477DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
478 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
479 "rtp ip-probing",
480 RTP_STR "automatic rtp bind ip selection\n")
481{
482 g_cfg->net_ports.bind_addr_probe = true;
483 return CMD_SUCCESS;
484}
485
486DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
487 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
488 "no rtp ip-probing",
489 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
490{
491 g_cfg->net_ports.bind_addr_probe = false;
492 return CMD_SUCCESS;
493}
494
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200495DEFUN(cfg_mgcp_rtp_ip_dscp,
496 cfg_mgcp_rtp_ip_dscp_cmd,
497 "rtp ip-dscp <0-255>",
498 RTP_STR
499 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
500{
501 int dscp = atoi(argv[0]);
502 g_cfg->endp_dscp = dscp;
503 return CMD_SUCCESS;
504}
505
506ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200507 "rtp ip-tos <0-255>",
508 RTP_STR
509 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
510#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
511 DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200512 cfg_mgcp_rtp_force_ptime_cmd,
513 "rtp force-ptime (10|20|40)",
514 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200515 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200516{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200517 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200518 return CMD_SUCCESS;
519}
520
521DEFUN(cfg_mgcp_no_rtp_force_ptime,
522 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200523 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200524{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200525 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200526 return CMD_SUCCESS;
527}
528
529DEFUN(cfg_mgcp_sdp_fmtp_extra,
530 cfg_mgcp_sdp_fmtp_extra_cmd,
531 "sdp audio fmtp-extra .NAME",
532 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
533 "Extra Information\n")
534{
535 char *txt = argv_concat(argv, argc, 0);
536 if (!txt)
537 return CMD_WARNING;
538
539 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
540 talloc_free(txt);
541 return CMD_SUCCESS;
542}
543
544DEFUN(cfg_mgcp_allow_transcoding,
545 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200546 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200547{
548 g_cfg->trunk.no_audio_transcoding = 0;
549 return CMD_SUCCESS;
550}
551
552DEFUN(cfg_mgcp_no_allow_transcoding,
553 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200554 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200555{
556 g_cfg->trunk.no_audio_transcoding = 1;
557 return CMD_SUCCESS;
558}
559
560#define SDP_STR "SDP File related options\n"
561#define AUDIO_STR "Audio payload options\n"
562DEFUN(cfg_mgcp_sdp_payload_number,
563 cfg_mgcp_sdp_payload_number_cmd,
564 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200565 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200566{
567 unsigned int payload = atoi(argv[0]);
568 g_cfg->trunk.audio_payload = payload;
569 return CMD_SUCCESS;
570}
571
Philipp Maier87bd9be2017-08-22 16:35:41 +0200572ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
573 cfg_mgcp_sdp_payload_number_cmd_old,
574 "sdp audio payload number <0-255>",
575 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200576
Philipp Maier87bd9be2017-08-22 16:35:41 +0200577 DEFUN(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200578 cfg_mgcp_sdp_payload_name_cmd,
579 "sdp audio-payload name NAME",
580 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
581{
582 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
583 return CMD_SUCCESS;
584}
585
586ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200587 "sdp audio payload name NAME",
588 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200589
Philipp Maier87bd9be2017-08-22 16:35:41 +0200590 DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200591 cfg_mgcp_sdp_payload_send_ptime_cmd,
592 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200593 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200594{
595 g_cfg->trunk.audio_send_ptime = 1;
596 return CMD_SUCCESS;
597}
598
599DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
600 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
601 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200602 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200603{
604 g_cfg->trunk.audio_send_ptime = 0;
605 return CMD_SUCCESS;
606}
607
608DEFUN(cfg_mgcp_sdp_payload_send_name,
609 cfg_mgcp_sdp_payload_send_name_cmd,
610 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200611 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200612{
613 g_cfg->trunk.audio_send_name = 1;
614 return CMD_SUCCESS;
615}
616
617DEFUN(cfg_mgcp_no_sdp_payload_send_name,
618 cfg_mgcp_no_sdp_payload_send_name_cmd,
619 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200620 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200621{
622 g_cfg->trunk.audio_send_name = 0;
623 return CMD_SUCCESS;
624}
625
626DEFUN(cfg_mgcp_loop,
627 cfg_mgcp_loop_cmd,
628 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200629 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200630{
631 if (g_cfg->osmux) {
632 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
633 return CMD_WARNING;
634 }
635 g_cfg->trunk.audio_loop = atoi(argv[0]);
636 return CMD_SUCCESS;
637}
638
639DEFUN(cfg_mgcp_force_realloc,
640 cfg_mgcp_force_realloc_cmd,
641 "force-realloc (0|1)",
642 "Force endpoint reallocation when the endpoint is still seized\n"
643 "Don't force reallocation\n" "force reallocation\n")
644{
645 g_cfg->trunk.force_realloc = atoi(argv[0]);
646 return CMD_SUCCESS;
647}
648
Philipp Maier87bd9be2017-08-22 16:35:41 +0200649DEFUN(cfg_mgcp_rtp_accept_all,
650 cfg_mgcp_rtp_accept_all_cmd,
651 "rtp-accept-all (0|1)",
652 "Accept all RTP packets, even when the originating IP/Port does not match\n"
653 "enable filter\n" "disable filter\n")
654{
655 g_cfg->trunk.rtp_accept_all = atoi(argv[0]);
656 return CMD_SUCCESS;
657}
658
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200659DEFUN(cfg_mgcp_number_endp,
660 cfg_mgcp_number_endp_cmd,
661 "number endpoints <0-65534>",
662 "Number options\n" "Endpoints available\n" "Number endpoints\n")
663{
664 /* + 1 as we start counting at one */
Philipp Maierfcd06552017-11-10 17:32:22 +0100665 g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200666 return CMD_SUCCESS;
667}
668
Philipp Maier87bd9be2017-08-22 16:35:41 +0200669DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200670{
671 g_cfg->trunk.omit_rtcp = 1;
672 return CMD_SUCCESS;
673}
674
675DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200676 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200677{
678 g_cfg->trunk.omit_rtcp = 0;
679 return CMD_SUCCESS;
680}
681
682DEFUN(cfg_mgcp_patch_rtp_ssrc,
683 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200684 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200685{
686 g_cfg->trunk.force_constant_ssrc = 1;
687 return CMD_SUCCESS;
688}
689
690DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
691 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200692 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200693{
694 g_cfg->trunk.force_constant_ssrc = 0;
695 return CMD_SUCCESS;
696}
697
698DEFUN(cfg_mgcp_patch_rtp_ts,
699 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200700 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200701{
702 g_cfg->trunk.force_aligned_timing = 1;
703 return CMD_SUCCESS;
704}
705
706DEFUN(cfg_mgcp_no_patch_rtp_ts,
707 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200708 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200709{
710 g_cfg->trunk.force_aligned_timing = 0;
711 return CMD_SUCCESS;
712}
713
714DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200715 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200716{
717 g_cfg->trunk.force_constant_ssrc = 0;
718 g_cfg->trunk.force_aligned_timing = 0;
719 return CMD_SUCCESS;
720}
721
722DEFUN(cfg_mgcp_rtp_keepalive,
723 cfg_mgcp_rtp_keepalive_cmd,
724 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200725 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200726{
727 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
728 return CMD_SUCCESS;
729}
730
731DEFUN(cfg_mgcp_rtp_keepalive_once,
732 cfg_mgcp_rtp_keepalive_once_cmd,
733 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200734 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200735{
736 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
737 return CMD_SUCCESS;
738}
739
740DEFUN(cfg_mgcp_no_rtp_keepalive,
741 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200742 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200743{
Philipp Maiere726d4f2017-11-01 10:41:34 +0100744 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200745 return CMD_SUCCESS;
746}
747
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200748#define CALL_AGENT_STR "Callagent information\n"
749DEFUN(cfg_mgcp_agent_addr,
750 cfg_mgcp_agent_addr_cmd,
751 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200752 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200753{
754 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
755 return CMD_SUCCESS;
756}
757
758ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200759 "call agent ip A.B.C.D",
760 CALL_AGENT_STR CALL_AGENT_STR IP_STR
761 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200762
Philipp Maier87bd9be2017-08-22 16:35:41 +0200763 DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
764 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200765{
766 struct mgcp_trunk_config *trunk;
767 int index = atoi(argv[0]);
768
769 trunk = mgcp_trunk_num(g_cfg, index);
770 if (!trunk)
771 trunk = mgcp_trunk_alloc(g_cfg, index);
772
773 if (!trunk) {
774 vty_out(vty, "%%Unable to allocate trunk %u.%s",
775 index, VTY_NEWLINE);
776 return CMD_WARNING;
777 }
778
779 vty->node = TRUNK_NODE;
780 vty->index = trunk;
781 return CMD_SUCCESS;
782}
783
784static int config_write_trunk(struct vty *vty)
785{
786 struct mgcp_trunk_config *trunk;
787
788 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
789 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
790 vty_out(vty, " sdp audio-payload number %d%s",
791 trunk->audio_payload, VTY_NEWLINE);
792 vty_out(vty, " sdp audio-payload name %s%s",
793 trunk->audio_name, VTY_NEWLINE);
794 vty_out(vty, " %ssdp audio-payload send-ptime%s",
795 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
796 vty_out(vty, " %ssdp audio-payload send-name%s",
797 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
798
799 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
800 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
801 else if (trunk->keepalive_interval)
802 vty_out(vty, " rtp keep-alive %d%s",
803 trunk->keepalive_interval, VTY_NEWLINE);
804 else
805 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200806 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200807 vty_out(vty, " force-realloc %d%s",
808 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200809 vty_out(vty, " rtp-accept-all %d%s",
810 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200811 if (trunk->omit_rtcp)
812 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
813 else
814 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
815 if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
816 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200817 trunk->force_constant_ssrc ? "" : "no ",
818 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200819 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200820 trunk->force_aligned_timing ? "" : "no ",
821 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200822 } else
823 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
824 if (trunk->audio_fmtp_extra)
825 vty_out(vty, " sdp audio fmtp-extra %s%s",
826 trunk->audio_fmtp_extra, VTY_NEWLINE);
827 vty_out(vty, " %sallow-transcoding%s",
828 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
829 }
830
831 return CMD_SUCCESS;
832}
833
834DEFUN(cfg_trunk_sdp_fmtp_extra,
835 cfg_trunk_sdp_fmtp_extra_cmd,
836 "sdp audio fmtp-extra .NAME",
837 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
838 "Extra Information\n")
839{
840 struct mgcp_trunk_config *trunk = vty->index;
841 char *txt = argv_concat(argv, argc, 0);
842 if (!txt)
843 return CMD_WARNING;
844
845 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
846 talloc_free(txt);
847 return CMD_SUCCESS;
848}
849
850DEFUN(cfg_trunk_payload_number,
851 cfg_trunk_payload_number_cmd,
852 "sdp audio-payload number <0-255>",
853 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
854{
855 struct mgcp_trunk_config *trunk = vty->index;
856 unsigned int payload = atoi(argv[0]);
857
858 trunk->audio_payload = payload;
859 return CMD_SUCCESS;
860}
861
862ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200863 "sdp audio payload number <0-255>",
864 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200865
Philipp Maier87bd9be2017-08-22 16:35:41 +0200866 DEFUN(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200867 cfg_trunk_payload_name_cmd,
868 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200869 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200870{
871 struct mgcp_trunk_config *trunk = vty->index;
872
873 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
874 return CMD_SUCCESS;
875}
876
877ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200878 "sdp audio payload name NAME",
879 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200880
Philipp Maier87bd9be2017-08-22 16:35:41 +0200881 DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200882 cfg_trunk_loop_cmd,
883 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200884 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200885{
886 struct mgcp_trunk_config *trunk = vty->index;
887
888 if (g_cfg->osmux) {
889 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
890 return CMD_WARNING;
891 }
892 trunk->audio_loop = atoi(argv[0]);
893 return CMD_SUCCESS;
894}
895
896DEFUN(cfg_trunk_sdp_payload_send_ptime,
897 cfg_trunk_sdp_payload_send_ptime_cmd,
898 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200899 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200900{
901 struct mgcp_trunk_config *trunk = vty->index;
902 trunk->audio_send_ptime = 1;
903 return CMD_SUCCESS;
904}
905
906DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
907 cfg_trunk_no_sdp_payload_send_ptime_cmd,
908 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200909 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200910{
911 struct mgcp_trunk_config *trunk = vty->index;
912 trunk->audio_send_ptime = 0;
913 return CMD_SUCCESS;
914}
915
916DEFUN(cfg_trunk_sdp_payload_send_name,
917 cfg_trunk_sdp_payload_send_name_cmd,
918 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200919 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200920{
921 struct mgcp_trunk_config *trunk = vty->index;
922 trunk->audio_send_name = 1;
923 return CMD_SUCCESS;
924}
925
926DEFUN(cfg_trunk_no_sdp_payload_send_name,
927 cfg_trunk_no_sdp_payload_send_name_cmd,
928 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200929 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200930{
931 struct mgcp_trunk_config *trunk = vty->index;
932 trunk->audio_send_name = 0;
933 return CMD_SUCCESS;
934}
935
Philipp Maier87bd9be2017-08-22 16:35:41 +0200936DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200937{
938 struct mgcp_trunk_config *trunk = vty->index;
939 trunk->omit_rtcp = 1;
940 return CMD_SUCCESS;
941}
942
943DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200944 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200945{
946 struct mgcp_trunk_config *trunk = vty->index;
947 trunk->omit_rtcp = 0;
948 return CMD_SUCCESS;
949}
950
951DEFUN(cfg_trunk_patch_rtp_ssrc,
952 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200953 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200954{
955 struct mgcp_trunk_config *trunk = vty->index;
956 trunk->force_constant_ssrc = 1;
957 return CMD_SUCCESS;
958}
959
960DEFUN(cfg_trunk_no_patch_rtp_ssrc,
961 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200962 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200963{
964 struct mgcp_trunk_config *trunk = vty->index;
965 trunk->force_constant_ssrc = 0;
966 return CMD_SUCCESS;
967}
968
969DEFUN(cfg_trunk_patch_rtp_ts,
970 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200971 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200972{
973 struct mgcp_trunk_config *trunk = vty->index;
974 trunk->force_aligned_timing = 1;
975 return CMD_SUCCESS;
976}
977
978DEFUN(cfg_trunk_no_patch_rtp_ts,
979 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200980 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200981{
982 struct mgcp_trunk_config *trunk = vty->index;
983 trunk->force_aligned_timing = 0;
984 return CMD_SUCCESS;
985}
986
987DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200988 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200989{
990 struct mgcp_trunk_config *trunk = vty->index;
991 trunk->force_constant_ssrc = 0;
992 trunk->force_aligned_timing = 0;
993 return CMD_SUCCESS;
994}
995
996DEFUN(cfg_trunk_rtp_keepalive,
997 cfg_trunk_rtp_keepalive_cmd,
998 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200999 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001000{
1001 struct mgcp_trunk_config *trunk = vty->index;
1002 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
1003 return CMD_SUCCESS;
1004}
1005
1006DEFUN(cfg_trunk_rtp_keepalive_once,
1007 cfg_trunk_rtp_keepalive_once_cmd,
1008 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001009 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001010{
1011 struct mgcp_trunk_config *trunk = vty->index;
1012 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1013 return CMD_SUCCESS;
1014}
1015
1016DEFUN(cfg_trunk_no_rtp_keepalive,
1017 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001018 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001019{
1020 struct mgcp_trunk_config *trunk = vty->index;
1021 mgcp_trunk_set_keepalive(trunk, 0);
1022 return CMD_SUCCESS;
1023}
1024
1025DEFUN(cfg_trunk_allow_transcoding,
1026 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001027 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001028{
1029 struct mgcp_trunk_config *trunk = vty->index;
1030 trunk->no_audio_transcoding = 0;
1031 return CMD_SUCCESS;
1032}
1033
1034DEFUN(cfg_trunk_no_allow_transcoding,
1035 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001036 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001037{
1038 struct mgcp_trunk_config *trunk = vty->index;
1039 trunk->no_audio_transcoding = 1;
1040 return CMD_SUCCESS;
1041}
1042
Philipp Maier87bd9be2017-08-22 16:35:41 +02001043DEFUN(loop_conn,
1044 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001045 "loop-endpoint <0-64> NAME (0|1)",
1046 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001047 "The name in hex of the endpoint\n" "Disable the loop\n"
1048 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001049{
1050 struct mgcp_trunk_config *trunk;
1051 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001052 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001053
1054 trunk = find_trunk(g_cfg, atoi(argv[0]));
1055 if (!trunk) {
1056 vty_out(vty, "%%Trunk %d not found in the config.%s",
1057 atoi(argv[0]), VTY_NEWLINE);
1058 return CMD_WARNING;
1059 }
1060
1061 if (!trunk->endpoints) {
1062 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1063 trunk->trunk_nr, VTY_NEWLINE);
1064 return CMD_WARNING;
1065 }
1066
1067 int endp_no = strtoul(argv[1], NULL, 16);
1068 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1069 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001070 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001071 return CMD_WARNING;
1072 }
1073
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001074 endp = &trunk->endpoints[endp_no];
1075 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001076 llist_for_each_entry(conn, &endp->conns, entry) {
1077 if (conn->type == MGCP_CONN_TYPE_RTP)
1078 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1079 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1080 else {
1081 /* FIXME: Introduce support for other connection (E1)
1082 * types when implementation is available */
1083 vty_out(vty, "%%Can't enable SSRC patching,"
1084 "connection %s is not an RTP connection.%s",
1085 mgcp_conn_dump(conn), VTY_NEWLINE);
1086 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001087
Philipp Maier87bd9be2017-08-22 16:35:41 +02001088 if (loop)
1089 conn->mode = MGCP_CONN_LOOPBACK;
1090 else
1091 conn->mode = conn->mode_orig;
1092 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001093
1094 return CMD_SUCCESS;
1095}
1096
Philipp Maier87bd9be2017-08-22 16:35:41 +02001097DEFUN(tap_rtp,
1098 tap_rtp_cmd,
1099 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001100 "Forward data on endpoint to a different system\n" "Trunk number\n"
1101 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001102 "The connection id in hex\n"
1103 "Forward incoming data\n"
1104 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001105 "destination IP of the data\n" "destination port\n")
1106{
1107 struct mgcp_rtp_tap *tap;
1108 struct mgcp_trunk_config *trunk;
1109 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001110 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001111 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001112
1113 trunk = find_trunk(g_cfg, atoi(argv[0]));
1114 if (!trunk) {
1115 vty_out(vty, "%%Trunk %d not found in the config.%s",
1116 atoi(argv[0]), VTY_NEWLINE);
1117 return CMD_WARNING;
1118 }
1119
1120 if (!trunk->endpoints) {
1121 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1122 trunk->trunk_nr, VTY_NEWLINE);
1123 return CMD_WARNING;
1124 }
1125
1126 int endp_no = strtoul(argv[1], NULL, 16);
1127 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1128 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001129 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001130 return CMD_WARNING;
1131 }
1132
1133 endp = &trunk->endpoints[endp_no];
1134
Philipp Maier01d24a32017-11-21 17:26:09 +01001135 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001136 conn = mgcp_conn_get_rtp(endp, conn_id);
1137 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001138 vty_out(vty, "Conn ID %s is invalid.%s",
1139 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001140 return CMD_WARNING;
1141 }
1142
1143 if (strcmp(argv[3], "in") == 0)
1144 tap = &conn->tap_in;
1145 else if (strcmp(argv[3], "out") == 0)
1146 tap = &conn->tap_out;
1147 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001148 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1149 return CMD_WARNING;
1150 }
1151
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001152 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001153 inet_aton(argv[4], &tap->forward.sin_addr);
1154 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001155 tap->enabled = 1;
1156 return CMD_SUCCESS;
1157}
1158
1159DEFUN(free_endp, free_endp_cmd,
1160 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001161 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001162{
1163 struct mgcp_trunk_config *trunk;
1164 struct mgcp_endpoint *endp;
1165
1166 trunk = find_trunk(g_cfg, atoi(argv[0]));
1167 if (!trunk) {
1168 vty_out(vty, "%%Trunk %d not found in the config.%s",
1169 atoi(argv[0]), VTY_NEWLINE);
1170 return CMD_WARNING;
1171 }
1172
1173 if (!trunk->endpoints) {
1174 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1175 trunk->trunk_nr, VTY_NEWLINE);
1176 return CMD_WARNING;
1177 }
1178
1179 int endp_no = strtoul(argv[1], NULL, 16);
1180 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1181 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001182 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001183 return CMD_WARNING;
1184 }
1185
1186 endp = &trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001187 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001188 return CMD_SUCCESS;
1189}
1190
1191DEFUN(reset_endp, reset_endp_cmd,
1192 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001193 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001194{
1195 struct mgcp_trunk_config *trunk;
1196 struct mgcp_endpoint *endp;
1197 int endp_no, rc;
1198
1199 trunk = find_trunk(g_cfg, atoi(argv[0]));
1200 if (!trunk) {
1201 vty_out(vty, "%%Trunk %d not found in the config.%s",
1202 atoi(argv[0]), VTY_NEWLINE);
1203 return CMD_WARNING;
1204 }
1205
1206 if (!trunk->endpoints) {
1207 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1208 trunk->trunk_nr, VTY_NEWLINE);
1209 return CMD_WARNING;
1210 }
1211
1212 endp_no = strtoul(argv[1], NULL, 16);
1213 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1214 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001215 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001216 return CMD_WARNING;
1217 }
1218
1219 endp = &trunk->endpoints[endp_no];
1220 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1221 if (rc < 0) {
1222 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1223 return CMD_WARNING;
1224 }
1225 return CMD_SUCCESS;
1226}
1227
1228DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001229 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001230{
1231 int rc;
1232
1233 rc = mgcp_send_reset_all(g_cfg);
1234 if (rc < 0) {
1235 vty_out(vty, "Error %d during endpoint reset.%s",
1236 rc, VTY_NEWLINE);
1237 return CMD_WARNING;
1238 }
1239 return CMD_SUCCESS;
1240}
1241
1242#define OSMUX_STR "RTP multiplexing\n"
1243DEFUN(cfg_mgcp_osmux,
1244 cfg_mgcp_osmux_cmd,
1245 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001246 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001247{
1248 if (strcmp(argv[0], "off") == 0) {
1249 g_cfg->osmux = OSMUX_USAGE_OFF;
1250 return CMD_SUCCESS;
1251 }
1252
Philipp Maier87bd9be2017-08-22 16:35:41 +02001253 /* Since OSMUX support is not finished, we do not
1254 * allow to turn it on yet. */
1255 vty_out(vty, "OSMUX currently unavailable in this software version.%s", VTY_NEWLINE);
1256 return CMD_WARNING;
Philipp Maier2982e422017-11-07 12:27:48 +01001257#if 0
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001258 if (strcmp(argv[0], "on") == 0)
1259 g_cfg->osmux = OSMUX_USAGE_ON;
1260 else if (strcmp(argv[0], "only") == 0)
1261 g_cfg->osmux = OSMUX_USAGE_ONLY;
1262
1263 if (g_cfg->trunk.audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001264 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001265 return CMD_WARNING;
1266 }
1267
1268 return CMD_SUCCESS;
Philipp Maier2982e422017-11-07 12:27:48 +01001269#endif
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001270}
1271
1272DEFUN(cfg_mgcp_osmux_ip,
1273 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001274 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001275{
1276 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1277 return CMD_SUCCESS;
1278}
1279
1280DEFUN(cfg_mgcp_osmux_batch_factor,
1281 cfg_mgcp_osmux_batch_factor_cmd,
1282 "osmux batch-factor <1-8>",
1283 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1284{
1285 g_cfg->osmux_batch = atoi(argv[0]);
1286 return CMD_SUCCESS;
1287}
1288
1289DEFUN(cfg_mgcp_osmux_batch_size,
1290 cfg_mgcp_osmux_batch_size_cmd,
1291 "osmux batch-size <1-65535>",
1292 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1293{
1294 g_cfg->osmux_batch_size = atoi(argv[0]);
1295 return CMD_SUCCESS;
1296}
1297
1298DEFUN(cfg_mgcp_osmux_port,
1299 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001300 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001301{
1302 g_cfg->osmux_port = atoi(argv[0]);
1303 return CMD_SUCCESS;
1304}
1305
1306DEFUN(cfg_mgcp_osmux_dummy,
1307 cfg_mgcp_osmux_dummy_cmd,
1308 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001309 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1310 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001311{
1312 if (strcmp(argv[0], "on") == 0)
1313 g_cfg->osmux_dummy = 1;
1314 else if (strcmp(argv[0], "off") == 0)
1315 g_cfg->osmux_dummy = 0;
1316
1317 return CMD_SUCCESS;
1318}
1319
Philipp Maier12943ea2018-01-17 15:40:25 +01001320DEFUN(cfg_mgcp_domain,
1321 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001322 "domain NAME",
1323 "Set the domain part expected in MGCP messages' endpoint names\n"
1324 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001325{
1326 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1327 return CMD_SUCCESS;
1328}
1329
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001330int mgcp_vty_init(void)
1331{
1332 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001333 install_element_ve(&show_mgcp_endpoint_cmd);
1334 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001335 install_element(ENABLE_NODE, &loop_conn_cmd);
1336 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001337 install_element(ENABLE_NODE, &free_endp_cmd);
1338 install_element(ENABLE_NODE, &reset_endp_cmd);
1339 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1340
1341 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1342 install_node(&mgcp_node, config_write_mgcp);
1343
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001344 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001345 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1346 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1347 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001348 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001349 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001350 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001351 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001352 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001353 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001354 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1355 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001356 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1357 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1358 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1359 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1360 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1361 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1362 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1363 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1364 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001365 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1366 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1367 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1368 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1369 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1370 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001371 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001372 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1373 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1374 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1375 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1376 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1377 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1378 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1379 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
1380 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1381 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1382 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1383 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1384 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1385 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1386 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1387 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1388 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1389 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1390 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1391 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1392 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001393 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001394
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001395 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1396 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001397 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1398 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1399 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1400 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1401 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1402 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1403 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1404 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1405 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1406 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1407 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1408 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1409 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
1410 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1411 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1412 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1413 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1414 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1415 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1416 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1417 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1418 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1419
1420 return 0;
1421}
1422
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001423int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1424 enum mgcp_role role)
1425{
1426 int rc;
1427 struct mgcp_trunk_config *trunk;
1428
1429 cfg->osmux_port = OSMUX_PORT;
1430 cfg->osmux_batch = 4;
1431 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1432
1433 g_cfg = cfg;
1434 rc = vty_read_config_file(config_file, NULL);
1435 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001436 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1437 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001438 return rc;
1439 }
1440
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001441 if (!g_cfg->source_addr) {
1442 fprintf(stderr, "You need to specify a bind address.\n");
1443 return -1;
1444 }
1445
Philipp Maier48454982017-11-10 16:46:41 +01001446 if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001447 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001448 "Failed to initialize the virtual trunk (%d endpoints)\n",
1449 g_cfg->trunk.number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001450 return -1;
1451 }
1452
1453 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maier48454982017-11-10 16:46:41 +01001454 if (mgcp_endpoints_allocate(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001455 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001456 "Failed to initialize trunk %d (%d endpoints)\n",
1457 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001458 return -1;
1459 }
1460 }
1461 cfg->role = role;
1462
1463 return 0;
1464}