blob: 76d674f60c279cd07cd658cc03f8e273e075e692 [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 }
Alexander Chemeris63866002020-05-05 17:18:40 +0300269 if (show_stats && cfg->mgcp_general_ctr_group) {
270 vty_out(vty, " %s:%s", cfg->mgcp_general_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_general_ctr_group);
272 }
Stefan Sperling1e174872018-10-25 18:36:10 +0200273 if (show_stats && cfg->mgcp_crcx_ctr_group) {
274 vty_out(vty, " %s:%s", cfg->mgcp_crcx_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_crcx_ctr_group);
276 }
Stefan Sperling8ab3fbb2018-10-30 14:57:25 +0100277 if (show_stats && cfg->mgcp_dlcx_ctr_group) {
278 vty_out(vty, " %s:%s", cfg->mgcp_dlcx_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_dlcx_ctr_group);
280 }
Stefan Sperlingaa823bf2018-10-29 14:51:41 +0100281 if (show_stats && cfg->mgcp_mdcx_ctr_group) {
282 vty_out(vty, " %s:%s", cfg->mgcp_mdcx_ctr_group->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->mgcp_mdcx_ctr_group);
284 }
Stefan Sperlingba25eab2018-10-30 14:32:31 +0100285 if (show_stats && cfg->all_rtp_conn_stats) {
286 vty_out(vty, " %s:%s", cfg->all_rtp_conn_stats->desc->group_description, VTY_NEWLINE);
287 vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", cfg->all_rtp_conn_stats);
288 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200289}
290
Stefan Sperling12086582018-06-26 15:26:28 +0200291#define SHOW_MGCP_STR "Display information about the MGCP Media Gateway\n"
292
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200293DEFUN(show_mcgp, show_mgcp_cmd,
294 "show mgcp [stats]",
295 SHOW_STR
Stefan Sperling12086582018-06-26 15:26:28 +0200296 SHOW_MGCP_STR
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200297 "Include Statistics\n")
298{
299 struct mgcp_trunk_config *trunk;
300 int show_stats = argc >= 1;
301
302 dump_trunk(vty, &g_cfg->trunk, show_stats);
303
304 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
Philipp Maier87bd9be2017-08-22 16:35:41 +0200305 dump_trunk(vty, trunk, show_stats);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200306
307 if (g_cfg->osmux)
Pau Espin Pedrol8de58e72019-04-24 13:33:46 +0200308 vty_out(vty, "Osmux used CID: %d%s", osmux_cid_pool_count_used(),
Philipp Maier87bd9be2017-08-22 16:35:41 +0200309 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200310
311 return CMD_SUCCESS;
312}
313
Stefan Sperling12086582018-06-26 15:26:28 +0200314static void
315dump_mgcp_endpoint(struct vty *vty, struct mgcp_trunk_config *trunk, const char *epname)
316{
317 const size_t virt_prefix_len = sizeof(MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK) - 1;
318 unsigned long epidx;
319 char *endp;
320 int i;
321
322 if (strncmp(epname, MGCP_ENDPOINT_PREFIX_VIRTUAL_TRUNK, virt_prefix_len) == 0)
323 epname += virt_prefix_len;
324 errno = 0;
325 epidx = strtoul(epname, &endp, 16);
326 if (epname[0] == '\0' || *endp != '\0') {
327 vty_out(vty, "endpoint name '%s' is not a hex number%s", epname, VTY_NEWLINE);
328 return;
329 }
330 if ((errno == ERANGE && epidx == ULONG_MAX) /* parsed value out of range */
331 || epidx >= trunk->number_endpoints) {
332 vty_out(vty, "endpoint %.2lx not configured on trunk %d%s", epidx, trunk->trunk_nr, VTY_NEWLINE);
333 return;
334 }
335
336 for (i = 0; i < trunk->number_endpoints; ++i) {
337 struct mgcp_endpoint *endp = &trunk->endpoints[i];
338 if (i == epidx) {
339 dump_endpoint(vty, endp, i, trunk->trunk_nr, trunk->trunk_type, true);
340 break;
341 }
342 }
343}
344
345DEFUN(show_mcgp_endpoint, show_mgcp_endpoint_cmd,
346 "show mgcp endpoint NAME",
347 SHOW_STR
348 SHOW_MGCP_STR
349 "Display information about an endpoint\n" "The name of the endpoint\n")
350{
351 struct mgcp_trunk_config *trunk;
352
353 dump_mgcp_endpoint(vty, &g_cfg->trunk, argv[0]);
354 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
355 dump_mgcp_endpoint(vty, trunk, argv[0]);
356
357 return CMD_SUCCESS;
358}
359
360DEFUN(show_mcgp_trunk_endpoint, show_mgcp_trunk_endpoint_cmd,
361 "show mgcp trunk <0-64> endpoint NAME",
362 SHOW_STR
363 SHOW_MGCP_STR
364 "Display information about a trunk\n" "Trunk number\n"
365 "Display information about an endpoint\n" "The name of the endpoint\n")
366{
367 struct mgcp_trunk_config *trunk;
368 int trunkidx = atoi(argv[0]);
369
370 trunk = find_trunk(g_cfg, trunkidx);
371 if (!trunk) {
372 vty_out(vty, "trunk %d not found%s", trunkidx, VTY_NEWLINE);
373 return CMD_WARNING;
374 }
375
376 dump_mgcp_endpoint(vty, trunk, argv[1]);
377 return CMD_SUCCESS;
378}
379
Philipp Maier87bd9be2017-08-22 16:35:41 +0200380DEFUN(cfg_mgcp, cfg_mgcp_cmd, "mgcp", "Configure the MGCP")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200381{
382 vty->node = MGCP_NODE;
383 return CMD_SUCCESS;
384}
385
386DEFUN(cfg_mgcp_local_ip,
387 cfg_mgcp_local_ip_cmd,
388 "local ip A.B.C.D",
389 "Local options for the SDP record\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200390 IP_STR "IPv4 Address to use in SDP record\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200391{
392 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
393 return CMD_SUCCESS;
394}
395
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200396#define BIND_STR "Listen/Bind related socket option\n"
397DEFUN(cfg_mgcp_bind_ip,
398 cfg_mgcp_bind_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200399 "bind ip A.B.C.D", BIND_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200400{
401 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
402 return CMD_SUCCESS;
403}
404
405DEFUN(cfg_mgcp_bind_port,
406 cfg_mgcp_bind_port_cmd,
407 "bind port <0-65534>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200408 BIND_STR "Port information\n" "UDP port to listen for MGCP messages\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200409{
410 unsigned int port = atoi(argv[0]);
411 g_cfg->source_port = port;
412 return CMD_SUCCESS;
413}
414
415DEFUN(cfg_mgcp_bind_early,
416 cfg_mgcp_bind_early_cmd,
417 "bind early (0|1)",
418 BIND_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200419 "Bind local ports on start up\n" "Bind on demand\n" "Bind on startup\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200420{
421 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
422 return CMD_WARNING;
423}
424
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200425#define RTP_STR "RTP configuration\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200426#define UDP_PORT_STR "UDP Port number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +0200427#define NET_START_STR "First UDP port allocated\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200428#define RANGE_START_STR "Start of the range of ports\n"
429#define RANGE_END_STR "End of the range of ports\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200430
Philipp Maierf1889d82017-11-08 14:59:39 +0100431DEFUN(cfg_mgcp_rtp_port_range,
432 cfg_mgcp_rtp_port_range_cmd,
Philipp Maiera19547b2018-05-22 13:44:34 +0200433 "rtp port-range <1024-65534> <1025-65535>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200434 RTP_STR "Range of ports to use for the NET side\n"
435 RANGE_START_STR RANGE_END_STR)
436{
Philipp Maiera19547b2018-05-22 13:44:34 +0200437 int start;
438 int end;
439
440 start = atoi(argv[0]);
441 end = atoi(argv[1]);
442
443 if (end < start) {
444 vty_out(vty, "range end port (%i) must be greater than the range start port (%i)!%s",
445 end, start, VTY_NEWLINE);
446 return CMD_WARNING;
447 }
448
449 if (start & 1) {
450 vty_out(vty, "range must begin at an even port number, autocorrecting port (%i) to: %i%s",
451 start, start & 0xFFFE, VTY_NEWLINE);
452 start &= 0xFFFE;
453 }
454
455 if ((end & 1) == 0) {
456 vty_out(vty, "range must end at an odd port number, autocorrecting port (%i) to: %i%s",
457 end, end | 1, VTY_NEWLINE);
458 end |= 1;
459 }
460
461 g_cfg->net_ports.range_start = start;
462 g_cfg->net_ports.range_end = end;
463 g_cfg->net_ports.last_port = g_cfg->net_ports.range_start;
464
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200465 return CMD_SUCCESS;
466}
Philipp Maierf1889d82017-11-08 14:59:39 +0100467ALIAS_DEPRECATED(cfg_mgcp_rtp_port_range,
468 cfg_mgcp_rtp_net_range_cmd,
469 "rtp net-range <0-65534> <0-65534>",
470 RTP_STR "Range of ports to use for the NET side\n"
471 RANGE_START_STR RANGE_END_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200472
Philipp Maierf1889d82017-11-08 14:59:39 +0100473DEFUN(cfg_mgcp_rtp_bind_ip,
474 cfg_mgcp_rtp_bind_ip_cmd,
475 "rtp bind-ip A.B.C.D",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200476 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
477{
478 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
479 return CMD_SUCCESS;
480}
Philipp Maierf1889d82017-11-08 14:59:39 +0100481ALIAS_DEPRECATED(cfg_mgcp_rtp_bind_ip,
482 cfg_mgcp_rtp_net_bind_ip_cmd,
483 "rtp net-bind-ip A.B.C.D",
484 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200485
Philipp Maierf1889d82017-11-08 14:59:39 +0100486DEFUN(cfg_mgcp_rtp_no_bind_ip,
487 cfg_mgcp_rtp_no_bind_ip_cmd,
488 "no rtp bind-ip",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200489 NO_STR RTP_STR "Bind endpoints facing the Network\n"
490 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200491{
492 talloc_free(g_cfg->net_ports.bind_addr);
493 g_cfg->net_ports.bind_addr = NULL;
494 return CMD_SUCCESS;
495}
Philipp Maierf1889d82017-11-08 14:59:39 +0100496ALIAS_DEPRECATED(cfg_mgcp_rtp_no_bind_ip,
497 cfg_mgcp_rtp_no_net_bind_ip_cmd,
498 "no rtp net-bind-ip",
499 NO_STR RTP_STR "Bind endpoints facing the Network\n"
500 "Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200501
Philipp Maier1cb1e382017-11-02 17:16:04 +0100502DEFUN(cfg_mgcp_rtp_net_bind_ip_probing,
503 cfg_mgcp_rtp_net_bind_ip_probing_cmd,
504 "rtp ip-probing",
505 RTP_STR "automatic rtp bind ip selection\n")
506{
507 g_cfg->net_ports.bind_addr_probe = true;
508 return CMD_SUCCESS;
509}
510
511DEFUN(cfg_mgcp_rtp_no_net_bind_ip_probing,
512 cfg_mgcp_rtp_no_net_bind_ip_probing_cmd,
513 "no rtp ip-probing",
514 NO_STR RTP_STR "no automatic rtp bind ip selection\n")
515{
516 g_cfg->net_ports.bind_addr_probe = false;
517 return CMD_SUCCESS;
518}
519
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200520DEFUN(cfg_mgcp_rtp_ip_dscp,
521 cfg_mgcp_rtp_ip_dscp_cmd,
522 "rtp ip-dscp <0-255>",
523 RTP_STR
524 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
525{
526 int dscp = atoi(argv[0]);
527 g_cfg->endp_dscp = dscp;
528 return CMD_SUCCESS;
529}
530
531ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200532 "rtp ip-tos <0-255>",
533 RTP_STR
534 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
535#define FORCE_PTIME_STR "Force a fixed ptime for packets sent"
536 DEFUN(cfg_mgcp_rtp_force_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200537 cfg_mgcp_rtp_force_ptime_cmd,
538 "rtp force-ptime (10|20|40)",
539 RTP_STR FORCE_PTIME_STR
Philipp Maier87bd9be2017-08-22 16:35:41 +0200540 "The required ptime (packet duration) in ms\n" "10 ms\n20 ms\n40 ms\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200541{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200542 g_cfg->force_ptime = atoi(argv[0]);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200543 return CMD_SUCCESS;
544}
545
546DEFUN(cfg_mgcp_no_rtp_force_ptime,
547 cfg_mgcp_no_rtp_force_ptime_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200548 "no rtp force-ptime", NO_STR RTP_STR FORCE_PTIME_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200549{
Philipp Maier87bd9be2017-08-22 16:35:41 +0200550 g_cfg->force_ptime = 0;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200551 return CMD_SUCCESS;
552}
553
554DEFUN(cfg_mgcp_sdp_fmtp_extra,
555 cfg_mgcp_sdp_fmtp_extra_cmd,
556 "sdp audio fmtp-extra .NAME",
557 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
558 "Extra Information\n")
559{
560 char *txt = argv_concat(argv, argc, 0);
561 if (!txt)
562 return CMD_WARNING;
563
564 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
565 talloc_free(txt);
566 return CMD_SUCCESS;
567}
568
569DEFUN(cfg_mgcp_allow_transcoding,
570 cfg_mgcp_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200571 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200572{
573 g_cfg->trunk.no_audio_transcoding = 0;
574 return CMD_SUCCESS;
575}
576
577DEFUN(cfg_mgcp_no_allow_transcoding,
578 cfg_mgcp_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200579 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200580{
581 g_cfg->trunk.no_audio_transcoding = 1;
582 return CMD_SUCCESS;
583}
584
585#define SDP_STR "SDP File related options\n"
586#define AUDIO_STR "Audio payload options\n"
587DEFUN(cfg_mgcp_sdp_payload_number,
588 cfg_mgcp_sdp_payload_number_cmd,
589 "sdp audio-payload number <0-255>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200590 SDP_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200591{
592 unsigned int payload = atoi(argv[0]);
593 g_cfg->trunk.audio_payload = payload;
594 return CMD_SUCCESS;
595}
596
Philipp Maier87bd9be2017-08-22 16:35:41 +0200597ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number,
598 cfg_mgcp_sdp_payload_number_cmd_old,
599 "sdp audio payload number <0-255>",
600 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200601
Philipp Maier87bd9be2017-08-22 16:35:41 +0200602 DEFUN(cfg_mgcp_sdp_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200603 cfg_mgcp_sdp_payload_name_cmd,
604 "sdp audio-payload name NAME",
605 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
606{
607 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
608 return CMD_SUCCESS;
609}
610
611ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200612 "sdp audio payload name NAME",
613 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200614
Philipp Maier87bd9be2017-08-22 16:35:41 +0200615 DEFUN(cfg_mgcp_sdp_payload_send_ptime,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200616 cfg_mgcp_sdp_payload_send_ptime_cmd,
617 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200618 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200619{
620 g_cfg->trunk.audio_send_ptime = 1;
621 return CMD_SUCCESS;
622}
623
624DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
625 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
626 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200627 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200628{
629 g_cfg->trunk.audio_send_ptime = 0;
630 return CMD_SUCCESS;
631}
632
633DEFUN(cfg_mgcp_sdp_payload_send_name,
634 cfg_mgcp_sdp_payload_send_name_cmd,
635 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200636 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200637{
638 g_cfg->trunk.audio_send_name = 1;
639 return CMD_SUCCESS;
640}
641
642DEFUN(cfg_mgcp_no_sdp_payload_send_name,
643 cfg_mgcp_no_sdp_payload_send_name_cmd,
644 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200645 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200646{
647 g_cfg->trunk.audio_send_name = 0;
648 return CMD_SUCCESS;
649}
650
651DEFUN(cfg_mgcp_loop,
652 cfg_mgcp_loop_cmd,
653 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200654 "Loop audio for all endpoints on main trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200655{
656 if (g_cfg->osmux) {
657 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
658 return CMD_WARNING;
659 }
660 g_cfg->trunk.audio_loop = atoi(argv[0]);
661 return CMD_SUCCESS;
662}
663
664DEFUN(cfg_mgcp_force_realloc,
665 cfg_mgcp_force_realloc_cmd,
666 "force-realloc (0|1)",
667 "Force endpoint reallocation when the endpoint is still seized\n"
668 "Don't force reallocation\n" "force reallocation\n")
669{
670 g_cfg->trunk.force_realloc = atoi(argv[0]);
671 return CMD_SUCCESS;
672}
673
Philipp Maier87bd9be2017-08-22 16:35:41 +0200674DEFUN(cfg_mgcp_rtp_accept_all,
675 cfg_mgcp_rtp_accept_all_cmd,
676 "rtp-accept-all (0|1)",
677 "Accept all RTP packets, even when the originating IP/Port does not match\n"
678 "enable filter\n" "disable filter\n")
679{
680 g_cfg->trunk.rtp_accept_all = atoi(argv[0]);
681 return CMD_SUCCESS;
682}
683
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200684DEFUN(cfg_mgcp_number_endp,
685 cfg_mgcp_number_endp_cmd,
686 "number endpoints <0-65534>",
687 "Number options\n" "Endpoints available\n" "Number endpoints\n")
688{
689 /* + 1 as we start counting at one */
Philipp Maierfcd06552017-11-10 17:32:22 +0100690 g_cfg->trunk.vty_number_endpoints = atoi(argv[0]) + 1;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200691 return CMD_SUCCESS;
692}
693
Philipp Maier87bd9be2017-08-22 16:35:41 +0200694DEFUN(cfg_mgcp_omit_rtcp, cfg_mgcp_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200695{
696 g_cfg->trunk.omit_rtcp = 1;
697 return CMD_SUCCESS;
698}
699
700DEFUN(cfg_mgcp_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200701 cfg_mgcp_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200702{
703 g_cfg->trunk.omit_rtcp = 0;
704 return CMD_SUCCESS;
705}
706
707DEFUN(cfg_mgcp_patch_rtp_ssrc,
708 cfg_mgcp_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200709 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200710{
711 g_cfg->trunk.force_constant_ssrc = 1;
712 return CMD_SUCCESS;
713}
714
715DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
716 cfg_mgcp_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200717 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200718{
719 g_cfg->trunk.force_constant_ssrc = 0;
720 return CMD_SUCCESS;
721}
722
723DEFUN(cfg_mgcp_patch_rtp_ts,
724 cfg_mgcp_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200725 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200726{
727 g_cfg->trunk.force_aligned_timing = 1;
728 return CMD_SUCCESS;
729}
730
731DEFUN(cfg_mgcp_no_patch_rtp_ts,
732 cfg_mgcp_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200733 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200734{
735 g_cfg->trunk.force_aligned_timing = 0;
736 return CMD_SUCCESS;
737}
738
Philipp Maier9fc8a022019-02-20 12:26:52 +0100739DEFUN(cfg_mgcp_patch_rtp_rfc5993hr,
740 cfg_mgcp_patch_rtp_rfc5993hr_cmd,
741 "rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
742{
743 g_cfg->trunk.rfc5993_hr_convert = true;
744 return CMD_SUCCESS;
745}
746
747DEFUN(cfg_mgcp_no_patch_rtp_rfc5993hr,
748 cfg_mgcp_no_patch_rtp_rfc5993hr_cmd,
749 "no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
750{
751 g_cfg->trunk.rfc5993_hr_convert = false;
752 return CMD_SUCCESS;
753}
754
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200755DEFUN(cfg_mgcp_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200756 cfg_mgcp_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200757{
758 g_cfg->trunk.force_constant_ssrc = 0;
759 g_cfg->trunk.force_aligned_timing = 0;
Philipp Maier9fc8a022019-02-20 12:26:52 +0100760 g_cfg->trunk.rfc5993_hr_convert = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200761 return CMD_SUCCESS;
762}
763
764DEFUN(cfg_mgcp_rtp_keepalive,
765 cfg_mgcp_rtp_keepalive_cmd,
766 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200767 RTP_STR RTP_KEEPALIVE_STR "Keep alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200768{
769 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
770 return CMD_SUCCESS;
771}
772
773DEFUN(cfg_mgcp_rtp_keepalive_once,
774 cfg_mgcp_rtp_keepalive_once_cmd,
775 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200776 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200777{
778 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
779 return CMD_SUCCESS;
780}
781
782DEFUN(cfg_mgcp_no_rtp_keepalive,
783 cfg_mgcp_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200784 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200785{
Philipp Maiere726d4f2017-11-01 10:41:34 +0100786 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_NEVER);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200787 return CMD_SUCCESS;
788}
789
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200790#define CALL_AGENT_STR "Callagent information\n"
791DEFUN(cfg_mgcp_agent_addr,
792 cfg_mgcp_agent_addr_cmd,
793 "call-agent ip A.B.C.D",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200794 CALL_AGENT_STR IP_STR "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200795{
796 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
797 return CMD_SUCCESS;
798}
799
800ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200801 "call agent ip A.B.C.D",
802 CALL_AGENT_STR CALL_AGENT_STR IP_STR
803 "IPv4 Address of the callagent\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200804
Philipp Maier87bd9be2017-08-22 16:35:41 +0200805 DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
806 "trunk <1-64>", "Configure a SS7 trunk\n" "Trunk Nr\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200807{
808 struct mgcp_trunk_config *trunk;
809 int index = atoi(argv[0]);
810
811 trunk = mgcp_trunk_num(g_cfg, index);
812 if (!trunk)
813 trunk = mgcp_trunk_alloc(g_cfg, index);
814
815 if (!trunk) {
816 vty_out(vty, "%%Unable to allocate trunk %u.%s",
817 index, VTY_NEWLINE);
818 return CMD_WARNING;
819 }
820
821 vty->node = TRUNK_NODE;
822 vty->index = trunk;
823 return CMD_SUCCESS;
824}
825
826static int config_write_trunk(struct vty *vty)
827{
828 struct mgcp_trunk_config *trunk;
829
830 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
831 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
832 vty_out(vty, " sdp audio-payload number %d%s",
833 trunk->audio_payload, VTY_NEWLINE);
834 vty_out(vty, " sdp audio-payload name %s%s",
835 trunk->audio_name, VTY_NEWLINE);
836 vty_out(vty, " %ssdp audio-payload send-ptime%s",
837 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
838 vty_out(vty, " %ssdp audio-payload send-name%s",
839 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
840
841 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
842 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
843 else if (trunk->keepalive_interval)
844 vty_out(vty, " rtp keep-alive %d%s",
845 trunk->keepalive_interval, VTY_NEWLINE);
846 else
847 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200848 vty_out(vty, " loop %d%s", trunk->audio_loop, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200849 vty_out(vty, " force-realloc %d%s",
850 trunk->force_realloc, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +0200851 vty_out(vty, " rtp-accept-all %d%s",
852 trunk->rtp_accept_all, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200853 if (trunk->omit_rtcp)
854 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
855 else
856 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100857 if (trunk->force_constant_ssrc || trunk->force_aligned_timing
858 || g_cfg->trunk.rfc5993_hr_convert) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200859 vty_out(vty, " %srtp-patch ssrc%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200860 trunk->force_constant_ssrc ? "" : "no ",
861 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200862 vty_out(vty, " %srtp-patch timestamp%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200863 trunk->force_aligned_timing ? "" : "no ",
864 VTY_NEWLINE);
Philipp Maier9fc8a022019-02-20 12:26:52 +0100865 vty_out(vty, " %srtp-patch rfc5993hr%s",
866 trunk->rfc5993_hr_convert ? "" : "no ",
867 VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200868 } else
869 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
870 if (trunk->audio_fmtp_extra)
871 vty_out(vty, " sdp audio fmtp-extra %s%s",
872 trunk->audio_fmtp_extra, VTY_NEWLINE);
873 vty_out(vty, " %sallow-transcoding%s",
874 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
875 }
876
877 return CMD_SUCCESS;
878}
879
880DEFUN(cfg_trunk_sdp_fmtp_extra,
881 cfg_trunk_sdp_fmtp_extra_cmd,
882 "sdp audio fmtp-extra .NAME",
883 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
884 "Extra Information\n")
885{
886 struct mgcp_trunk_config *trunk = vty->index;
887 char *txt = argv_concat(argv, argc, 0);
888 if (!txt)
889 return CMD_WARNING;
890
891 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
892 talloc_free(txt);
893 return CMD_SUCCESS;
894}
895
896DEFUN(cfg_trunk_payload_number,
897 cfg_trunk_payload_number_cmd,
898 "sdp audio-payload number <0-255>",
899 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
900{
901 struct mgcp_trunk_config *trunk = vty->index;
902 unsigned int payload = atoi(argv[0]);
903
904 trunk->audio_payload = payload;
905 return CMD_SUCCESS;
906}
907
908ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200909 "sdp audio payload number <0-255>",
910 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200911
Philipp Maier87bd9be2017-08-22 16:35:41 +0200912 DEFUN(cfg_trunk_payload_name,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200913 cfg_trunk_payload_name_cmd,
914 "sdp audio-payload name NAME",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200915 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200916{
917 struct mgcp_trunk_config *trunk = vty->index;
918
919 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
920 return CMD_SUCCESS;
921}
922
923ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200924 "sdp audio payload name NAME",
925 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200926
Philipp Maier87bd9be2017-08-22 16:35:41 +0200927 DEFUN(cfg_trunk_loop,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200928 cfg_trunk_loop_cmd,
929 "loop (0|1)",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200930 "Loop audio for all endpoints on this trunk\n" "Don't Loop\n" "Loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200931{
932 struct mgcp_trunk_config *trunk = vty->index;
933
934 if (g_cfg->osmux) {
935 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
936 return CMD_WARNING;
937 }
938 trunk->audio_loop = atoi(argv[0]);
939 return CMD_SUCCESS;
940}
941
942DEFUN(cfg_trunk_sdp_payload_send_ptime,
943 cfg_trunk_sdp_payload_send_ptime_cmd,
944 "sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200945 SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200946{
947 struct mgcp_trunk_config *trunk = vty->index;
948 trunk->audio_send_ptime = 1;
949 return CMD_SUCCESS;
950}
951
952DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
953 cfg_trunk_no_sdp_payload_send_ptime_cmd,
954 "no sdp audio-payload send-ptime",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200955 NO_STR SDP_STR AUDIO_STR "Send SDP ptime (packet duration) attribute\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200956{
957 struct mgcp_trunk_config *trunk = vty->index;
958 trunk->audio_send_ptime = 0;
959 return CMD_SUCCESS;
960}
961
962DEFUN(cfg_trunk_sdp_payload_send_name,
963 cfg_trunk_sdp_payload_send_name_cmd,
964 "sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200965 SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200966{
967 struct mgcp_trunk_config *trunk = vty->index;
968 trunk->audio_send_name = 1;
969 return CMD_SUCCESS;
970}
971
972DEFUN(cfg_trunk_no_sdp_payload_send_name,
973 cfg_trunk_no_sdp_payload_send_name_cmd,
974 "no sdp audio-payload send-name",
Philipp Maier87bd9be2017-08-22 16:35:41 +0200975 NO_STR SDP_STR AUDIO_STR "Send SDP rtpmap with the audio name\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200976{
977 struct mgcp_trunk_config *trunk = vty->index;
978 trunk->audio_send_name = 0;
979 return CMD_SUCCESS;
980}
981
Philipp Maier87bd9be2017-08-22 16:35:41 +0200982DEFUN(cfg_trunk_omit_rtcp, cfg_trunk_omit_rtcp_cmd, "rtcp-omit", RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200983{
984 struct mgcp_trunk_config *trunk = vty->index;
985 trunk->omit_rtcp = 1;
986 return CMD_SUCCESS;
987}
988
989DEFUN(cfg_trunk_no_omit_rtcp,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200990 cfg_trunk_no_omit_rtcp_cmd, "no rtcp-omit", NO_STR RTCP_OMIT_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +0200991{
992 struct mgcp_trunk_config *trunk = vty->index;
993 trunk->omit_rtcp = 0;
994 return CMD_SUCCESS;
995}
996
997DEFUN(cfg_trunk_patch_rtp_ssrc,
998 cfg_trunk_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +0200999 "rtp-patch ssrc", RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001000{
1001 struct mgcp_trunk_config *trunk = vty->index;
1002 trunk->force_constant_ssrc = 1;
1003 return CMD_SUCCESS;
1004}
1005
1006DEFUN(cfg_trunk_no_patch_rtp_ssrc,
1007 cfg_trunk_no_patch_rtp_ssrc_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001008 "no rtp-patch ssrc", NO_STR RTP_PATCH_STR "Force a fixed SSRC\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001009{
1010 struct mgcp_trunk_config *trunk = vty->index;
1011 trunk->force_constant_ssrc = 0;
1012 return CMD_SUCCESS;
1013}
1014
1015DEFUN(cfg_trunk_patch_rtp_ts,
1016 cfg_trunk_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001017 "rtp-patch timestamp", RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001018{
1019 struct mgcp_trunk_config *trunk = vty->index;
1020 trunk->force_aligned_timing = 1;
1021 return CMD_SUCCESS;
1022}
1023
1024DEFUN(cfg_trunk_no_patch_rtp_ts,
1025 cfg_trunk_no_patch_rtp_ts_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001026 "no rtp-patch timestamp", NO_STR RTP_PATCH_STR "Adjust RTP timestamp\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001027{
1028 struct mgcp_trunk_config *trunk = vty->index;
1029 trunk->force_aligned_timing = 0;
1030 return CMD_SUCCESS;
1031}
1032
Philipp Maier9fc8a022019-02-20 12:26:52 +01001033DEFUN(cfg_trunk_patch_rtp_rfc5993hr,
1034 cfg_trunk_patch_rtp_rfc5993hr_cmd,
1035 "rtp-patch rfc5993hr", RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
1036{
1037 struct mgcp_trunk_config *trunk = vty->index;
1038 trunk->rfc5993_hr_convert = true;
1039 return CMD_SUCCESS;
1040}
1041
1042DEFUN(cfg_trunk_no_patch_rtp_rfc5993hr,
1043 cfg_trunk_no_patch_rtp_rfc5993hr_cmd,
1044 "no rtp-patch rfc5993hr", NO_STR RTP_PATCH_STR RTP_TS101318_RFC5993_CONV_STR)
1045{
1046 struct mgcp_trunk_config *trunk = vty->index;
1047 trunk->rfc5993_hr_convert = false;
1048 return CMD_SUCCESS;
1049}
1050
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001051DEFUN(cfg_trunk_no_patch_rtp,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001052 cfg_trunk_no_patch_rtp_cmd, "no rtp-patch", NO_STR RTP_PATCH_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001053{
1054 struct mgcp_trunk_config *trunk = vty->index;
1055 trunk->force_constant_ssrc = 0;
1056 trunk->force_aligned_timing = 0;
Philipp Maier9fc8a022019-02-20 12:26:52 +01001057 trunk->rfc5993_hr_convert = false;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001058 return CMD_SUCCESS;
1059}
1060
1061DEFUN(cfg_trunk_rtp_keepalive,
1062 cfg_trunk_rtp_keepalive_cmd,
1063 "rtp keep-alive <1-120>",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001064 RTP_STR RTP_KEEPALIVE_STR "Keep-alive interval in secs\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001065{
1066 struct mgcp_trunk_config *trunk = vty->index;
1067 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
1068 return CMD_SUCCESS;
1069}
1070
1071DEFUN(cfg_trunk_rtp_keepalive_once,
1072 cfg_trunk_rtp_keepalive_once_cmd,
1073 "rtp keep-alive once",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001074 RTP_STR RTP_KEEPALIVE_STR "Send dummy packet only once after CRCX/MDCX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001075{
1076 struct mgcp_trunk_config *trunk = vty->index;
1077 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1078 return CMD_SUCCESS;
1079}
1080
1081DEFUN(cfg_trunk_no_rtp_keepalive,
1082 cfg_trunk_no_rtp_keepalive_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001083 "no rtp keep-alive", NO_STR RTP_STR RTP_KEEPALIVE_STR)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001084{
1085 struct mgcp_trunk_config *trunk = vty->index;
1086 mgcp_trunk_set_keepalive(trunk, 0);
1087 return CMD_SUCCESS;
1088}
1089
1090DEFUN(cfg_trunk_allow_transcoding,
1091 cfg_trunk_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001092 "allow-transcoding", "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001093{
1094 struct mgcp_trunk_config *trunk = vty->index;
1095 trunk->no_audio_transcoding = 0;
1096 return CMD_SUCCESS;
1097}
1098
1099DEFUN(cfg_trunk_no_allow_transcoding,
1100 cfg_trunk_no_allow_transcoding_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001101 "no allow-transcoding", NO_STR "Allow transcoding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001102{
1103 struct mgcp_trunk_config *trunk = vty->index;
1104 trunk->no_audio_transcoding = 1;
1105 return CMD_SUCCESS;
1106}
1107
Philipp Maier87bd9be2017-08-22 16:35:41 +02001108DEFUN(loop_conn,
1109 loop_conn_cmd,
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001110 "loop-endpoint <0-64> NAME (0|1)",
1111 "Loop a given endpoint\n" "Trunk number\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001112 "The name in hex of the endpoint\n" "Disable the loop\n"
1113 "Enable the loop\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001114{
1115 struct mgcp_trunk_config *trunk;
1116 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001117 struct mgcp_conn *conn;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001118
1119 trunk = find_trunk(g_cfg, atoi(argv[0]));
1120 if (!trunk) {
1121 vty_out(vty, "%%Trunk %d not found in the config.%s",
1122 atoi(argv[0]), VTY_NEWLINE);
1123 return CMD_WARNING;
1124 }
1125
1126 if (!trunk->endpoints) {
1127 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1128 trunk->trunk_nr, VTY_NEWLINE);
1129 return CMD_WARNING;
1130 }
1131
1132 int endp_no = strtoul(argv[1], NULL, 16);
1133 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1134 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001135 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001136 return CMD_WARNING;
1137 }
1138
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001139 endp = &trunk->endpoints[endp_no];
1140 int loop = atoi(argv[2]);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001141 llist_for_each_entry(conn, &endp->conns, entry) {
1142 if (conn->type == MGCP_CONN_TYPE_RTP)
1143 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1144 mgcp_rtp_end_config(endp, 1, &conn->u.rtp.end);
1145 else {
1146 /* FIXME: Introduce support for other connection (E1)
1147 * types when implementation is available */
1148 vty_out(vty, "%%Can't enable SSRC patching,"
1149 "connection %s is not an RTP connection.%s",
1150 mgcp_conn_dump(conn), VTY_NEWLINE);
1151 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001152
Philipp Maier87bd9be2017-08-22 16:35:41 +02001153 if (loop)
1154 conn->mode = MGCP_CONN_LOOPBACK;
1155 else
1156 conn->mode = conn->mode_orig;
1157 }
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001158
1159 return CMD_SUCCESS;
1160}
1161
Philipp Maier87bd9be2017-08-22 16:35:41 +02001162DEFUN(tap_rtp,
1163 tap_rtp_cmd,
1164 "tap-rtp <0-64> ENDPOINT CONN (in|out) A.B.C.D <0-65534>",
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001165 "Forward data on endpoint to a different system\n" "Trunk number\n"
1166 "The endpoint in hex\n"
Philipp Maier87bd9be2017-08-22 16:35:41 +02001167 "The connection id in hex\n"
1168 "Forward incoming data\n"
1169 "Forward leaving data\n"
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001170 "destination IP of the data\n" "destination port\n")
1171{
1172 struct mgcp_rtp_tap *tap;
1173 struct mgcp_trunk_config *trunk;
1174 struct mgcp_endpoint *endp;
Philipp Maier87bd9be2017-08-22 16:35:41 +02001175 struct mgcp_conn_rtp *conn;
Philipp Maier01d24a32017-11-21 17:26:09 +01001176 const char *conn_id = NULL;
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001177
1178 trunk = find_trunk(g_cfg, atoi(argv[0]));
1179 if (!trunk) {
1180 vty_out(vty, "%%Trunk %d not found in the config.%s",
1181 atoi(argv[0]), VTY_NEWLINE);
1182 return CMD_WARNING;
1183 }
1184
1185 if (!trunk->endpoints) {
1186 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1187 trunk->trunk_nr, VTY_NEWLINE);
1188 return CMD_WARNING;
1189 }
1190
1191 int endp_no = strtoul(argv[1], NULL, 16);
1192 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1193 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001194 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001195 return CMD_WARNING;
1196 }
1197
1198 endp = &trunk->endpoints[endp_no];
1199
Philipp Maier01d24a32017-11-21 17:26:09 +01001200 conn_id = argv[2];
Philipp Maier87bd9be2017-08-22 16:35:41 +02001201 conn = mgcp_conn_get_rtp(endp, conn_id);
1202 if (!conn) {
Philipp Maier01d24a32017-11-21 17:26:09 +01001203 vty_out(vty, "Conn ID %s is invalid.%s",
1204 conn_id, VTY_NEWLINE);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001205 return CMD_WARNING;
1206 }
1207
1208 if (strcmp(argv[3], "in") == 0)
1209 tap = &conn->tap_in;
1210 else if (strcmp(argv[3], "out") == 0)
1211 tap = &conn->tap_out;
1212 else {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001213 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1214 return CMD_WARNING;
1215 }
1216
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001217 memset(&tap->forward, 0, sizeof(tap->forward));
Philipp Maier87bd9be2017-08-22 16:35:41 +02001218 inet_aton(argv[4], &tap->forward.sin_addr);
1219 tap->forward.sin_port = htons(atoi(argv[5]));
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001220 tap->enabled = 1;
1221 return CMD_SUCCESS;
1222}
1223
1224DEFUN(free_endp, free_endp_cmd,
1225 "free-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001226 "Free the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001227{
1228 struct mgcp_trunk_config *trunk;
1229 struct mgcp_endpoint *endp;
1230
1231 trunk = find_trunk(g_cfg, atoi(argv[0]));
1232 if (!trunk) {
1233 vty_out(vty, "%%Trunk %d not found in the config.%s",
1234 atoi(argv[0]), VTY_NEWLINE);
1235 return CMD_WARNING;
1236 }
1237
1238 if (!trunk->endpoints) {
1239 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1240 trunk->trunk_nr, VTY_NEWLINE);
1241 return CMD_WARNING;
1242 }
1243
1244 int endp_no = strtoul(argv[1], NULL, 16);
1245 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1246 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001247 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001248 return CMD_WARNING;
1249 }
1250
1251 endp = &trunk->endpoints[endp_no];
Philipp Maier1355d7e2018-02-01 14:30:06 +01001252 mgcp_endp_release(endp);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001253 return CMD_SUCCESS;
1254}
1255
1256DEFUN(reset_endp, reset_endp_cmd,
1257 "reset-endpoint <0-64> NUMBER",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001258 "Reset the given endpoint\n" "Trunk number\n" "Endpoint number in hex.\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001259{
1260 struct mgcp_trunk_config *trunk;
1261 struct mgcp_endpoint *endp;
1262 int endp_no, rc;
1263
1264 trunk = find_trunk(g_cfg, atoi(argv[0]));
1265 if (!trunk) {
1266 vty_out(vty, "%%Trunk %d not found in the config.%s",
1267 atoi(argv[0]), VTY_NEWLINE);
1268 return CMD_WARNING;
1269 }
1270
1271 if (!trunk->endpoints) {
1272 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1273 trunk->trunk_nr, VTY_NEWLINE);
1274 return CMD_WARNING;
1275 }
1276
1277 endp_no = strtoul(argv[1], NULL, 16);
1278 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1279 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001280 argv[1], endp_no, VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001281 return CMD_WARNING;
1282 }
1283
1284 endp = &trunk->endpoints[endp_no];
1285 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1286 if (rc < 0) {
1287 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1288 return CMD_WARNING;
1289 }
1290 return CMD_SUCCESS;
1291}
1292
1293DEFUN(reset_all_endp, reset_all_endp_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001294 "reset-all-endpoints", "Reset all endpoints\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001295{
1296 int rc;
1297
1298 rc = mgcp_send_reset_all(g_cfg);
1299 if (rc < 0) {
1300 vty_out(vty, "Error %d during endpoint reset.%s",
1301 rc, VTY_NEWLINE);
1302 return CMD_WARNING;
1303 }
1304 return CMD_SUCCESS;
1305}
1306
1307#define OSMUX_STR "RTP multiplexing\n"
1308DEFUN(cfg_mgcp_osmux,
1309 cfg_mgcp_osmux_cmd,
1310 "osmux (on|off|only)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001311 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001312{
1313 if (strcmp(argv[0], "off") == 0) {
1314 g_cfg->osmux = OSMUX_USAGE_OFF;
1315 return CMD_SUCCESS;
Pau Espin Pedrolb542b042019-04-23 13:09:32 +02001316 } else if (strcmp(argv[0], "on") == 0)
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001317 g_cfg->osmux = OSMUX_USAGE_ON;
1318 else if (strcmp(argv[0], "only") == 0)
1319 g_cfg->osmux = OSMUX_USAGE_ONLY;
1320
1321 if (g_cfg->trunk.audio_loop) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001322 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001323 return CMD_WARNING;
1324 }
1325
1326 return CMD_SUCCESS;
Pau Espin Pedrolb542b042019-04-23 13:09:32 +02001327
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001328}
1329
1330DEFUN(cfg_mgcp_osmux_ip,
1331 cfg_mgcp_osmux_ip_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001332 "osmux bind-ip A.B.C.D", OSMUX_STR IP_STR "IPv4 Address to bind to\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001333{
1334 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1335 return CMD_SUCCESS;
1336}
1337
1338DEFUN(cfg_mgcp_osmux_batch_factor,
1339 cfg_mgcp_osmux_batch_factor_cmd,
1340 "osmux batch-factor <1-8>",
1341 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1342{
1343 g_cfg->osmux_batch = atoi(argv[0]);
1344 return CMD_SUCCESS;
1345}
1346
1347DEFUN(cfg_mgcp_osmux_batch_size,
1348 cfg_mgcp_osmux_batch_size_cmd,
1349 "osmux batch-size <1-65535>",
1350 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1351{
1352 g_cfg->osmux_batch_size = atoi(argv[0]);
1353 return CMD_SUCCESS;
1354}
1355
1356DEFUN(cfg_mgcp_osmux_port,
1357 cfg_mgcp_osmux_port_cmd,
Philipp Maier87bd9be2017-08-22 16:35:41 +02001358 "osmux port <1-65535>", OSMUX_STR "port\n" "UDP port\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001359{
1360 g_cfg->osmux_port = atoi(argv[0]);
1361 return CMD_SUCCESS;
1362}
1363
1364DEFUN(cfg_mgcp_osmux_dummy,
1365 cfg_mgcp_osmux_dummy_cmd,
1366 "osmux dummy (on|off)",
Philipp Maier87bd9be2017-08-22 16:35:41 +02001367 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n"
1368 "Disable dummy padding\n")
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001369{
1370 if (strcmp(argv[0], "on") == 0)
1371 g_cfg->osmux_dummy = 1;
1372 else if (strcmp(argv[0], "off") == 0)
1373 g_cfg->osmux_dummy = 0;
1374
1375 return CMD_SUCCESS;
1376}
1377
Philipp Maier12943ea2018-01-17 15:40:25 +01001378DEFUN(cfg_mgcp_domain,
1379 cfg_mgcp_domain_cmd,
Neels Hofmeyr352eed02018-08-20 23:59:32 +02001380 "domain NAME",
1381 "Set the domain part expected in MGCP messages' endpoint names\n"
1382 "Qualified domain name expected in MGCP endpoint names, or '*' to accept any domain\n")
Philipp Maier12943ea2018-01-17 15:40:25 +01001383{
1384 osmo_strlcpy(g_cfg->domain, argv[0], sizeof(g_cfg->domain));
1385 return CMD_SUCCESS;
1386}
1387
Oliver Smithe36b7752019-01-22 16:31:36 +01001388DEFUN(cfg_mgcp_conn_timeout,
1389 cfg_mgcp_conn_timeout_cmd,
Oliver Smithd2ce4442019-06-26 09:56:44 +02001390 "conn-timeout <0-65534>",
1391 "Set a time after which inactive connections (CIs) are closed. Set to 0 to disable timeout. This can be used to"
1392 " work around interoperability problems causing connections to stay open forever, and slowly exhausting all"
Oliver Smith189f29e2019-06-26 12:08:20 +02001393 " available ports. Enable keep-alive packets in MGW clients when using this option together with LCLS (OsmoBSC,"
1394 " OsmoMSC: 'rtp keep-alive')!\n"
Oliver Smithe36b7752019-01-22 16:31:36 +01001395 "Timeout value (sec.)\n")
1396{
1397 g_cfg->conn_timeout = strtoul(argv[0], NULL, 10);
1398 return CMD_SUCCESS;
1399}
1400
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001401int mgcp_vty_init(void)
1402{
1403 install_element_ve(&show_mgcp_cmd);
Stefan Sperling12086582018-06-26 15:26:28 +02001404 install_element_ve(&show_mgcp_endpoint_cmd);
1405 install_element_ve(&show_mgcp_trunk_endpoint_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001406 install_element(ENABLE_NODE, &loop_conn_cmd);
1407 install_element(ENABLE_NODE, &tap_rtp_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001408 install_element(ENABLE_NODE, &free_endp_cmd);
1409 install_element(ENABLE_NODE, &reset_endp_cmd);
1410 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1411
1412 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1413 install_node(&mgcp_node, config_write_mgcp);
1414
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001415 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001416 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1417 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1418 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001419 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001420 install_element(MGCP_NODE, &cfg_mgcp_rtp_port_range_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001421 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001422 install_element(MGCP_NODE, &cfg_mgcp_rtp_bind_ip_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001423 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
Philipp Maierf1889d82017-11-08 14:59:39 +01001424 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bind_ip_cmd);
Philipp Maier1cb1e382017-11-02 17:16:04 +01001425 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_probing_cmd);
1426 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_probing_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001427 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1428 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1429 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1430 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1431 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1432 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1433 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1434 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1435 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001436 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1437 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1438 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1439 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1440 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1441 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
Philipp Maier87bd9be2017-08-22 16:35:41 +02001442 install_element(MGCP_NODE, &cfg_mgcp_rtp_accept_all_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001443 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1444 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1445 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1446 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1447 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1448 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1449 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1450 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
Philipp Maier9fc8a022019-02-20 12:26:52 +01001451 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_rfc5993hr_cmd);
1452 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_rfc5993hr_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001453 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1454 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1455 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1456 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1457 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1458 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1459 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1460 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1461 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1462 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1463 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1464 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1465 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Philipp Maier12943ea2018-01-17 15:40:25 +01001466 install_element(MGCP_NODE, &cfg_mgcp_domain_cmd);
Oliver Smithe36b7752019-01-22 16:31:36 +01001467 install_element(MGCP_NODE, &cfg_mgcp_conn_timeout_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001468
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001469 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1470 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001471 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1472 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1473 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1474 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1475 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1476 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1477 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1478 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1479 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1480 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1481 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1482 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1483 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
Philipp Maier9fc8a022019-02-20 12:26:52 +01001484 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_rfc5993hr_cmd);
1485 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_rfc5993hr_cmd);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001486 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1487 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1488 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1489 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1490 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1491 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1492 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1493 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1494 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1495
1496 return 0;
1497}
1498
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001499int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1500 enum mgcp_role role)
1501{
1502 int rc;
1503 struct mgcp_trunk_config *trunk;
1504
1505 cfg->osmux_port = OSMUX_PORT;
1506 cfg->osmux_batch = 4;
1507 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1508
1509 g_cfg = cfg;
1510 rc = vty_read_config_file(config_file, NULL);
1511 if (rc < 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001512 fprintf(stderr, "Failed to parse the config file: '%s'\n",
1513 config_file);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001514 return rc;
1515 }
1516
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001517 if (!g_cfg->source_addr) {
1518 fprintf(stderr, "You need to specify a bind address.\n");
1519 return -1;
1520 }
1521
Philipp Maier48454982017-11-10 16:46:41 +01001522 if (mgcp_endpoints_allocate(&g_cfg->trunk) != 0) {
Philipp Maier87bd9be2017-08-22 16:35:41 +02001523 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001524 "Failed to initialize the virtual trunk (%d endpoints)\n",
1525 g_cfg->trunk.number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001526 return -1;
1527 }
1528
1529 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
Philipp Maier48454982017-11-10 16:46:41 +01001530 if (mgcp_endpoints_allocate(trunk) != 0) {
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001531 LOGP(DLMGCP, LOGL_ERROR,
Philipp Maier48454982017-11-10 16:46:41 +01001532 "Failed to initialize trunk %d (%d endpoints)\n",
1533 trunk->trunk_nr, trunk->number_endpoints);
Neels Hofmeyrf83ec562017-09-07 19:18:40 +02001534 return -1;
1535 }
1536 }
1537 cfg->role = role;
1538
1539 return 0;
1540}