blob: e40d412172cde01a28bc9f0a6edc4e47c4d9e9e4 [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 Sperlingaa823bf2018-10-29 14:51:41 +0100252 if (show_stats && cfg->mgcp_mdcx_ctr_group) {
253 vty_out(vty, " %s:%s", cfg->mgcp_mdcx_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_mdcx_ctr_group);
255 }
Stefan Sperlingba25eab2018-10-30 14:32:31 +0100256 if (show_stats && cfg->all_rtp_conn_stats) {
257 vty_out(vty, " %s:%s", cfg->all_rtp_conn_stats->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->all_rtp_conn_stats);
259 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200260}
261
Stefan Sperling12086582018-06-26 15:26:28 +0200262#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
263
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200264DEFUN(show_mcgp, show_mgcp_cmd,
265 "show mgcp [stats]",
266 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200267 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200268 "Include Statistics\n")
269{
270 struct mgcp_trunk_config *trunk;
271 int show_stats = argc >= 1;
272
273 dump_trunk(vty, &g_cfg->trunk, show_stats);
274
275 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200276 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200277
278 if (g_cfg->osmux)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200279 vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(),
280 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200281
282 return CMD_SUCCESS;
283}
284
Stefan Sperling12086582018-06-26 15:26:28 +0200285static void
286dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk_config *trunk, const char *epname)
287{
288 const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
289 unsigned long epidx;
290 char *endp;
291 int i;
292
293 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)
294 epname += virt_prefix_len;
295 errno = 0;
296 epidx = strtoul(epname, &endp, 16);
297 if (epname[0] == '\0' || *endp != '\0') {
298 vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);
299 return;
300 }
301 if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */
302 || epidx >= trunk->number_endpoints) {
303 vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);
304 return;
305 }
306
307 for (i = 0; i < trunk->number_endpoints; ++i) {
308 struct mgcp_endpoint *endp = &trunk->endpoints[i];
309 if (i == epidx) {
310 dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);
311 break;
312 }
313 }
314}
315
316DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
317 "show mgcp endpoint NAME",
318 SHOW_STR
319 SHOW_MGCP_STR
320 "Display information about an endpoint\n" "The name of the endpoint\n")
321{
322 struct mgcp_trunk_config *trunk;
323
324 dump_mgcp_endpoint(vty, &g_cfg->trunk, argv[0]);
325 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
326 dump_mgcp_endpoint(vty, trunk, argv[0]);
327
328 return CMD_SUCCESS;
329}
330
331DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
332 "show mgcp trunk <0-64> endpoint NAME",
333 SHOW_STR
334 SHOW_MGCP_STR
335 "Display information about a trunk\n" "Trunk number\n"
336 "Display information about an endpoint\n" "The name of the endpoint\n")
337{
338 struct mgcp_trunk_config *trunk;
339 int trunkidx = atoi(argv[0]);
340
341 trunk = find_trunk(g_cfg, trunkidx);
342 if (!trunk) {
343 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
344 return CMD_WARNING;
345 }
346
347 dump_mgcp_endpoint(vty, trunk, argv[1]);
348 return CMD_SUCCESS;
349}
350
Philipp Maier87bd9be2017-08-22 16:35:41 +0200351DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200352{
353 vty->node = MGCP_NODE;
354 return CMD_SUCCESS;
355}
356
357DEFUN(cfg_mgcp_local_ip,
358 cfg_mgcp_local_ip_cmd,
359 "local ip A.B.C.D",
360 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200361 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200362{
363 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
364 return CMD_SUCCESS;
365}
366
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200367#define BIND_STR "Listen/Bind related socket option\n"
368DEFUN(cfg_mgcp_bind_ip,
369 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200370 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200371{
372 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
373 return CMD_SUCCESS;
374}
375
376DEFUN(cfg_mgcp_bind_port,
377 cfg_mgcp_bind_port_cmd,
378 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200379 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200380{
381 unsigned int port = atoi(argv[0]);
382 g_cfg->source_port = port;
383 return CMD_SUCCESS;
384}
385
386DEFUN(cfg_mgcp_bind_early,
387 cfg_mgcp_bind_early_cmd,
388 "bind early (0|1)",
389 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200390 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200391{
392 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
393 return CMD_WARNING;
394}
395
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200396#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200397#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200398#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200399#define RANGE_START_STR "Start of the range of ports\n"
400#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200401
Philipp Maierf1889d82017-11-08 14:59:39 +0100402DEFUN(cfg_mgcp_rtp_port_range,
403 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200404 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200405 RTP_STR "Range of ports to use for the NET side\n"
406 RANGE_START_STR RANGE_END_STR)
407{
Philipp Maiera19547b2018-05-22 13:44:34 +0200408 int start;
409 int end;
410
411 start = atoi(argv[0]);
412 end = atoi(argv[1]);
413
414 if (end < start) {
415 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
416 end, start, VTY_NEWLINE);
417 return CMD_WARNING;
418 }
419
420 if (start & 1) {
421 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
422 start, start & 0xFFFE, VTY_NEWLINE);
423 start &= 0xFFFE;
424 }
425
426 if ((end & 1) == 0) {
427 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
428 end, end | 1, VTY_NEWLINE);
429 end |= 1;
430 }
431
432 g_cfg->net_ports.range_start = start;
433 g_cfg->net_ports.range_end = end;
434 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
435
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200436 return CMD_SUCCESS;
437}
Philipp Maierf1889d82017-11-08 14:59:39 +0100438ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
439 cfg_mgcp_rtp_net_range_cmd,
440 "rtp net-range <0-65534> <0-65534>",
441 RTP_STR "Range of ports to use for the NET side\n"
442 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200443
Philipp Maierf1889d82017-11-08 14:59:39 +0100444DEFUN(cfg_mgcp_rtp_bind_ip,
445 cfg_mgcp_rtp_bind_ip_cmd,
446 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200447 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
448{
449 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
450 return CMD_SUCCESS;
451}
Philipp Maierf1889d82017-11-08 14:59:39 +0100452ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
453 cfg_mgcp_rtp_net_bind_ip_cmd,
454 "rtp net-bind-ip A.B.C.D",
455 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200456
Philipp Maierf1889d82017-11-08 14:59:39 +0100457DEFUN(cfg_mgcp_rtp_no_bind_ip,
458 cfg_mgcp_rtp_no_bind_ip_cmd,
459 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200460 NO_STR RTP_STR "Bind endpoints facing the Network\n"
461 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200462{
463 talloc_free(g_cfg->net_ports.bind_addr);
464 g_cfg->net_ports.bind_addr = NULL;
465 return CMD_SUCCESS;
466}
Philipp Maierf1889d82017-11-08 14:59:39 +0100467ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
468 cfg_mgcp_rtp_no_net_bind_ip_cmd,
469 "no rtp net-bind-ip",
470 NO_STR RTP_STR "Bind endpoints facing the Network\n"
471 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200472
Philipp Maier1cb1e382017-11-02 17:16:04 +0100473DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
474 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
475 "rtp ip-probing",
476 RTP_STR "automatic rtp bind ip selection\n")
477{
478 g_cfg->net_ports.bind_addr_probe = true;
479 return CMD_SUCCESS;
480}
481
482DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
483 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
484 "no rtp ip-probing",
485 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
486{
487 g_cfg->net_ports.bind_addr_probe = false;
488 return CMD_SUCCESS;
489}
490
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200491DEFUN(cfg_mgcp_rtp_ip_dscp,
492 cfg_mgcp_rtp_ip_dscp_cmd,
493 "rtp ip-dscp <0-255>",
494 RTP_STR
495 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
496{
497 int dscp = atoi(argv[0]);
498 g_cfg->endp_dscp = dscp;
499 return CMD_SUCCESS;
500}
501
502ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200503 "rtp ip-tos <0-255>",
504 RTP_STR
505 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
506#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
507 DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200508 cfg_mgcp_rtp_force_ptime_cmd,
509 "rtp force-ptime (10|20|40)",
510 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200511 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200512{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200513 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200514 return CMD_SUCCESS;
515}
516
517DEFUN(cfg_mgcp_no_rtp_force_ptime,
518 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200519 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200520{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200521 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200522 return CMD_SUCCESS;
523}
524
525DEFUN(cfg_mgcp_sdp_fmtp_extra,
526 cfg_mgcp_sdp_fmtp_extra_cmd,
527 "sdp audio fmtp-extra .NAME",
528 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
529 "Extra Information\n")
530{
531 char *txt = argv_concat(argv, argc, 0);
532 if (!txt)
533 return CMD_WARNING;
534
535 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
536 talloc_free(txt);
537 return CMD_SUCCESS;
538}
539
540DEFUN(cfg_mgcp_allow_transcoding,
541 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200542 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200543{
544 g_cfg->trunk.no_audio_transcoding = 0;
545 return CMD_SUCCESS;
546}
547
548DEFUN(cfg_mgcp_no_allow_transcoding,
549 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200550 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200551{
552 g_cfg->trunk.no_audio_transcoding = 1;
553 return CMD_SUCCESS;
554}
555
556#define SDP_STR "SDP File related options\n"
557#define AUDIO_STR "Audio payload options\n"
558DEFUN(cfg_mgcp_sdp_payload_number,
559 cfg_mgcp_sdp_payload_number_cmd,
560 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200561 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200562{
563 unsigned int payload = atoi(argv[0]);
564 g_cfg->trunk.audio_payload = payload;
565 return CMD_SUCCESS;
566}
567
Philipp Maier87bd9be2017-08-22 16:35:41 +0200568ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
569 cfg_mgcp_sdp_payload_number_cmd_old,
570 "sdp audio payload number <0-255>",
571 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200572
Philipp Maier87bd9be2017-08-22 16:35:41 +0200573 DEFUN(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200574 cfg_mgcp_sdp_payload_name_cmd,
575 "sdp audio-payload name NAME",
576 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
577{
578 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
579 return CMD_SUCCESS;
580}
581
582ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200583 "sdp audio payload name NAME",
584 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200585
Philipp Maier87bd9be2017-08-22 16:35:41 +0200586 DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200587 cfg_mgcp_sdp_payload_send_ptime_cmd,
588 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200589 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200590{
591 g_cfg->trunk.audio_send_ptime = 1;
592 return CMD_SUCCESS;
593}
594
595DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
596 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
597 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200598 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200599{
600 g_cfg->trunk.audio_send_ptime = 0;
601 return CMD_SUCCESS;
602}
603
604DEFUN(cfg_mgcp_sdp_payload_send_name,
605 cfg_mgcp_sdp_payload_send_name_cmd,
606 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200607 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200608{
609 g_cfg->trunk.audio_send_name = 1;
610 return CMD_SUCCESS;
611}
612
613DEFUN(cfg_mgcp_no_sdp_payload_send_name,
614 cfg_mgcp_no_sdp_payload_send_name_cmd,
615 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200616 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200617{
618 g_cfg->trunk.audio_send_name = 0;
619 return CMD_SUCCESS;
620}
621
622DEFUN(cfg_mgcp_loop,
623 cfg_mgcp_loop_cmd,
624 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200625 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200626{
627 if (g_cfg->osmux) {
628 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
629 return CMD_WARNING;
630 }
631 g_cfg->trunk.audio_loop = atoi(argv[0]);
632 return CMD_SUCCESS;
633}
634
635DEFUN(cfg_mgcp_force_realloc,
636 cfg_mgcp_force_realloc_cmd,
637 "force-realloc (0|1)",
638 "Force endpoint reallocation when the endpoint is still seized\n"
639 "Don't force reallocation\n" "force reallocation\n")
640{
641 g_cfg->trunk.force_realloc = atoi(argv[0]);
642 return CMD_SUCCESS;
643}
644
Philipp Maier87bd9be2017-08-22 16:35:41 +0200645DEFUN(cfg_mgcp_rtp_accept_all,
646 cfg_mgcp_rtp_accept_all_cmd,
647 "rtp-accept-all (0|1)",
648 "Accept all RTP packets, even when the originating IP/Port does not match\n"
649 "enable filter\n" "disable filter\n")
650{
651 g_cfg->trunk.rtp_accept_all = atoi(argv[0]);
652 return CMD_SUCCESS;
653}
654
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200655DEFUN(cfg_mgcp_number_endp,
656 cfg_mgcp_number_endp_cmd,
657 "number endpoints <0-65534>",
658 "Number options\n" "Endpoints available\n" "Number endpoints\n")
659{
660 /* + 1 as we start counting at one */
Philipp Maierfcd06552017-11-10 17:32:22 +0100661 g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200662 return CMD_SUCCESS;
663}
664
Philipp Maier87bd9be2017-08-22 16:35:41 +0200665DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200666{
667 g_cfg->trunk.omit_rtcp = 1;
668 return CMD_SUCCESS;
669}
670
671DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200672 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200673{
674 g_cfg->trunk.omit_rtcp = 0;
675 return CMD_SUCCESS;
676}
677
678DEFUN(cfg_mgcp_patch_rtp_ssrc,
679 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200680 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200681{
682 g_cfg->trunk.force_constant_ssrc = 1;
683 return CMD_SUCCESS;
684}
685
686DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
687 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200688 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200689{
690 g_cfg->trunk.force_constant_ssrc = 0;
691 return CMD_SUCCESS;
692}
693
694DEFUN(cfg_mgcp_patch_rtp_ts,
695 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200696 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200697{
698 g_cfg->trunk.force_aligned_timing = 1;
699 return CMD_SUCCESS;
700}
701
702DEFUN(cfg_mgcp_no_patch_rtp_ts,
703 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200704 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200705{
706 g_cfg->trunk.force_aligned_timing = 0;
707 return CMD_SUCCESS;
708}
709
710DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200711 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200712{
713 g_cfg->trunk.force_constant_ssrc = 0;
714 g_cfg->trunk.force_aligned_timing = 0;
715 return CMD_SUCCESS;
716}
717
718DEFUN(cfg_mgcp_rtp_keepalive,
719 cfg_mgcp_rtp_keepalive_cmd,
720 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200721 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200722{
723 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
724 return CMD_SUCCESS;
725}
726
727DEFUN(cfg_mgcp_rtp_keepalive_once,
728 cfg_mgcp_rtp_keepalive_once_cmd,
729 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200730 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200731{
732 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
733 return CMD_SUCCESS;
734}
735
736DEFUN(cfg_mgcp_no_rtp_keepalive,
737 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200738 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200739{
Philipp Maiere726d4f2017-11-01 10:41:34 +0100740 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200741 return CMD_SUCCESS;
742}
743
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200744#define CALL_AGENT_STR "Callagent information\n"
745DEFUN(cfg_mgcp_agent_addr,
746 cfg_mgcp_agent_addr_cmd,
747 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200748 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200749{
750 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
751 return CMD_SUCCESS;
752}
753
754ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200755 "call agent ip A.B.C.D",
756 CALL_AGENT_STR CALL_AGENT_STR IP_STR
757 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200758
Philipp Maier87bd9be2017-08-22 16:35:41 +0200759 DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
760 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200761{
762 struct mgcp_trunk_config *trunk;
763 int index = atoi(argv[0]);
764
765 trunk = mgcp_trunk_num(g_cfg, index);
766 if (!trunk)
767 trunk = mgcp_trunk_alloc(g_cfg, index);
768
769 if (!trunk) {
770 vty_out(vty, "%%Unable to allocate trunk %u.%s",
771 index, VTY_NEWLINE);
772 return CMD_WARNING;
773 }
774
775 vty->node = TRUNK_NODE;
776 vty->index = trunk;
777 return CMD_SUCCESS;
778}
779
780static int config_write_trunk(struct vty *vty)
781{
782 struct mgcp_trunk_config *trunk;
783
784 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
785 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
786 vty_out(vty, " sdp audio-payload number %d%s",
787 trunk->audio_payload, VTY_NEWLINE);
788 vty_out(vty, " sdp audio-payload name %s%s",
789 trunk->audio_name, VTY_NEWLINE);
790 vty_out(vty, " %ssdp audio-payload send-ptime%s",
791 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
792 vty_out(vty, " %ssdp audio-payload send-name%s",
793 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
794
795 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
796 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
797 else if (trunk->keepalive_interval)
798 vty_out(vty, " rtp keep-alive %d%s",
799 trunk->keepalive_interval, VTY_NEWLINE);
800 else
801 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200802 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200803 vty_out(vty, " force-realloc %d%s",
804 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200805 vty_out(vty, " rtp-accept-all %d%s",
806 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200807 if (trunk->omit_rtcp)
808 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
809 else
810 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
811 if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
812 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200813 trunk->force_constant_ssrc ? "" : "no ",
814 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200815 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200816 trunk->force_aligned_timing ? "" : "no ",
817 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200818 } else
819 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
820 if (trunk->audio_fmtp_extra)
821 vty_out(vty, " sdp audio fmtp-extra %s%s",
822 trunk->audio_fmtp_extra, VTY_NEWLINE);
823 vty_out(vty, " %sallow-transcoding%s",
824 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
825 }
826
827 return CMD_SUCCESS;
828}
829
830DEFUN(cfg_trunk_sdp_fmtp_extra,
831 cfg_trunk_sdp_fmtp_extra_cmd,
832 "sdp audio fmtp-extra .NAME",
833 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
834 "Extra Information\n")
835{
836 struct mgcp_trunk_config *trunk = vty->index;
837 char *txt = argv_concat(argv, argc, 0);
838 if (!txt)
839 return CMD_WARNING;
840
841 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
842 talloc_free(txt);
843 return CMD_SUCCESS;
844}
845
846DEFUN(cfg_trunk_payload_number,
847 cfg_trunk_payload_number_cmd,
848 "sdp audio-payload number <0-255>",
849 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
850{
851 struct mgcp_trunk_config *trunk = vty->index;
852 unsigned int payload = atoi(argv[0]);
853
854 trunk->audio_payload = payload;
855 return CMD_SUCCESS;
856}
857
858ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200859 "sdp audio payload number <0-255>",
860 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200861
Philipp Maier87bd9be2017-08-22 16:35:41 +0200862 DEFUN(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200863 cfg_trunk_payload_name_cmd,
864 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200865 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200866{
867 struct mgcp_trunk_config *trunk = vty->index;
868
869 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
870 return CMD_SUCCESS;
871}
872
873ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200874 "sdp audio payload name NAME",
875 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200876
Philipp Maier87bd9be2017-08-22 16:35:41 +0200877 DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200878 cfg_trunk_loop_cmd,
879 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200880 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200881{
882 struct mgcp_trunk_config *trunk = vty->index;
883
884 if (g_cfg->osmux) {
885 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
886 return CMD_WARNING;
887 }
888 trunk->audio_loop = atoi(argv[0]);
889 return CMD_SUCCESS;
890}
891
892DEFUN(cfg_trunk_sdp_payload_send_ptime,
893 cfg_trunk_sdp_payload_send_ptime_cmd,
894 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200895 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200896{
897 struct mgcp_trunk_config *trunk = vty->index;
898 trunk->audio_send_ptime = 1;
899 return CMD_SUCCESS;
900}
901
902DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
903 cfg_trunk_no_sdp_payload_send_ptime_cmd,
904 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200905 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200906{
907 struct mgcp_trunk_config *trunk = vty->index;
908 trunk->audio_send_ptime = 0;
909 return CMD_SUCCESS;
910}
911
912DEFUN(cfg_trunk_sdp_payload_send_name,
913 cfg_trunk_sdp_payload_send_name_cmd,
914 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200915 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200916{
917 struct mgcp_trunk_config *trunk = vty->index;
918 trunk->audio_send_name = 1;
919 return CMD_SUCCESS;
920}
921
922DEFUN(cfg_trunk_no_sdp_payload_send_name,
923 cfg_trunk_no_sdp_payload_send_name_cmd,
924 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200925 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200926{
927 struct mgcp_trunk_config *trunk = vty->index;
928 trunk->audio_send_name = 0;
929 return CMD_SUCCESS;
930}
931
Philipp Maier87bd9be2017-08-22 16:35:41 +0200932DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200933{
934 struct mgcp_trunk_config *trunk = vty->index;
935 trunk->omit_rtcp = 1;
936 return CMD_SUCCESS;
937}
938
939DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200940 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200941{
942 struct mgcp_trunk_config *trunk = vty->index;
943 trunk->omit_rtcp = 0;
944 return CMD_SUCCESS;
945}
946
947DEFUN(cfg_trunk_patch_rtp_ssrc,
948 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200949 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200950{
951 struct mgcp_trunk_config *trunk = vty->index;
952 trunk->force_constant_ssrc = 1;
953 return CMD_SUCCESS;
954}
955
956DEFUN(cfg_trunk_no_patch_rtp_ssrc,
957 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200958 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200959{
960 struct mgcp_trunk_config *trunk = vty->index;
961 trunk->force_constant_ssrc = 0;
962 return CMD_SUCCESS;
963}
964
965DEFUN(cfg_trunk_patch_rtp_ts,
966 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200967 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200968{
969 struct mgcp_trunk_config *trunk = vty->index;
970 trunk->force_aligned_timing = 1;
971 return CMD_SUCCESS;
972}
973
974DEFUN(cfg_trunk_no_patch_rtp_ts,
975 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200976 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200977{
978 struct mgcp_trunk_config *trunk = vty->index;
979 trunk->force_aligned_timing = 0;
980 return CMD_SUCCESS;
981}
982
983DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200984 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200985{
986 struct mgcp_trunk_config *trunk = vty->index;
987 trunk->force_constant_ssrc = 0;
988 trunk->force_aligned_timing = 0;
989 return CMD_SUCCESS;
990}
991
992DEFUN(cfg_trunk_rtp_keepalive,
993 cfg_trunk_rtp_keepalive_cmd,
994 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200995 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200996{
997 struct mgcp_trunk_config *trunk = vty->index;
998 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
999 return CMD_SUCCESS;
1000}
1001
1002DEFUN(cfg_trunk_rtp_keepalive_once,
1003 cfg_trunk_rtp_keepalive_once_cmd,
1004 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001005 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001006{
1007 struct mgcp_trunk_config *trunk = vty->index;
1008 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1009 return CMD_SUCCESS;
1010}
1011
1012DEFUN(cfg_trunk_no_rtp_keepalive,
1013 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001014 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001015{
1016 struct mgcp_trunk_config *trunk = vty->index;
1017 mgcp_trunk_set_keepalive(trunk, 0);
1018 return CMD_SUCCESS;
1019}
1020
1021DEFUN(cfg_trunk_allow_transcoding,
1022 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001023 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001024{
1025 struct mgcp_trunk_config *trunk = vty->index;
1026 trunk->no_audio_transcoding = 0;
1027 return CMD_SUCCESS;
1028}
1029
1030DEFUN(cfg_trunk_no_allow_transcoding,
1031 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001032 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001033{
1034 struct mgcp_trunk_config *trunk = vty->index;
1035 trunk->no_audio_transcoding = 1;
1036 return CMD_SUCCESS;
1037}
1038
Philipp Maier87bd9be2017-08-22 16:35:41 +02001039DEFUN(loop_conn,
1040 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001041 "loop-endpoint <0-64> NAME (0|1)",
1042 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001043 "The name in hex of the endpoint\n" "Disable the loop\n"
1044 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001045{
1046 struct mgcp_trunk_config *trunk;
1047 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001048 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001049
1050 trunk = find_trunk(g_cfg, atoi(argv[0]));
1051 if (!trunk) {
1052 vty_out(vty, "%%Trunk %d not found in the config.%s",
1053 atoi(argv[0]), VTY_NEWLINE);
1054 return CMD_WARNING;
1055 }
1056
1057 if (!trunk->endpoints) {
1058 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1059 trunk->trunk_nr, VTY_NEWLINE);
1060 return CMD_WARNING;
1061 }
1062
1063 int endp_no = strtoul(argv[1], NULL, 16);
1064 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1065 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001066 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001067 return CMD_WARNING;
1068 }
1069
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001070 endp = &trunk->endpoints[endp_no];
1071 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001072 llist_for_each_entry(conn, &endp->conns, entry) {
1073 if (conn->type == MGCP_CONN_TYPE_RTP)
1074 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1075 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1076 else {
1077 /* FIXME: Introduce support for other connection (E1)
1078 * types when implementation is available */
1079 vty_out(vty, "%%Can't enable SSRC patching,"
1080 "connection %s is not an RTP connection.%s",
1081 mgcp_conn_dump(conn), VTY_NEWLINE);
1082 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001083
Philipp Maier87bd9be2017-08-22 16:35:41 +02001084 if (loop)
1085 conn->mode = MGCP_CONN_LOOPBACK;
1086 else
1087 conn->mode = conn->mode_orig;
1088 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001089
1090 return CMD_SUCCESS;
1091}
1092
Philipp Maier87bd9be2017-08-22 16:35:41 +02001093DEFUN(tap_rtp,
1094 tap_rtp_cmd,
1095 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001096 "Forward data on endpoint to a different system\n" "Trunk number\n"
1097 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001098 "The connection id in hex\n"
1099 "Forward incoming data\n"
1100 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001101 "destination IP of the data\n" "destination port\n")
1102{
1103 struct mgcp_rtp_tap *tap;
1104 struct mgcp_trunk_config *trunk;
1105 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001106 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001107 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001108
1109 trunk = find_trunk(g_cfg, atoi(argv[0]));
1110 if (!trunk) {
1111 vty_out(vty, "%%Trunk %d not found in the config.%s",
1112 atoi(argv[0]), VTY_NEWLINE);
1113 return CMD_WARNING;
1114 }
1115
1116 if (!trunk->endpoints) {
1117 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1118 trunk->trunk_nr, VTY_NEWLINE);
1119 return CMD_WARNING;
1120 }
1121
1122 int endp_no = strtoul(argv[1], NULL, 16);
1123 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1124 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001125 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001126 return CMD_WARNING;
1127 }
1128
1129 endp = &trunk->endpoints[endp_no];
1130
Philipp Maier01d24a32017-11-21 17:26:09 +01001131 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001132 conn = mgcp_conn_get_rtp(endp, conn_id);
1133 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001134 vty_out(vty, "Conn ID %s is invalid.%s",
1135 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001136 return CMD_WARNING;
1137 }
1138
1139 if (strcmp(argv[3], "in") == 0)
1140 tap = &conn->tap_in;
1141 else if (strcmp(argv[3], "out") == 0)
1142 tap = &conn->tap_out;
1143 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001144 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1145 return CMD_WARNING;
1146 }
1147
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001148 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001149 inet_aton(argv[4], &tap->forward.sin_addr);
1150 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001151 tap->enabled = 1;
1152 return CMD_SUCCESS;
1153}
1154
1155DEFUN(free_endp, free_endp_cmd,
1156 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001157 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001158{
1159 struct mgcp_trunk_config *trunk;
1160 struct mgcp_endpoint *endp;
1161
1162 trunk = find_trunk(g_cfg, atoi(argv[0]));
1163 if (!trunk) {
1164 vty_out(vty, "%%Trunk %d not found in the config.%s",
1165 atoi(argv[0]), VTY_NEWLINE);
1166 return CMD_WARNING;
1167 }
1168
1169 if (!trunk->endpoints) {
1170 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1171 trunk->trunk_nr, VTY_NEWLINE);
1172 return CMD_WARNING;
1173 }
1174
1175 int endp_no = strtoul(argv[1], NULL, 16);
1176 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1177 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001178 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001179 return CMD_WARNING;
1180 }
1181
1182 endp = &trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001183 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001184 return CMD_SUCCESS;
1185}
1186
1187DEFUN(reset_endp, reset_endp_cmd,
1188 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001189 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001190{
1191 struct mgcp_trunk_config *trunk;
1192 struct mgcp_endpoint *endp;
1193 int endp_no, rc;
1194
1195 trunk = find_trunk(g_cfg, atoi(argv[0]));
1196 if (!trunk) {
1197 vty_out(vty, "%%Trunk %d not found in the config.%s",
1198 atoi(argv[0]), VTY_NEWLINE);
1199 return CMD_WARNING;
1200 }
1201
1202 if (!trunk->endpoints) {
1203 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1204 trunk->trunk_nr, VTY_NEWLINE);
1205 return CMD_WARNING;
1206 }
1207
1208 endp_no = strtoul(argv[1], NULL, 16);
1209 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1210 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001211 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001212 return CMD_WARNING;
1213 }
1214
1215 endp = &trunk->endpoints[endp_no];
1216 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1217 if (rc < 0) {
1218 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1219 return CMD_WARNING;
1220 }
1221 return CMD_SUCCESS;
1222}
1223
1224DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001225 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001226{
1227 int rc;
1228
1229 rc = mgcp_send_reset_all(g_cfg);
1230 if (rc < 0) {
1231 vty_out(vty, "Error %d during endpoint reset.%s",
1232 rc, VTY_NEWLINE);
1233 return CMD_WARNING;
1234 }
1235 return CMD_SUCCESS;
1236}
1237
1238#define OSMUX_STR "RTP multiplexing\n"
1239DEFUN(cfg_mgcp_osmux,
1240 cfg_mgcp_osmux_cmd,
1241 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001242 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001243{
1244 if (strcmp(argv[0], "off") == 0) {
1245 g_cfg->osmux = OSMUX_USAGE_OFF;
1246 return CMD_SUCCESS;
1247 }
1248
Philipp Maier87bd9be2017-08-22 16:35:41 +02001249 /* Since OSMUX support is not finished, we do not
1250 * allow to turn it on yet. */
1251 vty_out(vty, "OSMUX currently unavailable in this software version.%s", VTY_NEWLINE);
1252 return CMD_WARNING;
Philipp Maier2982e422017-11-07 12:27:48 +01001253#if 0
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001254 if (strcmp(argv[0], "on") == 0)
1255 g_cfg->osmux = OSMUX_USAGE_ON;
1256 else if (strcmp(argv[0], "only") == 0)
1257 g_cfg->osmux = OSMUX_USAGE_ONLY;
1258
1259 if (g_cfg->trunk.audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001260 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001261 return CMD_WARNING;
1262 }
1263
1264 return CMD_SUCCESS;
Philipp Maier2982e422017-11-07 12:27:48 +01001265#endif
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001266}
1267
1268DEFUN(cfg_mgcp_osmux_ip,
1269 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001270 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001271{
1272 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1273 return CMD_SUCCESS;
1274}
1275
1276DEFUN(cfg_mgcp_osmux_batch_factor,
1277 cfg_mgcp_osmux_batch_factor_cmd,
1278 "osmux batch-factor <1-8>",
1279 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1280{
1281 g_cfg->osmux_batch = atoi(argv[0]);
1282 return CMD_SUCCESS;
1283}
1284
1285DEFUN(cfg_mgcp_osmux_batch_size,
1286 cfg_mgcp_osmux_batch_size_cmd,
1287 "osmux batch-size <1-65535>",
1288 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1289{
1290 g_cfg->osmux_batch_size = atoi(argv[0]);
1291 return CMD_SUCCESS;
1292}
1293
1294DEFUN(cfg_mgcp_osmux_port,
1295 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001296 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001297{
1298 g_cfg->osmux_port = atoi(argv[0]);
1299 return CMD_SUCCESS;
1300}
1301
1302DEFUN(cfg_mgcp_osmux_dummy,
1303 cfg_mgcp_osmux_dummy_cmd,
1304 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001305 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1306 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001307{
1308 if (strcmp(argv[0], "on") == 0)
1309 g_cfg->osmux_dummy = 1;
1310 else if (strcmp(argv[0], "off") == 0)
1311 g_cfg->osmux_dummy = 0;
1312
1313 return CMD_SUCCESS;
1314}
1315
Philipp Maier12943ea2018-01-17 15:40:25 +01001316DEFUN(cfg_mgcp_domain,
1317 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001318 "domain NAME",
1319 "Set the domain part expected in MGCP messages' endpoint names\n"
1320 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001321{
1322 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1323 return CMD_SUCCESS;
1324}
1325
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001326int mgcp_vty_init(void)
1327{
1328 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001329 install_element_ve(&show_mgcp_endpoint_cmd);
1330 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001331 install_element(ENABLE_NODE, &loop_conn_cmd);
1332 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001333 install_element(ENABLE_NODE, &free_endp_cmd);
1334 install_element(ENABLE_NODE, &reset_endp_cmd);
1335 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1336
1337 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1338 install_node(&mgcp_node, config_write_mgcp);
1339
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001340 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001341 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1342 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1343 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001344 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001345 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001346 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001347 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001348 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001349 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001350 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1351 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001352 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1353 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1354 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1355 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1356 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1357 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1358 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1359 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1360 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001361 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1362 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1363 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1364 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1365 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1366 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001367 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001368 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1369 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1370 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1371 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1372 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1373 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1374 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1375 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
1376 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1377 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1378 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1379 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1380 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1381 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1382 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1383 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1384 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1385 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1386 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1387 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1388 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001389 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001390
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001391 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1392 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001393 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1394 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1395 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1396 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1397 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1398 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1399 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1400 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1401 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1402 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1403 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1404 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1405 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
1406 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1407 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1408 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1409 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1410 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1411 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1412 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1413 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1414 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1415
1416 return 0;
1417}
1418
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001419int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1420 enum mgcp_role role)
1421{
1422 int rc;
1423 struct mgcp_trunk_config *trunk;
1424
1425 cfg->osmux_port = OSMUX_PORT;
1426 cfg->osmux_batch = 4;
1427 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1428
1429 g_cfg = cfg;
1430 rc = vty_read_config_file(config_file, NULL);
1431 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001432 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1433 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001434 return rc;
1435 }
1436
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001437 if (!g_cfg->source_addr) {
1438 fprintf(stderr, "You need to specify a bind address.\n");
1439 return -1;
1440 }
1441
Philipp Maier48454982017-11-10 16:46:41 +01001442 if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001443 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001444 "Failed to initialize the virtual trunk (%d endpoints)\n",
1445 g_cfg->trunk.number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001446 return -1;
1447 }
1448
1449 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maier48454982017-11-10 16:46:41 +01001450 if (mgcp_endpoints_allocate(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001451 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001452 "Failed to initialize trunk %d (%d endpoints)\n",
1453 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001454 return -1;
1455 }
1456 }
1457 cfg->role = role;
1458
1459 return 0;
1460}