blob: ed8aca52c8f48d808503ba27d0e20b90315b046f [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 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200256}
257
Stefan Sperling12086582018-06-26 15:26:28 +0200258#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
259
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200260DEFUN(show_mcgp, show_mgcp_cmd,
261 "show mgcp [stats]",
262 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200263 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200264 "Include Statistics\n")
265{
266 struct mgcp_trunk_config *trunk;
267 int show_stats = argc >= 1;
268
269 dump_trunk(vty, &g_cfg->trunk, show_stats);
270
271 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200272 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200273
274 if (g_cfg->osmux)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200275 vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(),
276 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200277
278 return CMD_SUCCESS;
279}
280
Stefan Sperling12086582018-06-26 15:26:28 +0200281static void
282dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk_config *trunk, const char *epname)
283{
284 const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
285 unsigned long epidx;
286 char *endp;
287 int i;
288
289 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)
290 epname += virt_prefix_len;
291 errno = 0;
292 epidx = strtoul(epname, &endp, 16);
293 if (epname[0] == '\0' || *endp != '\0') {
294 vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);
295 return;
296 }
297 if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */
298 || epidx >= trunk->number_endpoints) {
299 vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);
300 return;
301 }
302
303 for (i = 0; i < trunk->number_endpoints; ++i) {
304 struct mgcp_endpoint *endp = &trunk->endpoints[i];
305 if (i == epidx) {
306 dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);
307 break;
308 }
309 }
310}
311
312DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
313 "show mgcp endpoint NAME",
314 SHOW_STR
315 SHOW_MGCP_STR
316 "Display information about an endpoint\n" "The name of the endpoint\n")
317{
318 struct mgcp_trunk_config *trunk;
319
320 dump_mgcp_endpoint(vty, &g_cfg->trunk, argv[0]);
321 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
322 dump_mgcp_endpoint(vty, trunk, argv[0]);
323
324 return CMD_SUCCESS;
325}
326
327DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
328 "show mgcp trunk <0-64> endpoint NAME",
329 SHOW_STR
330 SHOW_MGCP_STR
331 "Display information about a trunk\n" "Trunk number\n"
332 "Display information about an endpoint\n" "The name of the endpoint\n")
333{
334 struct mgcp_trunk_config *trunk;
335 int trunkidx = atoi(argv[0]);
336
337 trunk = find_trunk(g_cfg, trunkidx);
338 if (!trunk) {
339 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
340 return CMD_WARNING;
341 }
342
343 dump_mgcp_endpoint(vty, trunk, argv[1]);
344 return CMD_SUCCESS;
345}
346
Philipp Maier87bd9be2017-08-22 16:35:41 +0200347DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200348{
349 vty->node = MGCP_NODE;
350 return CMD_SUCCESS;
351}
352
353DEFUN(cfg_mgcp_local_ip,
354 cfg_mgcp_local_ip_cmd,
355 "local ip A.B.C.D",
356 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200357 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200358{
359 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
360 return CMD_SUCCESS;
361}
362
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200363#define BIND_STR "Listen/Bind related socket option\n"
364DEFUN(cfg_mgcp_bind_ip,
365 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200366 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200367{
368 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
369 return CMD_SUCCESS;
370}
371
372DEFUN(cfg_mgcp_bind_port,
373 cfg_mgcp_bind_port_cmd,
374 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200375 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200376{
377 unsigned int port = atoi(argv[0]);
378 g_cfg->source_port = port;
379 return CMD_SUCCESS;
380}
381
382DEFUN(cfg_mgcp_bind_early,
383 cfg_mgcp_bind_early_cmd,
384 "bind early (0|1)",
385 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200386 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200387{
388 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
389 return CMD_WARNING;
390}
391
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200392#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200393#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200394#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200395#define RANGE_START_STR "Start of the range of ports\n"
396#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200397
Philipp Maierf1889d82017-11-08 14:59:39 +0100398DEFUN(cfg_mgcp_rtp_port_range,
399 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200400 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200401 RTP_STR "Range of ports to use for the NET side\n"
402 RANGE_START_STR RANGE_END_STR)
403{
Philipp Maiera19547b2018-05-22 13:44:34 +0200404 int start;
405 int end;
406
407 start = atoi(argv[0]);
408 end = atoi(argv[1]);
409
410 if (end < start) {
411 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
412 end, start, VTY_NEWLINE);
413 return CMD_WARNING;
414 }
415
416 if (start & 1) {
417 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
418 start, start & 0xFFFE, VTY_NEWLINE);
419 start &= 0xFFFE;
420 }
421
422 if ((end & 1) == 0) {
423 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
424 end, end | 1, VTY_NEWLINE);
425 end |= 1;
426 }
427
428 g_cfg->net_ports.range_start = start;
429 g_cfg->net_ports.range_end = end;
430 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
431
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200432 return CMD_SUCCESS;
433}
Philipp Maierf1889d82017-11-08 14:59:39 +0100434ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
435 cfg_mgcp_rtp_net_range_cmd,
436 "rtp net-range <0-65534> <0-65534>",
437 RTP_STR "Range of ports to use for the NET side\n"
438 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200439
Philipp Maierf1889d82017-11-08 14:59:39 +0100440DEFUN(cfg_mgcp_rtp_bind_ip,
441 cfg_mgcp_rtp_bind_ip_cmd,
442 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200443 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
444{
445 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
446 return CMD_SUCCESS;
447}
Philipp Maierf1889d82017-11-08 14:59:39 +0100448ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
449 cfg_mgcp_rtp_net_bind_ip_cmd,
450 "rtp net-bind-ip A.B.C.D",
451 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200452
Philipp Maierf1889d82017-11-08 14:59:39 +0100453DEFUN(cfg_mgcp_rtp_no_bind_ip,
454 cfg_mgcp_rtp_no_bind_ip_cmd,
455 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200456 NO_STR RTP_STR "Bind endpoints facing the Network\n"
457 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200458{
459 talloc_free(g_cfg->net_ports.bind_addr);
460 g_cfg->net_ports.bind_addr = NULL;
461 return CMD_SUCCESS;
462}
Philipp Maierf1889d82017-11-08 14:59:39 +0100463ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
464 cfg_mgcp_rtp_no_net_bind_ip_cmd,
465 "no rtp net-bind-ip",
466 NO_STR RTP_STR "Bind endpoints facing the Network\n"
467 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200468
Philipp Maier1cb1e382017-11-02 17:16:04 +0100469DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
470 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
471 "rtp ip-probing",
472 RTP_STR "automatic rtp bind ip selection\n")
473{
474 g_cfg->net_ports.bind_addr_probe = true;
475 return CMD_SUCCESS;
476}
477
478DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
479 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
480 "no rtp ip-probing",
481 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
482{
483 g_cfg->net_ports.bind_addr_probe = false;
484 return CMD_SUCCESS;
485}
486
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200487DEFUN(cfg_mgcp_rtp_ip_dscp,
488 cfg_mgcp_rtp_ip_dscp_cmd,
489 "rtp ip-dscp <0-255>",
490 RTP_STR
491 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
492{
493 int dscp = atoi(argv[0]);
494 g_cfg->endp_dscp = dscp;
495 return CMD_SUCCESS;
496}
497
498ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200499 "rtp ip-tos <0-255>",
500 RTP_STR
501 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
502#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
503 DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200504 cfg_mgcp_rtp_force_ptime_cmd,
505 "rtp force-ptime (10|20|40)",
506 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200507 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200508{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200509 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200510 return CMD_SUCCESS;
511}
512
513DEFUN(cfg_mgcp_no_rtp_force_ptime,
514 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200515 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200516{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200517 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200518 return CMD_SUCCESS;
519}
520
521DEFUN(cfg_mgcp_sdp_fmtp_extra,
522 cfg_mgcp_sdp_fmtp_extra_cmd,
523 "sdp audio fmtp-extra .NAME",
524 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
525 "Extra Information\n")
526{
527 char *txt = argv_concat(argv, argc, 0);
528 if (!txt)
529 return CMD_WARNING;
530
531 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
532 talloc_free(txt);
533 return CMD_SUCCESS;
534}
535
536DEFUN(cfg_mgcp_allow_transcoding,
537 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200538 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200539{
540 g_cfg->trunk.no_audio_transcoding = 0;
541 return CMD_SUCCESS;
542}
543
544DEFUN(cfg_mgcp_no_allow_transcoding,
545 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200546 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200547{
548 g_cfg->trunk.no_audio_transcoding = 1;
549 return CMD_SUCCESS;
550}
551
552#define SDP_STR "SDP File related options\n"
553#define AUDIO_STR "Audio payload options\n"
554DEFUN(cfg_mgcp_sdp_payload_number,
555 cfg_mgcp_sdp_payload_number_cmd,
556 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200557 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200558{
559 unsigned int payload = atoi(argv[0]);
560 g_cfg->trunk.audio_payload = payload;
561 return CMD_SUCCESS;
562}
563
Philipp Maier87bd9be2017-08-22 16:35:41 +0200564ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
565 cfg_mgcp_sdp_payload_number_cmd_old,
566 "sdp audio payload number <0-255>",
567 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200568
Philipp Maier87bd9be2017-08-22 16:35:41 +0200569 DEFUN(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200570 cfg_mgcp_sdp_payload_name_cmd,
571 "sdp audio-payload name NAME",
572 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
573{
574 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
575 return CMD_SUCCESS;
576}
577
578ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200579 "sdp audio payload name NAME",
580 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200581
Philipp Maier87bd9be2017-08-22 16:35:41 +0200582 DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200583 cfg_mgcp_sdp_payload_send_ptime_cmd,
584 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200585 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200586{
587 g_cfg->trunk.audio_send_ptime = 1;
588 return CMD_SUCCESS;
589}
590
591DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
592 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
593 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200594 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200595{
596 g_cfg->trunk.audio_send_ptime = 0;
597 return CMD_SUCCESS;
598}
599
600DEFUN(cfg_mgcp_sdp_payload_send_name,
601 cfg_mgcp_sdp_payload_send_name_cmd,
602 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200603 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200604{
605 g_cfg->trunk.audio_send_name = 1;
606 return CMD_SUCCESS;
607}
608
609DEFUN(cfg_mgcp_no_sdp_payload_send_name,
610 cfg_mgcp_no_sdp_payload_send_name_cmd,
611 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200612 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200613{
614 g_cfg->trunk.audio_send_name = 0;
615 return CMD_SUCCESS;
616}
617
618DEFUN(cfg_mgcp_loop,
619 cfg_mgcp_loop_cmd,
620 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200621 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200622{
623 if (g_cfg->osmux) {
624 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
625 return CMD_WARNING;
626 }
627 g_cfg->trunk.audio_loop = atoi(argv[0]);
628 return CMD_SUCCESS;
629}
630
631DEFUN(cfg_mgcp_force_realloc,
632 cfg_mgcp_force_realloc_cmd,
633 "force-realloc (0|1)",
634 "Force endpoint reallocation when the endpoint is still seized\n"
635 "Don't force reallocation\n" "force reallocation\n")
636{
637 g_cfg->trunk.force_realloc = atoi(argv[0]);
638 return CMD_SUCCESS;
639}
640
Philipp Maier87bd9be2017-08-22 16:35:41 +0200641DEFUN(cfg_mgcp_rtp_accept_all,
642 cfg_mgcp_rtp_accept_all_cmd,
643 "rtp-accept-all (0|1)",
644 "Accept all RTP packets, even when the originating IP/Port does not match\n"
645 "enable filter\n" "disable filter\n")
646{
647 g_cfg->trunk.rtp_accept_all = atoi(argv[0]);
648 return CMD_SUCCESS;
649}
650
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200651DEFUN(cfg_mgcp_number_endp,
652 cfg_mgcp_number_endp_cmd,
653 "number endpoints <0-65534>",
654 "Number options\n" "Endpoints available\n" "Number endpoints\n")
655{
656 /* + 1 as we start counting at one */
Philipp Maierfcd06552017-11-10 17:32:22 +0100657 g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200658 return CMD_SUCCESS;
659}
660
Philipp Maier87bd9be2017-08-22 16:35:41 +0200661DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200662{
663 g_cfg->trunk.omit_rtcp = 1;
664 return CMD_SUCCESS;
665}
666
667DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200668 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200669{
670 g_cfg->trunk.omit_rtcp = 0;
671 return CMD_SUCCESS;
672}
673
674DEFUN(cfg_mgcp_patch_rtp_ssrc,
675 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200676 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200677{
678 g_cfg->trunk.force_constant_ssrc = 1;
679 return CMD_SUCCESS;
680}
681
682DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
683 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200684 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200685{
686 g_cfg->trunk.force_constant_ssrc = 0;
687 return CMD_SUCCESS;
688}
689
690DEFUN(cfg_mgcp_patch_rtp_ts,
691 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200692 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200693{
694 g_cfg->trunk.force_aligned_timing = 1;
695 return CMD_SUCCESS;
696}
697
698DEFUN(cfg_mgcp_no_patch_rtp_ts,
699 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200700 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200701{
702 g_cfg->trunk.force_aligned_timing = 0;
703 return CMD_SUCCESS;
704}
705
706DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200707 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200708{
709 g_cfg->trunk.force_constant_ssrc = 0;
710 g_cfg->trunk.force_aligned_timing = 0;
711 return CMD_SUCCESS;
712}
713
714DEFUN(cfg_mgcp_rtp_keepalive,
715 cfg_mgcp_rtp_keepalive_cmd,
716 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200717 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200718{
719 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
720 return CMD_SUCCESS;
721}
722
723DEFUN(cfg_mgcp_rtp_keepalive_once,
724 cfg_mgcp_rtp_keepalive_once_cmd,
725 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200726 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200727{
728 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
729 return CMD_SUCCESS;
730}
731
732DEFUN(cfg_mgcp_no_rtp_keepalive,
733 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200734 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200735{
Philipp Maiere726d4f2017-11-01 10:41:34 +0100736 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200737 return CMD_SUCCESS;
738}
739
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200740#define CALL_AGENT_STR "Callagent information\n"
741DEFUN(cfg_mgcp_agent_addr,
742 cfg_mgcp_agent_addr_cmd,
743 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200744 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200745{
746 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
747 return CMD_SUCCESS;
748}
749
750ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200751 "call agent ip A.B.C.D",
752 CALL_AGENT_STR CALL_AGENT_STR IP_STR
753 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200754
Philipp Maier87bd9be2017-08-22 16:35:41 +0200755 DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
756 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200757{
758 struct mgcp_trunk_config *trunk;
759 int index = atoi(argv[0]);
760
761 trunk = mgcp_trunk_num(g_cfg, index);
762 if (!trunk)
763 trunk = mgcp_trunk_alloc(g_cfg, index);
764
765 if (!trunk) {
766 vty_out(vty, "%%Unable to allocate trunk %u.%s",
767 index, VTY_NEWLINE);
768 return CMD_WARNING;
769 }
770
771 vty->node = TRUNK_NODE;
772 vty->index = trunk;
773 return CMD_SUCCESS;
774}
775
776static int config_write_trunk(struct vty *vty)
777{
778 struct mgcp_trunk_config *trunk;
779
780 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
781 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
782 vty_out(vty, " sdp audio-payload number %d%s",
783 trunk->audio_payload, VTY_NEWLINE);
784 vty_out(vty, " sdp audio-payload name %s%s",
785 trunk->audio_name, VTY_NEWLINE);
786 vty_out(vty, " %ssdp audio-payload send-ptime%s",
787 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
788 vty_out(vty, " %ssdp audio-payload send-name%s",
789 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
790
791 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
792 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
793 else if (trunk->keepalive_interval)
794 vty_out(vty, " rtp keep-alive %d%s",
795 trunk->keepalive_interval, VTY_NEWLINE);
796 else
797 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200798 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200799 vty_out(vty, " force-realloc %d%s",
800 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200801 vty_out(vty, " rtp-accept-all %d%s",
802 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200803 if (trunk->omit_rtcp)
804 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
805 else
806 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
807 if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
808 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200809 trunk->force_constant_ssrc ? "" : "no ",
810 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200811 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200812 trunk->force_aligned_timing ? "" : "no ",
813 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200814 } else
815 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
816 if (trunk->audio_fmtp_extra)
817 vty_out(vty, " sdp audio fmtp-extra %s%s",
818 trunk->audio_fmtp_extra, VTY_NEWLINE);
819 vty_out(vty, " %sallow-transcoding%s",
820 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
821 }
822
823 return CMD_SUCCESS;
824}
825
826DEFUN(cfg_trunk_sdp_fmtp_extra,
827 cfg_trunk_sdp_fmtp_extra_cmd,
828 "sdp audio fmtp-extra .NAME",
829 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
830 "Extra Information\n")
831{
832 struct mgcp_trunk_config *trunk = vty->index;
833 char *txt = argv_concat(argv, argc, 0);
834 if (!txt)
835 return CMD_WARNING;
836
837 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
838 talloc_free(txt);
839 return CMD_SUCCESS;
840}
841
842DEFUN(cfg_trunk_payload_number,
843 cfg_trunk_payload_number_cmd,
844 "sdp audio-payload number <0-255>",
845 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
846{
847 struct mgcp_trunk_config *trunk = vty->index;
848 unsigned int payload = atoi(argv[0]);
849
850 trunk->audio_payload = payload;
851 return CMD_SUCCESS;
852}
853
854ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200855 "sdp audio payload number <0-255>",
856 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200857
Philipp Maier87bd9be2017-08-22 16:35:41 +0200858 DEFUN(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200859 cfg_trunk_payload_name_cmd,
860 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200861 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200862{
863 struct mgcp_trunk_config *trunk = vty->index;
864
865 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
866 return CMD_SUCCESS;
867}
868
869ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200870 "sdp audio payload name NAME",
871 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200872
Philipp Maier87bd9be2017-08-22 16:35:41 +0200873 DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200874 cfg_trunk_loop_cmd,
875 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200876 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200877{
878 struct mgcp_trunk_config *trunk = vty->index;
879
880 if (g_cfg->osmux) {
881 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
882 return CMD_WARNING;
883 }
884 trunk->audio_loop = atoi(argv[0]);
885 return CMD_SUCCESS;
886}
887
888DEFUN(cfg_trunk_sdp_payload_send_ptime,
889 cfg_trunk_sdp_payload_send_ptime_cmd,
890 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200891 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200892{
893 struct mgcp_trunk_config *trunk = vty->index;
894 trunk->audio_send_ptime = 1;
895 return CMD_SUCCESS;
896}
897
898DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
899 cfg_trunk_no_sdp_payload_send_ptime_cmd,
900 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200901 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200902{
903 struct mgcp_trunk_config *trunk = vty->index;
904 trunk->audio_send_ptime = 0;
905 return CMD_SUCCESS;
906}
907
908DEFUN(cfg_trunk_sdp_payload_send_name,
909 cfg_trunk_sdp_payload_send_name_cmd,
910 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200911 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200912{
913 struct mgcp_trunk_config *trunk = vty->index;
914 trunk->audio_send_name = 1;
915 return CMD_SUCCESS;
916}
917
918DEFUN(cfg_trunk_no_sdp_payload_send_name,
919 cfg_trunk_no_sdp_payload_send_name_cmd,
920 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200921 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200922{
923 struct mgcp_trunk_config *trunk = vty->index;
924 trunk->audio_send_name = 0;
925 return CMD_SUCCESS;
926}
927
Philipp Maier87bd9be2017-08-22 16:35:41 +0200928DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200929{
930 struct mgcp_trunk_config *trunk = vty->index;
931 trunk->omit_rtcp = 1;
932 return CMD_SUCCESS;
933}
934
935DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200936 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200937{
938 struct mgcp_trunk_config *trunk = vty->index;
939 trunk->omit_rtcp = 0;
940 return CMD_SUCCESS;
941}
942
943DEFUN(cfg_trunk_patch_rtp_ssrc,
944 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200945 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200946{
947 struct mgcp_trunk_config *trunk = vty->index;
948 trunk->force_constant_ssrc = 1;
949 return CMD_SUCCESS;
950}
951
952DEFUN(cfg_trunk_no_patch_rtp_ssrc,
953 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200954 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200955{
956 struct mgcp_trunk_config *trunk = vty->index;
957 trunk->force_constant_ssrc = 0;
958 return CMD_SUCCESS;
959}
960
961DEFUN(cfg_trunk_patch_rtp_ts,
962 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200963 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200964{
965 struct mgcp_trunk_config *trunk = vty->index;
966 trunk->force_aligned_timing = 1;
967 return CMD_SUCCESS;
968}
969
970DEFUN(cfg_trunk_no_patch_rtp_ts,
971 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200972 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200973{
974 struct mgcp_trunk_config *trunk = vty->index;
975 trunk->force_aligned_timing = 0;
976 return CMD_SUCCESS;
977}
978
979DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200980 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200981{
982 struct mgcp_trunk_config *trunk = vty->index;
983 trunk->force_constant_ssrc = 0;
984 trunk->force_aligned_timing = 0;
985 return CMD_SUCCESS;
986}
987
988DEFUN(cfg_trunk_rtp_keepalive,
989 cfg_trunk_rtp_keepalive_cmd,
990 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200991 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200992{
993 struct mgcp_trunk_config *trunk = vty->index;
994 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
995 return CMD_SUCCESS;
996}
997
998DEFUN(cfg_trunk_rtp_keepalive_once,
999 cfg_trunk_rtp_keepalive_once_cmd,
1000 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001001 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001002{
1003 struct mgcp_trunk_config *trunk = vty->index;
1004 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1005 return CMD_SUCCESS;
1006}
1007
1008DEFUN(cfg_trunk_no_rtp_keepalive,
1009 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001010 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001011{
1012 struct mgcp_trunk_config *trunk = vty->index;
1013 mgcp_trunk_set_keepalive(trunk, 0);
1014 return CMD_SUCCESS;
1015}
1016
1017DEFUN(cfg_trunk_allow_transcoding,
1018 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001019 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001020{
1021 struct mgcp_trunk_config *trunk = vty->index;
1022 trunk->no_audio_transcoding = 0;
1023 return CMD_SUCCESS;
1024}
1025
1026DEFUN(cfg_trunk_no_allow_transcoding,
1027 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001028 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001029{
1030 struct mgcp_trunk_config *trunk = vty->index;
1031 trunk->no_audio_transcoding = 1;
1032 return CMD_SUCCESS;
1033}
1034
Philipp Maier87bd9be2017-08-22 16:35:41 +02001035DEFUN(loop_conn,
1036 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001037 "loop-endpoint <0-64> NAME (0|1)",
1038 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001039 "The name in hex of the endpoint\n" "Disable the loop\n"
1040 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001041{
1042 struct mgcp_trunk_config *trunk;
1043 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001044 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001045
1046 trunk = find_trunk(g_cfg, atoi(argv[0]));
1047 if (!trunk) {
1048 vty_out(vty, "%%Trunk %d not found in the config.%s",
1049 atoi(argv[0]), VTY_NEWLINE);
1050 return CMD_WARNING;
1051 }
1052
1053 if (!trunk->endpoints) {
1054 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1055 trunk->trunk_nr, VTY_NEWLINE);
1056 return CMD_WARNING;
1057 }
1058
1059 int endp_no = strtoul(argv[1], NULL, 16);
1060 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1061 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001062 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001063 return CMD_WARNING;
1064 }
1065
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001066 endp = &trunk->endpoints[endp_no];
1067 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001068 llist_for_each_entry(conn, &endp->conns, entry) {
1069 if (conn->type == MGCP_CONN_TYPE_RTP)
1070 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1071 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1072 else {
1073 /* FIXME: Introduce support for other connection (E1)
1074 * types when implementation is available */
1075 vty_out(vty, "%%Can't enable SSRC patching,"
1076 "connection %s is not an RTP connection.%s",
1077 mgcp_conn_dump(conn), VTY_NEWLINE);
1078 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001079
Philipp Maier87bd9be2017-08-22 16:35:41 +02001080 if (loop)
1081 conn->mode = MGCP_CONN_LOOPBACK;
1082 else
1083 conn->mode = conn->mode_orig;
1084 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001085
1086 return CMD_SUCCESS;
1087}
1088
Philipp Maier87bd9be2017-08-22 16:35:41 +02001089DEFUN(tap_rtp,
1090 tap_rtp_cmd,
1091 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001092 "Forward data on endpoint to a different system\n" "Trunk number\n"
1093 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001094 "The connection id in hex\n"
1095 "Forward incoming data\n"
1096 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001097 "destination IP of the data\n" "destination port\n")
1098{
1099 struct mgcp_rtp_tap *tap;
1100 struct mgcp_trunk_config *trunk;
1101 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001102 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001103 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001104
1105 trunk = find_trunk(g_cfg, atoi(argv[0]));
1106 if (!trunk) {
1107 vty_out(vty, "%%Trunk %d not found in the config.%s",
1108 atoi(argv[0]), VTY_NEWLINE);
1109 return CMD_WARNING;
1110 }
1111
1112 if (!trunk->endpoints) {
1113 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1114 trunk->trunk_nr, VTY_NEWLINE);
1115 return CMD_WARNING;
1116 }
1117
1118 int endp_no = strtoul(argv[1], NULL, 16);
1119 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1120 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001121 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001122 return CMD_WARNING;
1123 }
1124
1125 endp = &trunk->endpoints[endp_no];
1126
Philipp Maier01d24a32017-11-21 17:26:09 +01001127 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001128 conn = mgcp_conn_get_rtp(endp, conn_id);
1129 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001130 vty_out(vty, "Conn ID %s is invalid.%s",
1131 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001132 return CMD_WARNING;
1133 }
1134
1135 if (strcmp(argv[3], "in") == 0)
1136 tap = &conn->tap_in;
1137 else if (strcmp(argv[3], "out") == 0)
1138 tap = &conn->tap_out;
1139 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001140 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1141 return CMD_WARNING;
1142 }
1143
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001144 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001145 inet_aton(argv[4], &tap->forward.sin_addr);
1146 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001147 tap->enabled = 1;
1148 return CMD_SUCCESS;
1149}
1150
1151DEFUN(free_endp, free_endp_cmd,
1152 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001153 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001154{
1155 struct mgcp_trunk_config *trunk;
1156 struct mgcp_endpoint *endp;
1157
1158 trunk = find_trunk(g_cfg, atoi(argv[0]));
1159 if (!trunk) {
1160 vty_out(vty, "%%Trunk %d not found in the config.%s",
1161 atoi(argv[0]), VTY_NEWLINE);
1162 return CMD_WARNING;
1163 }
1164
1165 if (!trunk->endpoints) {
1166 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1167 trunk->trunk_nr, VTY_NEWLINE);
1168 return CMD_WARNING;
1169 }
1170
1171 int endp_no = strtoul(argv[1], NULL, 16);
1172 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1173 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001174 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001175 return CMD_WARNING;
1176 }
1177
1178 endp = &trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001179 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001180 return CMD_SUCCESS;
1181}
1182
1183DEFUN(reset_endp, reset_endp_cmd,
1184 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001185 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001186{
1187 struct mgcp_trunk_config *trunk;
1188 struct mgcp_endpoint *endp;
1189 int endp_no, rc;
1190
1191 trunk = find_trunk(g_cfg, atoi(argv[0]));
1192 if (!trunk) {
1193 vty_out(vty, "%%Trunk %d not found in the config.%s",
1194 atoi(argv[0]), VTY_NEWLINE);
1195 return CMD_WARNING;
1196 }
1197
1198 if (!trunk->endpoints) {
1199 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1200 trunk->trunk_nr, VTY_NEWLINE);
1201 return CMD_WARNING;
1202 }
1203
1204 endp_no = strtoul(argv[1], NULL, 16);
1205 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1206 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001207 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001208 return CMD_WARNING;
1209 }
1210
1211 endp = &trunk->endpoints[endp_no];
1212 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1213 if (rc < 0) {
1214 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1215 return CMD_WARNING;
1216 }
1217 return CMD_SUCCESS;
1218}
1219
1220DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001221 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001222{
1223 int rc;
1224
1225 rc = mgcp_send_reset_all(g_cfg);
1226 if (rc < 0) {
1227 vty_out(vty, "Error %d during endpoint reset.%s",
1228 rc, VTY_NEWLINE);
1229 return CMD_WARNING;
1230 }
1231 return CMD_SUCCESS;
1232}
1233
1234#define OSMUX_STR "RTP multiplexing\n"
1235DEFUN(cfg_mgcp_osmux,
1236 cfg_mgcp_osmux_cmd,
1237 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001238 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001239{
1240 if (strcmp(argv[0], "off") == 0) {
1241 g_cfg->osmux = OSMUX_USAGE_OFF;
1242 return CMD_SUCCESS;
1243 }
1244
Philipp Maier87bd9be2017-08-22 16:35:41 +02001245 /* Since OSMUX support is not finished, we do not
1246 * allow to turn it on yet. */
1247 vty_out(vty, "OSMUX currently unavailable in this software version.%s", VTY_NEWLINE);
1248 return CMD_WARNING;
Philipp Maier2982e422017-11-07 12:27:48 +01001249#if 0
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001250 if (strcmp(argv[0], "on") == 0)
1251 g_cfg->osmux = OSMUX_USAGE_ON;
1252 else if (strcmp(argv[0], "only") == 0)
1253 g_cfg->osmux = OSMUX_USAGE_ONLY;
1254
1255 if (g_cfg->trunk.audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001256 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001257 return CMD_WARNING;
1258 }
1259
1260 return CMD_SUCCESS;
Philipp Maier2982e422017-11-07 12:27:48 +01001261#endif
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001262}
1263
1264DEFUN(cfg_mgcp_osmux_ip,
1265 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001266 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001267{
1268 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1269 return CMD_SUCCESS;
1270}
1271
1272DEFUN(cfg_mgcp_osmux_batch_factor,
1273 cfg_mgcp_osmux_batch_factor_cmd,
1274 "osmux batch-factor <1-8>",
1275 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1276{
1277 g_cfg->osmux_batch = atoi(argv[0]);
1278 return CMD_SUCCESS;
1279}
1280
1281DEFUN(cfg_mgcp_osmux_batch_size,
1282 cfg_mgcp_osmux_batch_size_cmd,
1283 "osmux batch-size <1-65535>",
1284 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1285{
1286 g_cfg->osmux_batch_size = atoi(argv[0]);
1287 return CMD_SUCCESS;
1288}
1289
1290DEFUN(cfg_mgcp_osmux_port,
1291 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001292 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001293{
1294 g_cfg->osmux_port = atoi(argv[0]);
1295 return CMD_SUCCESS;
1296}
1297
1298DEFUN(cfg_mgcp_osmux_dummy,
1299 cfg_mgcp_osmux_dummy_cmd,
1300 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001301 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1302 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001303{
1304 if (strcmp(argv[0], "on") == 0)
1305 g_cfg->osmux_dummy = 1;
1306 else if (strcmp(argv[0], "off") == 0)
1307 g_cfg->osmux_dummy = 0;
1308
1309 return CMD_SUCCESS;
1310}
1311
Philipp Maier12943ea2018-01-17 15:40:25 +01001312DEFUN(cfg_mgcp_domain,
1313 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001314 "domain NAME",
1315 "Set the domain part expected in MGCP messages' endpoint names\n"
1316 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001317{
1318 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1319 return CMD_SUCCESS;
1320}
1321
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001322int mgcp_vty_init(void)
1323{
1324 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001325 install_element_ve(&show_mgcp_endpoint_cmd);
1326 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001327 install_element(ENABLE_NODE, &loop_conn_cmd);
1328 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001329 install_element(ENABLE_NODE, &free_endp_cmd);
1330 install_element(ENABLE_NODE, &reset_endp_cmd);
1331 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1332
1333 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1334 install_node(&mgcp_node, config_write_mgcp);
1335
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001336 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001337 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1338 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1339 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001340 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001341 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001342 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001343 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001344 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001345 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001346 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1347 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001348 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1349 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1350 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1351 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1352 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1353 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1354 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1355 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1356 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001357 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1358 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1359 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1360 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1361 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1362 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001363 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001364 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1365 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1366 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1367 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1368 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1369 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1370 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1371 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
1372 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1373 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1374 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1375 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1376 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1377 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1378 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1379 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1380 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1381 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1382 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1383 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1384 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001385 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001386
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001387 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1388 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001389 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1390 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1391 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1392 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1393 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1394 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1395 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1396 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1397 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1398 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1399 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1400 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1401 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
1402 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1403 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1404 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1405 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1406 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1407 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1408 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1409 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1410 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1411
1412 return 0;
1413}
1414
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001415int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1416 enum mgcp_role role)
1417{
1418 int rc;
1419 struct mgcp_trunk_config *trunk;
1420
1421 cfg->osmux_port = OSMUX_PORT;
1422 cfg->osmux_batch = 4;
1423 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1424
1425 g_cfg = cfg;
1426 rc = vty_read_config_file(config_file, NULL);
1427 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001428 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1429 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001430 return rc;
1431 }
1432
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001433 if (!g_cfg->source_addr) {
1434 fprintf(stderr, "You need to specify a bind address.\n");
1435 return -1;
1436 }
1437
Philipp Maier48454982017-11-10 16:46:41 +01001438 if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001439 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001440 "Failed to initialize the virtual trunk (%d endpoints)\n",
1441 g_cfg->trunk.number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001442 return -1;
1443 }
1444
1445 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maier48454982017-11-10 16:46:41 +01001446 if (mgcp_endpoints_allocate(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001447 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001448 "Failed to initialize trunk %d (%d endpoints)\n",
1449 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001450 return -1;
1451 }
1452 }
1453 cfg->role = role;
1454
1455 return 0;
1456}