blob: fa175e154896fcebe8eeb383cb607664a9761fea [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"
Philipp Maier9fc8a022019-02-20 12:26:52 +010040#define RTP_TS101318_RFC5993_CONV_STR "Convert GSM-HR from TS101318 to RFC5993 and vice versa\n"
41
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020042
43static struct mgcp_config *g_cfg = NULL;
44
45static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
46{
47 struct mgcp_trunk_config *trunk;
48
49 if (nr == 0)
50 trunk = &cfg->trunk;
51 else
52 trunk = mgcp_trunk_num(cfg, nr);
53
54 return trunk;
55}
56
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020057struct cmd_node mgcp_node = {
58 MGCP_NODE,
59 "%s(config-mgcp)# ",
60 1,
61};
62
63struct cmd_node trunk_node = {
64 TRUNK_NODE,
65 "%s(config-mgcp-trunk)# ",
66 1,
67};
68
69static int config_write_mgcp(struct vty *vty)
70{
71 vty_out(vty, "mgcp%s", VTY_NEWLINE);
Philipp Maier12943ea2018-01-17 15:40:25 +010072 vty_out(vty, " domain %s%s", g_cfg->domain, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020073 if (g_cfg->local_ip)
74 vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020075 vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
76 vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
Philipp Maierf1889d82017-11-08 14:59:39 +010077 vty_out(vty, " rtp port-range %u %u%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +020078 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end,
79 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020080 if (g_cfg->net_ports.bind_addr)
Philipp Maierf1889d82017-11-08 14:59:39 +010081 vty_out(vty, " rtp bind-ip %s%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +020082 g_cfg->net_ports.bind_addr, VTY_NEWLINE);
Philipp Maier1cb1e382017-11-02 17:16:04 +010083 if (g_cfg->net_ports.bind_addr_probe)
84 vty_out(vty, " rtp ip-probing%s", VTY_NEWLINE);
85 else
86 vty_out(vty, " no rtp ip-probing%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +020087 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
88 if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE)
89 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
90 else if (g_cfg->trunk.keepalive_interval)
91 vty_out(vty, " rtp keep-alive %d%s",
92 g_cfg->trunk.keepalive_interval, VTY_NEWLINE);
93 else
94 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
95
96 if (g_cfg->trunk.omit_rtcp)
97 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
98 else
99 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200100 if (g_cfg->trunk.force_constant_ssrc
Philipp Maier9fc8a022019-02-20 12:26:52 +0100101 || g_cfg->trunk.force_aligned_timing
102 || g_cfg->trunk.rfc5993_hr_convert) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200103 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200104 g_cfg->trunk.force_constant_ssrc ? "" : "no ",
105 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200106 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200107 g_cfg->trunk.force_aligned_timing ? "" : "no ",
108 VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100109 vty_out(vty, " %srtp-patch rfc5993hr%s",
110 g_cfg->trunk.rfc5993_hr_convert ? "" : "no ",
111 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200112 } else
113 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
114 if (g_cfg->trunk.audio_payload != -1)
115 vty_out(vty, " sdp audio-payload number %d%s",
116 g_cfg->trunk.audio_payload, VTY_NEWLINE);
117 if (g_cfg->trunk.audio_name)
118 vty_out(vty, " sdp audio-payload name %s%s",
119 g_cfg->trunk.audio_name, VTY_NEWLINE);
120 if (g_cfg->trunk.audio_fmtp_extra)
121 vty_out(vty, " sdp audio fmtp-extra %s%s",
122 g_cfg->trunk.audio_fmtp_extra, VTY_NEWLINE);
123 vty_out(vty, " %ssdp audio-payload send-ptime%s",
124 g_cfg->trunk.audio_send_ptime ? "" : "no ", VTY_NEWLINE);
125 vty_out(vty, " %ssdp audio-payload send-name%s",
126 g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200127 vty_out(vty, " loop %u%s", ! !g_cfg->trunk.audio_loop, VTY_NEWLINE);
128 vty_out(vty, " number endpoints %u%s",
Philipp Maierfcd06552017-11-10 17:32:22 +0100129 g_cfg->trunk.vty_number_endpoints - 1, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200130 vty_out(vty, " %sallow-transcoding%s",
131 g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE);
132 if (g_cfg->call_agent_addr)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200133 vty_out(vty, " call-agent ip %s%s", g_cfg->call_agent_addr,
134 VTY_NEWLINE);
135 if (g_cfg->force_ptime > 0)
136 vty_out(vty, " rtp force-ptime %d%s", g_cfg->force_ptime,
137 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200138
139 switch (g_cfg->osmux) {
140 case OSMUX_USAGE_ON:
141 vty_out(vty, " osmux on%s", VTY_NEWLINE);
142 break;
143 case OSMUX_USAGE_ONLY:
144 vty_out(vty, " osmux only%s", VTY_NEWLINE);
145 break;
146 case OSMUX_USAGE_OFF:
147 default:
148 vty_out(vty, " osmux off%s", VTY_NEWLINE);
149 break;
150 }
151 if (g_cfg->osmux) {
152 vty_out(vty, " osmux bind-ip %s%s",
153 g_cfg->osmux_addr, VTY_NEWLINE);
154 vty_out(vty, " osmux batch-factor %d%s",
155 g_cfg->osmux_batch, VTY_NEWLINE);
156 vty_out(vty, " osmux batch-size %u%s",
157 g_cfg->osmux_batch_size, VTY_NEWLINE);
158 vty_out(vty, " osmux port %u%s",
159 g_cfg->osmux_port, VTY_NEWLINE);
160 vty_out(vty, " osmux dummy %s%s",
161 g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
162 }
Oliver Smithe36b7752019-01-22 16:31:36 +0100163
164 if (g_cfg->conn_timeout)
165 vty_out(vty, " conn-timeout %u%s", g_cfg->conn_timeout, VTY_NEWLINE);
166
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200167 return CMD_SUCCESS;
168}
169
Philipp Maiercede2a42018-07-03 14:14:21 +0200170static void dump_rtp_end(struct vty *vty, struct mgcp_conn_rtp *conn)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200171{
Philipp Maiercede2a42018-07-03 14:14:21 +0200172 struct mgcp_rtp_state *state = &conn->state;
173 struct mgcp_rtp_end *end = &conn->end;
Philipp Maierbc0346e2018-06-07 09:52:16 +0200174 struct mgcp_rtp_codec *codec = end->codec;
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100175 struct rate_ctr *tx_packets, *tx_bytes;
176 struct rate_ctr *rx_packets, *rx_bytes;
Philipp Maiercede2a42018-07-03 14:14:21 +0200177 struct rate_ctr *dropped_packets;
178
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100179 tx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_TX_CTR];
180 tx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_TX_CTR];
181 rx_packets = &conn->rate_ctr_group->ctr[RTP_PACKETS_RX_CTR];
182 rx_bytes = &conn->rate_ctr_group->ctr[RTP_OCTETS_RX_CTR];
Philipp Maiercede2a42018-07-03 14:14:21 +0200183 dropped_packets = &conn->rate_ctr_group->ctr[RTP_DROPPED_PACKETS_CTR];
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200184
185 vty_out(vty,
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100186 " Packets Sent: %" PRIu64 " (%" PRIu64 " bytes total)%s"
187 " Packets Received: %" PRIu64 " (%" PRIu64 " bytes total)%s"
Philipp Maierbca0ef62018-07-09 17:20:51 +0200188 " Timestamp Errs: %" PRIu64 "->%" PRIu64 "%s"
189 " Dropped Packets: %" PRIu64 "%s"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200190 " Payload Type: %d Rate: %u Channels: %d %s"
191 " Frame Duration: %u Frame Denominator: %u%s"
192 " FPP: %d Packet Duration: %u%s"
193 " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
194 " Output-Enabled: %d Force-PTIME: %d%s",
Stefan Sperlingb7974e22018-10-29 13:22:00 +0100195 tx_packets->current, tx_bytes->current, VTY_NEWLINE,
196 rx_packets->current, rx_bytes->current, VTY_NEWLINE,
Philipp Maier9e1d1642018-05-09 16:26:34 +0200197 state->in_stream.err_ts_ctr->current,
198 state->out_stream.err_ts_ctr->current,
199 VTY_NEWLINE,
Philipp Maiercede2a42018-07-03 14:14:21 +0200200 dropped_packets->current, VTY_NEWLINE,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200201 codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200202 codec->frame_duration_num, codec->frame_duration_den,
203 VTY_NEWLINE, end->frames_per_packet, end->packet_duration_ms,
204 VTY_NEWLINE, end->fmtp_extra, codec->audio_name,
205 codec->subtype_name, VTY_NEWLINE, end->output_enabled,
206 end->force_output_ptime, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200207}
208
Stefan Sperling12086582018-06-26 15:26:28 +0200209static void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp, int epidx,
210 int trunk_nr, enum mgcp_trunk_type trunk_type, int show_stats)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200211{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200212 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200213
Stefan Sperling12086582018-06-26 15:26:28 +0200214 vty_out(vty, "%s trunk %d endpoint %s%.2x:%s",
215 trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1", trunk_nr,
216 trunk_type == MGCP_TRUNK_VIRTUAL ? MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK : "",
217 epidx, VTY_NEWLINE);
218
219 if (llist_empty(&endp->conns)) {
220 vty_out(vty, " No active connections%s", VTY_NEWLINE);
221 return;
222 }
223
224 llist_for_each_entry(conn, &endp->conns, entry) {
225 vty_out(vty, " CONN: %s%s", mgcp_conn_dump(conn), VTY_NEWLINE);
226
227 if (show_stats) {
Oliver Smithe36b7752019-01-22 16:31:36 +0100228 if (endp->cfg->conn_timeout) {
229 struct timeval remaining;
230 osmo_timer_remaining(&conn->watchdog, NULL, &remaining);
231 vty_out(vty, " Currently remaining timeout (seconds): %d.%06d%s",
232 (int)remaining.tv_sec, (int)remaining.tv_usec, VTY_NEWLINE);
233 }
234
Stefan Sperling12086582018-06-26 15:26:28 +0200235 /* FIXME: Also add verbosity for other
236 * connection types (E1) as soon as
237 * the implementation is available */
238 if (conn->type == MGCP_CONN_TYPE_RTP) {
239 dump_rtp_end(vty, &conn->u.rtp);
240 }
241 }
242 }
243}
244
245static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int show_stats)
246{
247 int i;
248
249 vty_out(vty, "%s trunk %d with %d endpoints:%s",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200250 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
251 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
252
253 if (!cfg->endpoints) {
254 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
255 return;
256 }
257
Neels Hofmeyr6c92f9d2020-03-05 23:09:13 +0100258 for (i = 0; i < cfg->number_endpoints; ++i) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200259 struct mgcp_endpoint *endp = &cfg->endpoints[i];
Stefan Sperling12086582018-06-26 15:26:28 +0200260 dump_endpoint(vty, endp, i, cfg->trunk_nr, cfg->trunk_type, show_stats);
261 if (i < cfg->number_endpoints - 1)
262 vty_out(vty, "%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200263 }
Stefan Sperling1e174872018-10-25 18:36:10 +0200264
Alexander Chemerisdab89af2020-05-05 17:15:21 +0300265 if (show_stats) {
266 vty_out(vty, "%s", VTY_NEWLINE);
267 vty_out(vty, "Rate counters:%s", VTY_NEWLINE);
268 }
Stefan Sperling1e174872018-10-25 18:36:10 +0200269 if (show_stats && cfg->mgcp_crcx_ctr_group) {
270 vty_out(vty, " %s:%s", cfg->mgcp_crcx_ctr_group->desc->group_description, VTY_NEWLINE);
271 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_crcx_ctr_group);
272 }
Stefan Sperling8ab3fbb2018-10-30 14:57:25 +0100273 if (show_stats && cfg->mgcp_dlcx_ctr_group) {
274 vty_out(vty, " %s:%s", cfg->mgcp_dlcx_ctr_group->desc->group_description, VTY_NEWLINE);
275 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_dlcx_ctr_group);
276 }
Stefan Sperlingaa823bf2018-10-29 14:51:41 +0100277 if (show_stats && cfg->mgcp_mdcx_ctr_group) {
278 vty_out(vty, " %s:%s", cfg->mgcp_mdcx_ctr_group->desc->group_description, VTY_NEWLINE);
279 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->mgcp_mdcx_ctr_group);
280 }
Stefan Sperlingba25eab2018-10-30 14:32:31 +0100281 if (show_stats && cfg->all_rtp_conn_stats) {
282 vty_out(vty, " %s:%s", cfg->all_rtp_conn_stats->desc->group_description, VTY_NEWLINE);
283 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->all_rtp_conn_stats);
284 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200285}
286
Stefan Sperling12086582018-06-26 15:26:28 +0200287#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
288
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200289DEFUN(show_mcgp, show_mgcp_cmd,
290 "show mgcp [stats]",
291 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200292 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200293 "Include Statistics\n")
294{
295 struct mgcp_trunk_config *trunk;
296 int show_stats = argc >= 1;
297
298 dump_trunk(vty, &g_cfg->trunk, show_stats);
299
300 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200301 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200302
303 if (g_cfg->osmux)
Pau Espin Pedrol8de58e72019-04-24 13:33:46 +0200304 vty_out(vty, "Osmux used CID: %d%s", osmux_cid_pool_count_used(),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200305 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200306
307 return CMD_SUCCESS;
308}
309
Stefan Sperling12086582018-06-26 15:26:28 +0200310static void
311dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk_config *trunk, const char *epname)
312{
313 const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
314 unsigned long epidx;
315 char *endp;
316 int i;
317
318 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)
319 epname += virt_prefix_len;
320 errno = 0;
321 epidx = strtoul(epname, &endp, 16);
322 if (epname[0] == '\0' || *endp != '\0') {
323 vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);
324 return;
325 }
326 if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */
327 || epidx >= trunk->number_endpoints) {
328 vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);
329 return;
330 }
331
332 for (i = 0; i < trunk->number_endpoints; ++i) {
333 struct mgcp_endpoint *endp = &trunk->endpoints[i];
334 if (i == epidx) {
335 dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);
336 break;
337 }
338 }
339}
340
341DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
342 "show mgcp endpoint NAME",
343 SHOW_STR
344 SHOW_MGCP_STR
345 "Display information about an endpoint\n" "The name of the endpoint\n")
346{
347 struct mgcp_trunk_config *trunk;
348
349 dump_mgcp_endpoint(vty, &g_cfg->trunk, argv[0]);
350 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
351 dump_mgcp_endpoint(vty, trunk, argv[0]);
352
353 return CMD_SUCCESS;
354}
355
356DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
357 "show mgcp trunk <0-64> endpoint NAME",
358 SHOW_STR
359 SHOW_MGCP_STR
360 "Display information about a trunk\n" "Trunk number\n"
361 "Display information about an endpoint\n" "The name of the endpoint\n")
362{
363 struct mgcp_trunk_config *trunk;
364 int trunkidx = atoi(argv[0]);
365
366 trunk = find_trunk(g_cfg, trunkidx);
367 if (!trunk) {
368 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
369 return CMD_WARNING;
370 }
371
372 dump_mgcp_endpoint(vty, trunk, argv[1]);
373 return CMD_SUCCESS;
374}
375
Philipp Maier87bd9be2017-08-22 16:35:41 +0200376DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200377{
378 vty->node = MGCP_NODE;
379 return CMD_SUCCESS;
380}
381
382DEFUN(cfg_mgcp_local_ip,
383 cfg_mgcp_local_ip_cmd,
384 "local ip A.B.C.D",
385 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200386 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200387{
388 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
389 return CMD_SUCCESS;
390}
391
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200392#define BIND_STR "Listen/Bind related socket option\n"
393DEFUN(cfg_mgcp_bind_ip,
394 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200395 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200396{
397 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
398 return CMD_SUCCESS;
399}
400
401DEFUN(cfg_mgcp_bind_port,
402 cfg_mgcp_bind_port_cmd,
403 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200404 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200405{
406 unsigned int port = atoi(argv[0]);
407 g_cfg->source_port = port;
408 return CMD_SUCCESS;
409}
410
411DEFUN(cfg_mgcp_bind_early,
412 cfg_mgcp_bind_early_cmd,
413 "bind early (0|1)",
414 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200415 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200416{
417 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
418 return CMD_WARNING;
419}
420
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200421#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200422#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200423#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200424#define RANGE_START_STR "Start of the range of ports\n"
425#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200426
Philipp Maierf1889d82017-11-08 14:59:39 +0100427DEFUN(cfg_mgcp_rtp_port_range,
428 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200429 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200430 RTP_STR "Range of ports to use for the NET side\n"
431 RANGE_START_STR RANGE_END_STR)
432{
Philipp Maiera19547b2018-05-22 13:44:34 +0200433 int start;
434 int end;
435
436 start = atoi(argv[0]);
437 end = atoi(argv[1]);
438
439 if (end < start) {
440 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
441 end, start, VTY_NEWLINE);
442 return CMD_WARNING;
443 }
444
445 if (start & 1) {
446 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
447 start, start & 0xFFFE, VTY_NEWLINE);
448 start &= 0xFFFE;
449 }
450
451 if ((end & 1) == 0) {
452 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
453 end, end | 1, VTY_NEWLINE);
454 end |= 1;
455 }
456
457 g_cfg->net_ports.range_start = start;
458 g_cfg->net_ports.range_end = end;
459 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
460
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200461 return CMD_SUCCESS;
462}
Philipp Maierf1889d82017-11-08 14:59:39 +0100463ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
464 cfg_mgcp_rtp_net_range_cmd,
465 "rtp net-range <0-65534> <0-65534>",
466 RTP_STR "Range of ports to use for the NET side\n"
467 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200468
Philipp Maierf1889d82017-11-08 14:59:39 +0100469DEFUN(cfg_mgcp_rtp_bind_ip,
470 cfg_mgcp_rtp_bind_ip_cmd,
471 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200472 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
473{
474 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
475 return CMD_SUCCESS;
476}
Philipp Maierf1889d82017-11-08 14:59:39 +0100477ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
478 cfg_mgcp_rtp_net_bind_ip_cmd,
479 "rtp net-bind-ip A.B.C.D",
480 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200481
Philipp Maierf1889d82017-11-08 14:59:39 +0100482DEFUN(cfg_mgcp_rtp_no_bind_ip,
483 cfg_mgcp_rtp_no_bind_ip_cmd,
484 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200485 NO_STR RTP_STR "Bind endpoints facing the Network\n"
486 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200487{
488 talloc_free(g_cfg->net_ports.bind_addr);
489 g_cfg->net_ports.bind_addr = NULL;
490 return CMD_SUCCESS;
491}
Philipp Maierf1889d82017-11-08 14:59:39 +0100492ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
493 cfg_mgcp_rtp_no_net_bind_ip_cmd,
494 "no rtp net-bind-ip",
495 NO_STR RTP_STR "Bind endpoints facing the Network\n"
496 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200497
Philipp Maier1cb1e382017-11-02 17:16:04 +0100498DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
499 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
500 "rtp ip-probing",
501 RTP_STR "automatic rtp bind ip selection\n")
502{
503 g_cfg->net_ports.bind_addr_probe = true;
504 return CMD_SUCCESS;
505}
506
507DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
508 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
509 "no rtp ip-probing",
510 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
511{
512 g_cfg->net_ports.bind_addr_probe = false;
513 return CMD_SUCCESS;
514}
515
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200516DEFUN(cfg_mgcp_rtp_ip_dscp,
517 cfg_mgcp_rtp_ip_dscp_cmd,
518 "rtp ip-dscp <0-255>",
519 RTP_STR
520 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
521{
522 int dscp = atoi(argv[0]);
523 g_cfg->endp_dscp = dscp;
524 return CMD_SUCCESS;
525}
526
527ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200528 "rtp ip-tos <0-255>",
529 RTP_STR
530 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
531#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
532 DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200533 cfg_mgcp_rtp_force_ptime_cmd,
534 "rtp force-ptime (10|20|40)",
535 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200536 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200537{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200538 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200539 return CMD_SUCCESS;
540}
541
542DEFUN(cfg_mgcp_no_rtp_force_ptime,
543 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200544 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200545{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200546 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200547 return CMD_SUCCESS;
548}
549
550DEFUN(cfg_mgcp_sdp_fmtp_extra,
551 cfg_mgcp_sdp_fmtp_extra_cmd,
552 "sdp audio fmtp-extra .NAME",
553 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
554 "Extra Information\n")
555{
556 char *txt = argv_concat(argv, argc, 0);
557 if (!txt)
558 return CMD_WARNING;
559
560 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
561 talloc_free(txt);
562 return CMD_SUCCESS;
563}
564
565DEFUN(cfg_mgcp_allow_transcoding,
566 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200567 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200568{
569 g_cfg->trunk.no_audio_transcoding = 0;
570 return CMD_SUCCESS;
571}
572
573DEFUN(cfg_mgcp_no_allow_transcoding,
574 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200575 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200576{
577 g_cfg->trunk.no_audio_transcoding = 1;
578 return CMD_SUCCESS;
579}
580
581#define SDP_STR "SDP File related options\n"
582#define AUDIO_STR "Audio payload options\n"
583DEFUN(cfg_mgcp_sdp_payload_number,
584 cfg_mgcp_sdp_payload_number_cmd,
585 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200586 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200587{
588 unsigned int payload = atoi(argv[0]);
589 g_cfg->trunk.audio_payload = payload;
590 return CMD_SUCCESS;
591}
592
Philipp Maier87bd9be2017-08-22 16:35:41 +0200593ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
594 cfg_mgcp_sdp_payload_number_cmd_old,
595 "sdp audio payload number <0-255>",
596 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200597
Philipp Maier87bd9be2017-08-22 16:35:41 +0200598 DEFUN(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200599 cfg_mgcp_sdp_payload_name_cmd,
600 "sdp audio-payload name NAME",
601 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
602{
603 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
604 return CMD_SUCCESS;
605}
606
607ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200608 "sdp audio payload name NAME",
609 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200610
Philipp Maier87bd9be2017-08-22 16:35:41 +0200611 DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200612 cfg_mgcp_sdp_payload_send_ptime_cmd,
613 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200614 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200615{
616 g_cfg->trunk.audio_send_ptime = 1;
617 return CMD_SUCCESS;
618}
619
620DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
621 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
622 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200623 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200624{
625 g_cfg->trunk.audio_send_ptime = 0;
626 return CMD_SUCCESS;
627}
628
629DEFUN(cfg_mgcp_sdp_payload_send_name,
630 cfg_mgcp_sdp_payload_send_name_cmd,
631 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200632 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200633{
634 g_cfg->trunk.audio_send_name = 1;
635 return CMD_SUCCESS;
636}
637
638DEFUN(cfg_mgcp_no_sdp_payload_send_name,
639 cfg_mgcp_no_sdp_payload_send_name_cmd,
640 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200641 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200642{
643 g_cfg->trunk.audio_send_name = 0;
644 return CMD_SUCCESS;
645}
646
647DEFUN(cfg_mgcp_loop,
648 cfg_mgcp_loop_cmd,
649 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200650 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200651{
652 if (g_cfg->osmux) {
653 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
654 return CMD_WARNING;
655 }
656 g_cfg->trunk.audio_loop = atoi(argv[0]);
657 return CMD_SUCCESS;
658}
659
660DEFUN(cfg_mgcp_force_realloc,
661 cfg_mgcp_force_realloc_cmd,
662 "force-realloc (0|1)",
663 "Force endpoint reallocation when the endpoint is still seized\n"
664 "Don't force reallocation\n" "force reallocation\n")
665{
666 g_cfg->trunk.force_realloc = atoi(argv[0]);
667 return CMD_SUCCESS;
668}
669
Philipp Maier87bd9be2017-08-22 16:35:41 +0200670DEFUN(cfg_mgcp_rtp_accept_all,
671 cfg_mgcp_rtp_accept_all_cmd,
672 "rtp-accept-all (0|1)",
673 "Accept all RTP packets, even when the originating IP/Port does not match\n"
674 "enable filter\n" "disable filter\n")
675{
676 g_cfg->trunk.rtp_accept_all = atoi(argv[0]);
677 return CMD_SUCCESS;
678}
679
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200680DEFUN(cfg_mgcp_number_endp,
681 cfg_mgcp_number_endp_cmd,
682 "number endpoints <0-65534>",
683 "Number options\n" "Endpoints available\n" "Number endpoints\n")
684{
685 /* + 1 as we start counting at one */
Philipp Maierfcd06552017-11-10 17:32:22 +0100686 g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200687 return CMD_SUCCESS;
688}
689
Philipp Maier87bd9be2017-08-22 16:35:41 +0200690DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200691{
692 g_cfg->trunk.omit_rtcp = 1;
693 return CMD_SUCCESS;
694}
695
696DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200697 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200698{
699 g_cfg->trunk.omit_rtcp = 0;
700 return CMD_SUCCESS;
701}
702
703DEFUN(cfg_mgcp_patch_rtp_ssrc,
704 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200705 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200706{
707 g_cfg->trunk.force_constant_ssrc = 1;
708 return CMD_SUCCESS;
709}
710
711DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
712 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200713 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200714{
715 g_cfg->trunk.force_constant_ssrc = 0;
716 return CMD_SUCCESS;
717}
718
719DEFUN(cfg_mgcp_patch_rtp_ts,
720 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200721 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200722{
723 g_cfg->trunk.force_aligned_timing = 1;
724 return CMD_SUCCESS;
725}
726
727DEFUN(cfg_mgcp_no_patch_rtp_ts,
728 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200729 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200730{
731 g_cfg->trunk.force_aligned_timing = 0;
732 return CMD_SUCCESS;
733}
734
Philipp Maier9fc8a022019-02-20 12:26:52 +0100735DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
736 cfg_mgcp_patch_rtp_rfc5993hr_cmd,
737 "rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
738{
739 g_cfg->trunk.rfc5993_hr_convert = true;
740 return CMD_SUCCESS;
741}
742
743DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
744 cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
745 "no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
746{
747 g_cfg->trunk.rfc5993_hr_convert = false;
748 return CMD_SUCCESS;
749}
750
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200751DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200752 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200753{
754 g_cfg->trunk.force_constant_ssrc = 0;
755 g_cfg->trunk.force_aligned_timing = 0;
Philipp Maier9fc8a022019-02-20 12:26:52 +0100756 g_cfg->trunk.rfc5993_hr_convert = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200757 return CMD_SUCCESS;
758}
759
760DEFUN(cfg_mgcp_rtp_keepalive,
761 cfg_mgcp_rtp_keepalive_cmd,
762 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200763 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200764{
765 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
766 return CMD_SUCCESS;
767}
768
769DEFUN(cfg_mgcp_rtp_keepalive_once,
770 cfg_mgcp_rtp_keepalive_once_cmd,
771 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200772 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200773{
774 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
775 return CMD_SUCCESS;
776}
777
778DEFUN(cfg_mgcp_no_rtp_keepalive,
779 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200780 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200781{
Philipp Maiere726d4f2017-11-01 10:41:34 +0100782 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200783 return CMD_SUCCESS;
784}
785
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200786#define CALL_AGENT_STR "Callagent information\n"
787DEFUN(cfg_mgcp_agent_addr,
788 cfg_mgcp_agent_addr_cmd,
789 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200790 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200791{
792 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
793 return CMD_SUCCESS;
794}
795
796ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200797 "call agent ip A.B.C.D",
798 CALL_AGENT_STR CALL_AGENT_STR IP_STR
799 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200800
Philipp Maier87bd9be2017-08-22 16:35:41 +0200801 DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
802 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200803{
804 struct mgcp_trunk_config *trunk;
805 int index = atoi(argv[0]);
806
807 trunk = mgcp_trunk_num(g_cfg, index);
808 if (!trunk)
809 trunk = mgcp_trunk_alloc(g_cfg, index);
810
811 if (!trunk) {
812 vty_out(vty, "%%Unable to allocate trunk %u.%s",
813 index, VTY_NEWLINE);
814 return CMD_WARNING;
815 }
816
817 vty->node = TRUNK_NODE;
818 vty->index = trunk;
819 return CMD_SUCCESS;
820}
821
822static int config_write_trunk(struct vty *vty)
823{
824 struct mgcp_trunk_config *trunk;
825
826 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
827 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
828 vty_out(vty, " sdp audio-payload number %d%s",
829 trunk->audio_payload, VTY_NEWLINE);
830 vty_out(vty, " sdp audio-payload name %s%s",
831 trunk->audio_name, VTY_NEWLINE);
832 vty_out(vty, " %ssdp audio-payload send-ptime%s",
833 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
834 vty_out(vty, " %ssdp audio-payload send-name%s",
835 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
836
837 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
838 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
839 else if (trunk->keepalive_interval)
840 vty_out(vty, " rtp keep-alive %d%s",
841 trunk->keepalive_interval, VTY_NEWLINE);
842 else
843 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200844 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200845 vty_out(vty, " force-realloc %d%s",
846 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200847 vty_out(vty, " rtp-accept-all %d%s",
848 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200849 if (trunk->omit_rtcp)
850 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
851 else
852 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100853 if (trunk->force_constant_ssrc || trunk->force_aligned_timing
854 || g_cfg->trunk.rfc5993_hr_convert) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200855 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200856 trunk->force_constant_ssrc ? "" : "no ",
857 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200858 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200859 trunk->force_aligned_timing ? "" : "no ",
860 VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100861 vty_out(vty, " %srtp-patch rfc5993hr%s",
862 trunk->rfc5993_hr_convert ? "" : "no ",
863 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200864 } else
865 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
866 if (trunk->audio_fmtp_extra)
867 vty_out(vty, " sdp audio fmtp-extra %s%s",
868 trunk->audio_fmtp_extra, VTY_NEWLINE);
869 vty_out(vty, " %sallow-transcoding%s",
870 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
871 }
872
873 return CMD_SUCCESS;
874}
875
876DEFUN(cfg_trunk_sdp_fmtp_extra,
877 cfg_trunk_sdp_fmtp_extra_cmd,
878 "sdp audio fmtp-extra .NAME",
879 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
880 "Extra Information\n")
881{
882 struct mgcp_trunk_config *trunk = vty->index;
883 char *txt = argv_concat(argv, argc, 0);
884 if (!txt)
885 return CMD_WARNING;
886
887 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
888 talloc_free(txt);
889 return CMD_SUCCESS;
890}
891
892DEFUN(cfg_trunk_payload_number,
893 cfg_trunk_payload_number_cmd,
894 "sdp audio-payload number <0-255>",
895 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
896{
897 struct mgcp_trunk_config *trunk = vty->index;
898 unsigned int payload = atoi(argv[0]);
899
900 trunk->audio_payload = payload;
901 return CMD_SUCCESS;
902}
903
904ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200905 "sdp audio payload number <0-255>",
906 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200907
Philipp Maier87bd9be2017-08-22 16:35:41 +0200908 DEFUN(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200909 cfg_trunk_payload_name_cmd,
910 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200911 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200912{
913 struct mgcp_trunk_config *trunk = vty->index;
914
915 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
916 return CMD_SUCCESS;
917}
918
919ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200920 "sdp audio payload name NAME",
921 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200922
Philipp Maier87bd9be2017-08-22 16:35:41 +0200923 DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200924 cfg_trunk_loop_cmd,
925 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200926 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200927{
928 struct mgcp_trunk_config *trunk = vty->index;
929
930 if (g_cfg->osmux) {
931 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
932 return CMD_WARNING;
933 }
934 trunk->audio_loop = atoi(argv[0]);
935 return CMD_SUCCESS;
936}
937
938DEFUN(cfg_trunk_sdp_payload_send_ptime,
939 cfg_trunk_sdp_payload_send_ptime_cmd,
940 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200941 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200942{
943 struct mgcp_trunk_config *trunk = vty->index;
944 trunk->audio_send_ptime = 1;
945 return CMD_SUCCESS;
946}
947
948DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
949 cfg_trunk_no_sdp_payload_send_ptime_cmd,
950 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200951 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200952{
953 struct mgcp_trunk_config *trunk = vty->index;
954 trunk->audio_send_ptime = 0;
955 return CMD_SUCCESS;
956}
957
958DEFUN(cfg_trunk_sdp_payload_send_name,
959 cfg_trunk_sdp_payload_send_name_cmd,
960 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200961 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200962{
963 struct mgcp_trunk_config *trunk = vty->index;
964 trunk->audio_send_name = 1;
965 return CMD_SUCCESS;
966}
967
968DEFUN(cfg_trunk_no_sdp_payload_send_name,
969 cfg_trunk_no_sdp_payload_send_name_cmd,
970 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200971 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200972{
973 struct mgcp_trunk_config *trunk = vty->index;
974 trunk->audio_send_name = 0;
975 return CMD_SUCCESS;
976}
977
Philipp Maier87bd9be2017-08-22 16:35:41 +0200978DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200979{
980 struct mgcp_trunk_config *trunk = vty->index;
981 trunk->omit_rtcp = 1;
982 return CMD_SUCCESS;
983}
984
985DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200986 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200987{
988 struct mgcp_trunk_config *trunk = vty->index;
989 trunk->omit_rtcp = 0;
990 return CMD_SUCCESS;
991}
992
993DEFUN(cfg_trunk_patch_rtp_ssrc,
994 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200995 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200996{
997 struct mgcp_trunk_config *trunk = vty->index;
998 trunk->force_constant_ssrc = 1;
999 return CMD_SUCCESS;
1000}
1001
1002DEFUN(cfg_trunk_no_patch_rtp_ssrc,
1003 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001004 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001005{
1006 struct mgcp_trunk_config *trunk = vty->index;
1007 trunk->force_constant_ssrc = 0;
1008 return CMD_SUCCESS;
1009}
1010
1011DEFUN(cfg_trunk_patch_rtp_ts,
1012 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001013 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001014{
1015 struct mgcp_trunk_config *trunk = vty->index;
1016 trunk->force_aligned_timing = 1;
1017 return CMD_SUCCESS;
1018}
1019
1020DEFUN(cfg_trunk_no_patch_rtp_ts,
1021 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001022 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001023{
1024 struct mgcp_trunk_config *trunk = vty->index;
1025 trunk->force_aligned_timing = 0;
1026 return CMD_SUCCESS;
1027}
1028
Philipp Maier9fc8a022019-02-20 12:26:52 +01001029DEFUN(cfg_trunk_patch_rtp_rfc5993hr,
1030 cfg_trunk_patch_rtp_rfc5993hr_cmd,
1031 "rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
1032{
1033 struct mgcp_trunk_config *trunk = vty->index;
1034 trunk->rfc5993_hr_convert = true;
1035 return CMD_SUCCESS;
1036}
1037
1038DEFUN(cfg_trunk_no_patch_rtp_rfc5993hr,
1039 cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
1040 "no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
1041{
1042 struct mgcp_trunk_config *trunk = vty->index;
1043 trunk->rfc5993_hr_convert = false;
1044 return CMD_SUCCESS;
1045}
1046
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001047DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001048 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001049{
1050 struct mgcp_trunk_config *trunk = vty->index;
1051 trunk->force_constant_ssrc = 0;
1052 trunk->force_aligned_timing = 0;
Philipp Maier9fc8a022019-02-20 12:26:52 +01001053 trunk->rfc5993_hr_convert = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001054 return CMD_SUCCESS;
1055}
1056
1057DEFUN(cfg_trunk_rtp_keepalive,
1058 cfg_trunk_rtp_keepalive_cmd,
1059 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001060 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001061{
1062 struct mgcp_trunk_config *trunk = vty->index;
1063 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
1064 return CMD_SUCCESS;
1065}
1066
1067DEFUN(cfg_trunk_rtp_keepalive_once,
1068 cfg_trunk_rtp_keepalive_once_cmd,
1069 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001070 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001071{
1072 struct mgcp_trunk_config *trunk = vty->index;
1073 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1074 return CMD_SUCCESS;
1075}
1076
1077DEFUN(cfg_trunk_no_rtp_keepalive,
1078 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001079 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001080{
1081 struct mgcp_trunk_config *trunk = vty->index;
1082 mgcp_trunk_set_keepalive(trunk, 0);
1083 return CMD_SUCCESS;
1084}
1085
1086DEFUN(cfg_trunk_allow_transcoding,
1087 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001088 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001089{
1090 struct mgcp_trunk_config *trunk = vty->index;
1091 trunk->no_audio_transcoding = 0;
1092 return CMD_SUCCESS;
1093}
1094
1095DEFUN(cfg_trunk_no_allow_transcoding,
1096 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001097 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001098{
1099 struct mgcp_trunk_config *trunk = vty->index;
1100 trunk->no_audio_transcoding = 1;
1101 return CMD_SUCCESS;
1102}
1103
Philipp Maier87bd9be2017-08-22 16:35:41 +02001104DEFUN(loop_conn,
1105 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001106 "loop-endpoint <0-64> NAME (0|1)",
1107 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001108 "The name in hex of the endpoint\n" "Disable the loop\n"
1109 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001110{
1111 struct mgcp_trunk_config *trunk;
1112 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001113 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001114
1115 trunk = find_trunk(g_cfg, atoi(argv[0]));
1116 if (!trunk) {
1117 vty_out(vty, "%%Trunk %d not found in the config.%s",
1118 atoi(argv[0]), VTY_NEWLINE);
1119 return CMD_WARNING;
1120 }
1121
1122 if (!trunk->endpoints) {
1123 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1124 trunk->trunk_nr, VTY_NEWLINE);
1125 return CMD_WARNING;
1126 }
1127
1128 int endp_no = strtoul(argv[1], NULL, 16);
1129 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1130 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001131 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001132 return CMD_WARNING;
1133 }
1134
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001135 endp = &trunk->endpoints[endp_no];
1136 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001137 llist_for_each_entry(conn, &endp->conns, entry) {
1138 if (conn->type == MGCP_CONN_TYPE_RTP)
1139 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1140 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1141 else {
1142 /* FIXME: Introduce support for other connection (E1)
1143 * types when implementation is available */
1144 vty_out(vty, "%%Can't enable SSRC patching,"
1145 "connection %s is not an RTP connection.%s",
1146 mgcp_conn_dump(conn), VTY_NEWLINE);
1147 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001148
Philipp Maier87bd9be2017-08-22 16:35:41 +02001149 if (loop)
1150 conn->mode = MGCP_CONN_LOOPBACK;
1151 else
1152 conn->mode = conn->mode_orig;
1153 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001154
1155 return CMD_SUCCESS;
1156}
1157
Philipp Maier87bd9be2017-08-22 16:35:41 +02001158DEFUN(tap_rtp,
1159 tap_rtp_cmd,
1160 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001161 "Forward data on endpoint to a different system\n" "Trunk number\n"
1162 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001163 "The connection id in hex\n"
1164 "Forward incoming data\n"
1165 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001166 "destination IP of the data\n" "destination port\n")
1167{
1168 struct mgcp_rtp_tap *tap;
1169 struct mgcp_trunk_config *trunk;
1170 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001171 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001172 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001173
1174 trunk = find_trunk(g_cfg, atoi(argv[0]));
1175 if (!trunk) {
1176 vty_out(vty, "%%Trunk %d not found in the config.%s",
1177 atoi(argv[0]), VTY_NEWLINE);
1178 return CMD_WARNING;
1179 }
1180
1181 if (!trunk->endpoints) {
1182 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1183 trunk->trunk_nr, VTY_NEWLINE);
1184 return CMD_WARNING;
1185 }
1186
1187 int endp_no = strtoul(argv[1], NULL, 16);
1188 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1189 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001190 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001191 return CMD_WARNING;
1192 }
1193
1194 endp = &trunk->endpoints[endp_no];
1195
Philipp Maier01d24a32017-11-21 17:26:09 +01001196 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001197 conn = mgcp_conn_get_rtp(endp, conn_id);
1198 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001199 vty_out(vty, "Conn ID %s is invalid.%s",
1200 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001201 return CMD_WARNING;
1202 }
1203
1204 if (strcmp(argv[3], "in") == 0)
1205 tap = &conn->tap_in;
1206 else if (strcmp(argv[3], "out") == 0)
1207 tap = &conn->tap_out;
1208 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001209 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1210 return CMD_WARNING;
1211 }
1212
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001213 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001214 inet_aton(argv[4], &tap->forward.sin_addr);
1215 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001216 tap->enabled = 1;
1217 return CMD_SUCCESS;
1218}
1219
1220DEFUN(free_endp, free_endp_cmd,
1221 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001222 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001223{
1224 struct mgcp_trunk_config *trunk;
1225 struct mgcp_endpoint *endp;
1226
1227 trunk = find_trunk(g_cfg, atoi(argv[0]));
1228 if (!trunk) {
1229 vty_out(vty, "%%Trunk %d not found in the config.%s",
1230 atoi(argv[0]), VTY_NEWLINE);
1231 return CMD_WARNING;
1232 }
1233
1234 if (!trunk->endpoints) {
1235 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1236 trunk->trunk_nr, VTY_NEWLINE);
1237 return CMD_WARNING;
1238 }
1239
1240 int endp_no = strtoul(argv[1], NULL, 16);
1241 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1242 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001243 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001244 return CMD_WARNING;
1245 }
1246
1247 endp = &trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001248 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001249 return CMD_SUCCESS;
1250}
1251
1252DEFUN(reset_endp, reset_endp_cmd,
1253 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001254 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001255{
1256 struct mgcp_trunk_config *trunk;
1257 struct mgcp_endpoint *endp;
1258 int endp_no, rc;
1259
1260 trunk = find_trunk(g_cfg, atoi(argv[0]));
1261 if (!trunk) {
1262 vty_out(vty, "%%Trunk %d not found in the config.%s",
1263 atoi(argv[0]), VTY_NEWLINE);
1264 return CMD_WARNING;
1265 }
1266
1267 if (!trunk->endpoints) {
1268 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1269 trunk->trunk_nr, VTY_NEWLINE);
1270 return CMD_WARNING;
1271 }
1272
1273 endp_no = strtoul(argv[1], NULL, 16);
1274 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1275 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001276 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001277 return CMD_WARNING;
1278 }
1279
1280 endp = &trunk->endpoints[endp_no];
1281 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1282 if (rc < 0) {
1283 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1284 return CMD_WARNING;
1285 }
1286 return CMD_SUCCESS;
1287}
1288
1289DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001290 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001291{
1292 int rc;
1293
1294 rc = mgcp_send_reset_all(g_cfg);
1295 if (rc < 0) {
1296 vty_out(vty, "Error %d during endpoint reset.%s",
1297 rc, VTY_NEWLINE);
1298 return CMD_WARNING;
1299 }
1300 return CMD_SUCCESS;
1301}
1302
1303#define OSMUX_STR "RTP multiplexing\n"
1304DEFUN(cfg_mgcp_osmux,
1305 cfg_mgcp_osmux_cmd,
1306 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001307 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001308{
1309 if (strcmp(argv[0], "off") == 0) {
1310 g_cfg->osmux = OSMUX_USAGE_OFF;
1311 return CMD_SUCCESS;
Pau Espin Pedrolb542b042019-04-23 13:09:32 +02001312 } else if (strcmp(argv[0], "on") == 0)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001313 g_cfg->osmux = OSMUX_USAGE_ON;
1314 else if (strcmp(argv[0], "only") == 0)
1315 g_cfg->osmux = OSMUX_USAGE_ONLY;
1316
1317 if (g_cfg->trunk.audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001318 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001319 return CMD_WARNING;
1320 }
1321
1322 return CMD_SUCCESS;
Pau Espin Pedrolb542b042019-04-23 13:09:32 +02001323
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001324}
1325
1326DEFUN(cfg_mgcp_osmux_ip,
1327 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001328 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001329{
1330 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1331 return CMD_SUCCESS;
1332}
1333
1334DEFUN(cfg_mgcp_osmux_batch_factor,
1335 cfg_mgcp_osmux_batch_factor_cmd,
1336 "osmux batch-factor <1-8>",
1337 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1338{
1339 g_cfg->osmux_batch = atoi(argv[0]);
1340 return CMD_SUCCESS;
1341}
1342
1343DEFUN(cfg_mgcp_osmux_batch_size,
1344 cfg_mgcp_osmux_batch_size_cmd,
1345 "osmux batch-size <1-65535>",
1346 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1347{
1348 g_cfg->osmux_batch_size = atoi(argv[0]);
1349 return CMD_SUCCESS;
1350}
1351
1352DEFUN(cfg_mgcp_osmux_port,
1353 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001354 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001355{
1356 g_cfg->osmux_port = atoi(argv[0]);
1357 return CMD_SUCCESS;
1358}
1359
1360DEFUN(cfg_mgcp_osmux_dummy,
1361 cfg_mgcp_osmux_dummy_cmd,
1362 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001363 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1364 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001365{
1366 if (strcmp(argv[0], "on") == 0)
1367 g_cfg->osmux_dummy = 1;
1368 else if (strcmp(argv[0], "off") == 0)
1369 g_cfg->osmux_dummy = 0;
1370
1371 return CMD_SUCCESS;
1372}
1373
Philipp Maier12943ea2018-01-17 15:40:25 +01001374DEFUN(cfg_mgcp_domain,
1375 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001376 "domain NAME",
1377 "Set the domain part expected in MGCP messages' endpoint names\n"
1378 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001379{
1380 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1381 return CMD_SUCCESS;
1382}
1383
Oliver Smithe36b7752019-01-22 16:31:36 +01001384DEFUN(cfg_mgcp_conn_timeout,
1385 cfg_mgcp_conn_timeout_cmd,
Oliver Smithd2ce4442019-06-26 09:56:44 +02001386 "conn-timeout <0-65534>",
1387 "Set a time after which inactive connections (CIs) are closed. Set to 0 to disable timeout. This can be used to"
1388 " work around interoperability problems causing connections to stay open forever, and slowly exhausting all"
Oliver Smith189f29e2019-06-26 12:08:20 +02001389 " available ports. Enable keep-alive packets in MGW clients when using this option together with LCLS (OsmoBSC,"
1390 " OsmoMSC: 'rtp keep-alive')!\n"
Oliver Smithe36b7752019-01-22 16:31:36 +01001391 "Timeout value (sec.)\n")
1392{
1393 g_cfg->conn_timeout = strtoul(argv[0], NULL, 10);
1394 return CMD_SUCCESS;
1395}
1396
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001397int mgcp_vty_init(void)
1398{
1399 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001400 install_element_ve(&show_mgcp_endpoint_cmd);
1401 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001402 install_element(ENABLE_NODE, &loop_conn_cmd);
1403 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001404 install_element(ENABLE_NODE, &free_endp_cmd);
1405 install_element(ENABLE_NODE, &reset_endp_cmd);
1406 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1407
1408 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1409 install_node(&mgcp_node, config_write_mgcp);
1410
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001411 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001412 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1413 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1414 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001415 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001416 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001417 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001418 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001419 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001420 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001421 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1422 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001423 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1424 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1425 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1426 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1427 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1428 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1429 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1430 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1431 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001432 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1433 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1434 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1435 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1436 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1437 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001438 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001439 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1440 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1441 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1442 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1443 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1444 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1445 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1446 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
Philipp Maier9fc8a022019-02-20 12:26:52 +01001447 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_rfc5993hr_cmd);
1448 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_rfc5993hr_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001449 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1450 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1451 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1452 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1453 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1454 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1455 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1456 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1457 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1458 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1459 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1460 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1461 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001462 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Oliver Smithe36b7752019-01-22 16:31:36 +01001463 install_element(MGCP_NODE, &cfg_mgcp_conn_timeout_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001464
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001465 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1466 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001467 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1468 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1469 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1470 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1471 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1472 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1473 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1474 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1475 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1476 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1477 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1478 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1479 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
Philipp Maier9fc8a022019-02-20 12:26:52 +01001480 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_rfc5993hr_cmd);
1481 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_rfc5993hr_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001482 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1483 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1484 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1485 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1486 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1487 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1488 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1489 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1490 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1491
1492 return 0;
1493}
1494
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001495int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1496 enum mgcp_role role)
1497{
1498 int rc;
1499 struct mgcp_trunk_config *trunk;
1500
1501 cfg->osmux_port = OSMUX_PORT;
1502 cfg->osmux_batch = 4;
1503 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1504
1505 g_cfg = cfg;
1506 rc = vty_read_config_file(config_file, NULL);
1507 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001508 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1509 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001510 return rc;
1511 }
1512
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001513 if (!g_cfg->source_addr) {
1514 fprintf(stderr, "You need to specify a bind address.\n");
1515 return -1;
1516 }
1517
Philipp Maier48454982017-11-10 16:46:41 +01001518 if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001519 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001520 "Failed to initialize the virtual trunk (%d endpoints)\n",
1521 g_cfg->trunk.number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001522 return -1;
1523 }
1524
1525 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maier48454982017-11-10 16:46:41 +01001526 if (mgcp_endpoints_allocate(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001527 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001528 "Failed to initialize trunk %d (%d endpoints)\n",
1529 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001530 return -1;
1531 }
1532 }
1533 cfg->role = role;
1534
1535 return 0;
1536}