blob: 420333dbfcf8041abcd49d0cdcc30c0a62f7067c [file] [log] [blame]
Neels Hofmeyre9920f22017-07-10 15:07:22 +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
24
25#include <osmocom/core/talloc.h>
26
27#include <osmocom/legacy_mgcp/mgcp.h>
28#include <osmocom/legacy_mgcp/mgcp_internal.h>
29#include <osmocom/legacy_mgcp/vty.h>
30
31#include <string.h>
Pau Espin Pedrolba61f682018-05-16 14:03:38 +020032#include <inttypes.h>
Neels Hofmeyre9920f22017-07-10 15:07:22 +020033
34#define RTCP_OMIT_STR "Drop RTCP packets in both directions\n"
35#define RTP_PATCH_STR "Modify RTP packet header in both directions\n"
36#define RTP_KEEPALIVE_STR "Send dummy UDP packet to net RTP destination\n"
37
38static struct mgcp_config *g_cfg = NULL;
39
40static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
41{
42 struct mgcp_trunk_config *trunk;
43
44 if (nr == 0)
45 trunk = &cfg->trunk;
46 else
47 trunk = mgcp_trunk_num(cfg, nr);
48
49 return trunk;
50}
51
52/*
53 * vty code for mgcp below
54 */
55struct cmd_node mgcp_node = {
56 MGCP_NODE,
57 "%s(config-mgcp)# ",
58 1,
59};
60
61struct cmd_node trunk_node = {
62 TRUNK_NODE,
63 "%s(config-mgcp-trunk)# ",
64 1,
65};
66
67static int config_write_mgcp(struct vty *vty)
68{
69 vty_out(vty, "mgcp%s", VTY_NEWLINE);
70 if (g_cfg->local_ip)
71 vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
72 if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
73 vty_out(vty, " bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
74 vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
75 vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
76
77 if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC)
78 vty_out(vty, " rtp bts-base %u%s", g_cfg->bts_ports.base_port, VTY_NEWLINE);
79 else
80 vty_out(vty, " rtp bts-range %u %u%s",
81 g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE);
82 if (g_cfg->bts_ports.bind_addr)
83 vty_out(vty, " rtp bts-bind-ip %s%s", g_cfg->bts_ports.bind_addr, VTY_NEWLINE);
84
85 if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
86 vty_out(vty, " rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE);
87 else
88 vty_out(vty, " rtp net-range %u %u%s",
89 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
90 if (g_cfg->net_ports.bind_addr)
91 vty_out(vty, " rtp net-bind-ip %s%s", g_cfg->net_ports.bind_addr, VTY_NEWLINE);
92
93 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
94 if (g_cfg->trunk.keepalive_interval == MGCP_KEEPALIVE_ONCE)
95 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
96 else if (g_cfg->trunk.keepalive_interval)
97 vty_out(vty, " rtp keep-alive %d%s",
98 g_cfg->trunk.keepalive_interval, VTY_NEWLINE);
99 else
100 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
101
102 if (g_cfg->trunk.omit_rtcp)
103 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
104 else
105 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
106 if (g_cfg->trunk.force_constant_ssrc || g_cfg->trunk.force_aligned_timing) {
107 vty_out(vty, " %srtp-patch ssrc%s",
108 g_cfg->trunk.force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
109 vty_out(vty, " %srtp-patch timestamp%s",
110 g_cfg->trunk.force_aligned_timing ? "" : "no ", VTY_NEWLINE);
111 } else
112 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
113 if (g_cfg->trunk.audio_payload != -1)
114 vty_out(vty, " sdp audio-payload number %d%s",
115 g_cfg->trunk.audio_payload, VTY_NEWLINE);
116 if (g_cfg->trunk.audio_name)
117 vty_out(vty, " sdp audio-payload name %s%s",
118 g_cfg->trunk.audio_name, VTY_NEWLINE);
119 if (g_cfg->trunk.audio_fmtp_extra)
120 vty_out(vty, " sdp audio fmtp-extra %s%s",
121 g_cfg->trunk.audio_fmtp_extra, VTY_NEWLINE);
122 vty_out(vty, " %ssdp audio-payload send-ptime%s",
123 g_cfg->trunk.audio_send_ptime ? "" : "no ", VTY_NEWLINE);
124 vty_out(vty, " %ssdp audio-payload send-name%s",
125 g_cfg->trunk.audio_send_name ? "" : "no ", VTY_NEWLINE);
126 vty_out(vty, " loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
127 vty_out(vty, " number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
128 vty_out(vty, " %sallow-transcoding%s",
129 g_cfg->trunk.no_audio_transcoding ? "no " : "", VTY_NEWLINE);
130 if (g_cfg->call_agent_addr)
131 vty_out(vty, " call-agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
132 if (g_cfg->transcoder_ip)
133 vty_out(vty, " transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE);
134
135 if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC)
136 vty_out(vty, " rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE);
137 else
138 vty_out(vty, " rtp transcoder-range %u %u%s",
139 g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE);
140 if (g_cfg->bts_force_ptime > 0)
141 vty_out(vty, " rtp force-ptime %d%s", g_cfg->bts_force_ptime, VTY_NEWLINE);
142 vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
143
144 switch (g_cfg->osmux) {
145 case OSMUX_USAGE_ON:
146 vty_out(vty, " osmux on%s", VTY_NEWLINE);
147 break;
148 case OSMUX_USAGE_ONLY:
149 vty_out(vty, " osmux only%s", VTY_NEWLINE);
150 break;
151 case OSMUX_USAGE_OFF:
152 default:
153 vty_out(vty, " osmux off%s", VTY_NEWLINE);
154 break;
155 }
156 if (g_cfg->osmux) {
157 vty_out(vty, " osmux bind-ip %s%s",
158 g_cfg->osmux_addr, VTY_NEWLINE);
159 vty_out(vty, " osmux batch-factor %d%s",
160 g_cfg->osmux_batch, VTY_NEWLINE);
161 vty_out(vty, " osmux batch-size %u%s",
162 g_cfg->osmux_batch_size, VTY_NEWLINE);
163 vty_out(vty, " osmux port %u%s",
164 g_cfg->osmux_port, VTY_NEWLINE);
165 vty_out(vty, " osmux dummy %s%s",
166 g_cfg->osmux_dummy ? "on" : "off", VTY_NEWLINE);
167 }
Pau Espin Pedrolba61f682018-05-16 14:03:38 +0200168 if (g_cfg->bts_use_jibuf)
169 vty_out(vty, " bts-jitter-buffer%s", VTY_NEWLINE);
170 if (g_cfg->bts_jitter_delay_min)
Pau Espin Pedroldde80f32018-08-16 15:10:42 +0200171 vty_out(vty, " bts-jitter-buffer-delay-min %"PRIu32"%s", g_cfg->bts_jitter_delay_min, VTY_NEWLINE);
Pau Espin Pedrolba61f682018-05-16 14:03:38 +0200172 if (g_cfg->bts_jitter_delay_max)
Pau Espin Pedroldde80f32018-08-16 15:10:42 +0200173 vty_out(vty, " bts-jitter-buffer-delay-max %"PRIu32"%s", g_cfg->bts_jitter_delay_max, VTY_NEWLINE);
Pau Espin Pedrolba61f682018-05-16 14:03:38 +0200174
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200175 return CMD_SUCCESS;
176}
177
178static void dump_rtp_end(const char *end_name, struct vty *vty,
179 struct mgcp_rtp_state *state, struct mgcp_rtp_end *end)
180{
181 struct mgcp_rtp_codec *codec = &end->codec;
182
183 vty_out(vty,
184 " %s%s"
185 " Timestamp Errs: %d->%d%s"
186 " Dropped Packets: %d%s"
187 " Payload Type: %d Rate: %u Channels: %d %s"
188 " Frame Duration: %u Frame Denominator: %u%s"
189 " FPP: %d Packet Duration: %u%s"
190 " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s"
191 " Output-Enabled: %d Force-PTIME: %d%s",
192 end_name, VTY_NEWLINE,
193 state->in_stream.err_ts_counter,
194 state->out_stream.err_ts_counter, VTY_NEWLINE,
195 end->dropped_packets, VTY_NEWLINE,
196 codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE,
197 codec->frame_duration_num, codec->frame_duration_den, VTY_NEWLINE,
198 end->frames_per_packet, end->packet_duration_ms, VTY_NEWLINE,
199 end->fmtp_extra, codec->audio_name, codec->subtype_name, VTY_NEWLINE,
200 end->output_enabled, end->force_output_ptime, VTY_NEWLINE);
201}
202
203static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg, int verbose)
204{
205 int i;
206
207 vty_out(vty, "%s trunk nr %d with %d endpoints:%s",
208 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
209 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
210
211 if (!cfg->endpoints) {
212 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
213 return;
214 }
215
216 for (i = 1; i < cfg->number_endpoints; ++i) {
217 struct mgcp_endpoint *endp = &cfg->endpoints[i];
218 vty_out(vty,
219 " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s "
220 "traffic received bts: %u remote: %u transcoder: %u/%u%s",
221 i, endp->ci,
222 ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
223 ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port),
224 inet_ntoa(endp->bts_end.addr),
225 endp->bts_end.packets, endp->net_end.packets,
226 endp->trans_net.packets, endp->trans_bts.packets,
227 VTY_NEWLINE);
228
229 if (verbose && endp->allocated) {
230 dump_rtp_end("Net->BTS", vty, &endp->bts_state, &endp->bts_end);
231 dump_rtp_end("BTS->Net", vty, &endp->net_state, &endp->net_end);
232 }
233 }
234}
235
236DEFUN(show_mcgp, show_mgcp_cmd,
237 "show mgcp [stats]",
238 SHOW_STR
239 "Display information about the MGCP Media Gateway\n"
240 "Include Statistics\n")
241{
242 struct mgcp_trunk_config *trunk;
243 int show_stats = argc >= 1;
244
245 dump_trunk(vty, &g_cfg->trunk, show_stats);
246
247 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
248 dump_trunk(vty, trunk, show_stats);
249
250 if (g_cfg->osmux)
251 vty_out(vty, "Osmux used CID: %d%s", osmux_used_cid(), VTY_NEWLINE);
Pau Espin Pedrolba61f682018-05-16 14:03:38 +0200252 vty_out(vty, "Jitter Buffer by default on Uplink : %s%s",
253 g_cfg->bts_use_jibuf ? "on" : "off", VTY_NEWLINE);
254 if (g_cfg->bts_use_jibuf)
255 vty_out(vty, "Jitter Buffer delays: min=%"PRIu32" max=%"PRIu32"%s",
256 g_cfg->bts_jitter_delay_min, g_cfg->bts_jitter_delay_max, VTY_NEWLINE);
Neels Hofmeyre9920f22017-07-10 15:07:22 +0200257
258 return CMD_SUCCESS;
259}
260
261DEFUN(cfg_mgcp,
262 cfg_mgcp_cmd,
263 "mgcp",
264 "Configure the MGCP")
265{
266 vty->node = MGCP_NODE;
267 return CMD_SUCCESS;
268}
269
270DEFUN(cfg_mgcp_local_ip,
271 cfg_mgcp_local_ip_cmd,
272 "local ip A.B.C.D",
273 "Local options for the SDP record\n"
274 IP_STR
275 "IPv4 Address to use in SDP record\n")
276{
277 osmo_talloc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
278 return CMD_SUCCESS;
279}
280
281DEFUN(cfg_mgcp_bts_ip,
282 cfg_mgcp_bts_ip_cmd,
283 "bts ip A.B.C.D",
284 "BTS Audio source/destination options\n"
285 IP_STR
286 "IPv4 Address of the BTS\n")
287{
288 osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
289 inet_aton(g_cfg->bts_ip, &g_cfg->bts_in);
290 return CMD_SUCCESS;
291}
292
293#define BIND_STR "Listen/Bind related socket option\n"
294DEFUN(cfg_mgcp_bind_ip,
295 cfg_mgcp_bind_ip_cmd,
296 "bind ip A.B.C.D",
297 BIND_STR
298 IP_STR
299 "IPv4 Address to bind to\n")
300{
301 osmo_talloc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
302 return CMD_SUCCESS;
303}
304
305DEFUN(cfg_mgcp_bind_port,
306 cfg_mgcp_bind_port_cmd,
307 "bind port <0-65534>",
308 BIND_STR
309 "Port information\n"
310 "UDP port to listen for MGCP messages\n")
311{
312 unsigned int port = atoi(argv[0]);
313 g_cfg->source_port = port;
314 return CMD_SUCCESS;
315}
316
317DEFUN(cfg_mgcp_bind_early,
318 cfg_mgcp_bind_early_cmd,
319 "bind early (0|1)",
320 BIND_STR
321 "Bind local ports on start up\n"
322 "Bind on demand\n" "Bind on startup\n")
323{
324 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
325 return CMD_WARNING;
326}
327
328static void parse_base(struct mgcp_port_range *range, const char **argv)
329{
330 unsigned int port = atoi(argv[0]);
331 range->mode = PORT_ALLOC_STATIC;
332 range->base_port = port;
333}
334
335static void parse_range(struct mgcp_port_range *range, const char **argv)
336{
337 range->mode = PORT_ALLOC_DYNAMIC;
338 range->range_start = atoi(argv[0]);
339 range->range_end = atoi(argv[1]);
340 range->last_port = g_cfg->bts_ports.range_start;
341}
342
343
344#define RTP_STR "RTP configuration\n"
345#define BTS_START_STR "First UDP port allocated for the BTS side\n"
346#define NET_START_STR "First UDP port allocated for the NET side\n"
347#define UDP_PORT_STR "UDP Port number\n"
348DEFUN(cfg_mgcp_rtp_bts_base_port,
349 cfg_mgcp_rtp_bts_base_port_cmd,
350 "rtp bts-base <0-65534>",
351 RTP_STR
352 BTS_START_STR
353 UDP_PORT_STR)
354{
355 parse_base(&g_cfg->bts_ports, argv);
356 return CMD_SUCCESS;
357}
358
359#define RANGE_START_STR "Start of the range of ports\n"
360#define RANGE_END_STR "End of the range of ports\n"
361DEFUN(cfg_mgcp_rtp_bts_range,
362 cfg_mgcp_rtp_bts_range_cmd,
363 "rtp bts-range <0-65534> <0-65534>",
364 RTP_STR "Range of ports to use for the BTS side\n"
365 RANGE_START_STR RANGE_END_STR)
366{
367 parse_range(&g_cfg->bts_ports, argv);
368 return CMD_SUCCESS;
369}
370
371DEFUN(cfg_mgcp_rtp_net_range,
372 cfg_mgcp_rtp_net_range_cmd,
373 "rtp net-range <0-65534> <0-65534>",
374 RTP_STR "Range of ports to use for the NET side\n"
375 RANGE_START_STR RANGE_END_STR)
376{
377 parse_range(&g_cfg->net_ports, argv);
378 return CMD_SUCCESS;
379}
380
381DEFUN(cfg_mgcp_rtp_net_base_port,
382 cfg_mgcp_rtp_net_base_port_cmd,
383 "rtp net-base <0-65534>",
384 RTP_STR NET_START_STR UDP_PORT_STR)
385{
386 parse_base(&g_cfg->net_ports, argv);
387 return CMD_SUCCESS;
388}
389
390ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd,
391 "rtp base <0-65534>",
392 RTP_STR BTS_START_STR UDP_PORT_STR)
393
394DEFUN(cfg_mgcp_rtp_transcoder_range,
395 cfg_mgcp_rtp_transcoder_range_cmd,
396 "rtp transcoder-range <0-65534> <0-65534>",
397 RTP_STR "Range of ports to use for the Transcoder\n"
398 RANGE_START_STR RANGE_END_STR)
399{
400 parse_range(&g_cfg->transcoder_ports, argv);
401 return CMD_SUCCESS;
402}
403
404DEFUN(cfg_mgcp_rtp_transcoder_base,
405 cfg_mgcp_rtp_transcoder_base_cmd,
406 "rtp transcoder-base <0-65534>",
407 RTP_STR "First UDP port allocated for the Transcoder side\n"
408 UDP_PORT_STR)
409{
410 parse_base(&g_cfg->transcoder_ports, argv);
411 return CMD_SUCCESS;
412}
413
414DEFUN(cfg_mgcp_rtp_bts_bind_ip,
415 cfg_mgcp_rtp_bts_bind_ip_cmd,
416 "rtp bts-bind-ip A.B.C.D",
417 RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
418{
419 osmo_talloc_replace_string(g_cfg, &g_cfg->bts_ports.bind_addr, argv[0]);
420 return CMD_SUCCESS;
421}
422
423DEFUN(cfg_mgcp_rtp_no_bts_bind_ip,
424 cfg_mgcp_rtp_no_bts_bind_ip_cmd,
425 "no rtp bts-bind-ip",
426 NO_STR RTP_STR "Bind endpoints facing the BTS\n" "Address to bind to\n")
427{
428 talloc_free(g_cfg->bts_ports.bind_addr);
429 g_cfg->bts_ports.bind_addr = NULL;
430 return CMD_SUCCESS;
431}
432
433DEFUN(cfg_mgcp_rtp_net_bind_ip,
434 cfg_mgcp_rtp_net_bind_ip_cmd,
435 "rtp net-bind-ip A.B.C.D",
436 RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
437{
438 osmo_talloc_replace_string(g_cfg, &g_cfg->net_ports.bind_addr, argv[0]);
439 return CMD_SUCCESS;
440}
441
442DEFUN(cfg_mgcp_rtp_no_net_bind_ip,
443 cfg_mgcp_rtp_no_net_bind_ip_cmd,
444 "no rtp net-bind-ip",
445 NO_STR RTP_STR "Bind endpoints facing the Network\n" "Address to bind to\n")
446{
447 talloc_free(g_cfg->net_ports.bind_addr);
448 g_cfg->net_ports.bind_addr = NULL;
449 return CMD_SUCCESS;
450}
451
452DEFUN(cfg_mgcp_rtp_ip_dscp,
453 cfg_mgcp_rtp_ip_dscp_cmd,
454 "rtp ip-dscp <0-255>",
455 RTP_STR
456 "Apply IP_TOS to the audio stream (including Osmux)\n" "The DSCP value\n")
457{
458 int dscp = atoi(argv[0]);
459 g_cfg->endp_dscp = dscp;
460 return CMD_SUCCESS;
461}
462
463ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
464 "rtp ip-tos <0-255>",
465 RTP_STR
466 "Apply IP_TOS to the audio stream\n" "The DSCP value\n")
467
468#define FORCE_PTIME_STR "Force a fixed ptime for packets sent to the BTS"
469DEFUN(cfg_mgcp_rtp_force_ptime,
470 cfg_mgcp_rtp_force_ptime_cmd,
471 "rtp force-ptime (10|20|40)",
472 RTP_STR FORCE_PTIME_STR
473 "The required ptime (packet duration) in ms\n"
474 "10 ms\n20 ms\n40 ms\n")
475{
476 g_cfg->bts_force_ptime = atoi(argv[0]);
477 return CMD_SUCCESS;
478}
479
480DEFUN(cfg_mgcp_no_rtp_force_ptime,
481 cfg_mgcp_no_rtp_force_ptime_cmd,
482 "no rtp force-ptime",
483 NO_STR RTP_STR FORCE_PTIME_STR)
484{
485 g_cfg->bts_force_ptime = 0;
486 return CMD_SUCCESS;
487}
488
489DEFUN(cfg_mgcp_sdp_fmtp_extra,
490 cfg_mgcp_sdp_fmtp_extra_cmd,
491 "sdp audio fmtp-extra .NAME",
492 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
493 "Extra Information\n")
494{
495 char *txt = argv_concat(argv, argc, 0);
496 if (!txt)
497 return CMD_WARNING;
498
499 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_fmtp_extra, txt);
500 talloc_free(txt);
501 return CMD_SUCCESS;
502}
503
504DEFUN(cfg_mgcp_allow_transcoding,
505 cfg_mgcp_allow_transcoding_cmd,
506 "allow-transcoding",
507 "Allow transcoding\n")
508{
509 g_cfg->trunk.no_audio_transcoding = 0;
510 return CMD_SUCCESS;
511}
512
513DEFUN(cfg_mgcp_no_allow_transcoding,
514 cfg_mgcp_no_allow_transcoding_cmd,
515 "no allow-transcoding",
516 NO_STR "Allow transcoding\n")
517{
518 g_cfg->trunk.no_audio_transcoding = 1;
519 return CMD_SUCCESS;
520}
521
522#define SDP_STR "SDP File related options\n"
523#define AUDIO_STR "Audio payload options\n"
524DEFUN(cfg_mgcp_sdp_payload_number,
525 cfg_mgcp_sdp_payload_number_cmd,
526 "sdp audio-payload number <0-255>",
527 SDP_STR AUDIO_STR
528 "Number\n" "Payload number\n")
529{
530 unsigned int payload = atoi(argv[0]);
531 g_cfg->trunk.audio_payload = payload;
532 return CMD_SUCCESS;
533}
534
535ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_number, cfg_mgcp_sdp_payload_number_cmd_old,
536 "sdp audio payload number <0-255>",
537 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload number\n")
538
539
540DEFUN(cfg_mgcp_sdp_payload_name,
541 cfg_mgcp_sdp_payload_name_cmd,
542 "sdp audio-payload name NAME",
543 SDP_STR AUDIO_STR "Name\n" "Payload name\n")
544{
545 osmo_talloc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
546 return CMD_SUCCESS;
547}
548
549ALIAS_DEPRECATED(cfg_mgcp_sdp_payload_name, cfg_mgcp_sdp_payload_name_cmd_old,
550 "sdp audio payload name NAME",
551 SDP_STR AUDIO_STR AUDIO_STR "Name\n" "Payload name\n")
552
553DEFUN(cfg_mgcp_sdp_payload_send_ptime,
554 cfg_mgcp_sdp_payload_send_ptime_cmd,
555 "sdp audio-payload send-ptime",
556 SDP_STR AUDIO_STR
557 "Send SDP ptime (packet duration) attribute\n")
558{
559 g_cfg->trunk.audio_send_ptime = 1;
560 return CMD_SUCCESS;
561}
562
563DEFUN(cfg_mgcp_no_sdp_payload_send_ptime,
564 cfg_mgcp_no_sdp_payload_send_ptime_cmd,
565 "no sdp audio-payload send-ptime",
566 NO_STR SDP_STR AUDIO_STR
567 "Send SDP ptime (packet duration) attribute\n")
568{
569 g_cfg->trunk.audio_send_ptime = 0;
570 return CMD_SUCCESS;
571}
572
573DEFUN(cfg_mgcp_sdp_payload_send_name,
574 cfg_mgcp_sdp_payload_send_name_cmd,
575 "sdp audio-payload send-name",
576 SDP_STR AUDIO_STR
577 "Send SDP rtpmap with the audio name\n")
578{
579 g_cfg->trunk.audio_send_name = 1;
580 return CMD_SUCCESS;
581}
582
583DEFUN(cfg_mgcp_no_sdp_payload_send_name,
584 cfg_mgcp_no_sdp_payload_send_name_cmd,
585 "no sdp audio-payload send-name",
586 NO_STR SDP_STR AUDIO_STR
587 "Send SDP rtpmap with the audio name\n")
588{
589 g_cfg->trunk.audio_send_name = 0;
590 return CMD_SUCCESS;
591}
592
593DEFUN(cfg_mgcp_loop,
594 cfg_mgcp_loop_cmd,
595 "loop (0|1)",
596 "Loop audio for all endpoints on main trunk\n"
597 "Don't Loop\n" "Loop\n")
598{
599 if (g_cfg->osmux) {
600 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
601 return CMD_WARNING;
602 }
603 g_cfg->trunk.audio_loop = atoi(argv[0]);
604 return CMD_SUCCESS;
605}
606
607DEFUN(cfg_mgcp_force_realloc,
608 cfg_mgcp_force_realloc_cmd,
609 "force-realloc (0|1)",
610 "Force endpoint reallocation when the endpoint is still seized\n"
611 "Don't force reallocation\n" "force reallocation\n")
612{
613 g_cfg->trunk.force_realloc = atoi(argv[0]);
614 return CMD_SUCCESS;
615}
616
617DEFUN(cfg_mgcp_number_endp,
618 cfg_mgcp_number_endp_cmd,
619 "number endpoints <0-65534>",
620 "Number options\n" "Endpoints available\n" "Number endpoints\n")
621{
622 /* + 1 as we start counting at one */
623 g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
624 return CMD_SUCCESS;
625}
626
627DEFUN(cfg_mgcp_omit_rtcp,
628 cfg_mgcp_omit_rtcp_cmd,
629 "rtcp-omit",
630 RTCP_OMIT_STR)
631{
632 g_cfg->trunk.omit_rtcp = 1;
633 return CMD_SUCCESS;
634}
635
636DEFUN(cfg_mgcp_no_omit_rtcp,
637 cfg_mgcp_no_omit_rtcp_cmd,
638 "no rtcp-omit",
639 NO_STR RTCP_OMIT_STR)
640{
641 g_cfg->trunk.omit_rtcp = 0;
642 return CMD_SUCCESS;
643}
644
645DEFUN(cfg_mgcp_patch_rtp_ssrc,
646 cfg_mgcp_patch_rtp_ssrc_cmd,
647 "rtp-patch ssrc",
648 RTP_PATCH_STR
649 "Force a fixed SSRC\n"
650 )
651{
652 g_cfg->trunk.force_constant_ssrc = 1;
653 return CMD_SUCCESS;
654}
655
656DEFUN(cfg_mgcp_no_patch_rtp_ssrc,
657 cfg_mgcp_no_patch_rtp_ssrc_cmd,
658 "no rtp-patch ssrc",
659 NO_STR RTP_PATCH_STR
660 "Force a fixed SSRC\n"
661 )
662{
663 g_cfg->trunk.force_constant_ssrc = 0;
664 return CMD_SUCCESS;
665}
666
667DEFUN(cfg_mgcp_patch_rtp_ts,
668 cfg_mgcp_patch_rtp_ts_cmd,
669 "rtp-patch timestamp",
670 RTP_PATCH_STR
671 "Adjust RTP timestamp\n"
672 )
673{
674 g_cfg->trunk.force_aligned_timing = 1;
675 return CMD_SUCCESS;
676}
677
678DEFUN(cfg_mgcp_no_patch_rtp_ts,
679 cfg_mgcp_no_patch_rtp_ts_cmd,
680 "no rtp-patch timestamp",
681 NO_STR RTP_PATCH_STR
682 "Adjust RTP timestamp\n"
683 )
684{
685 g_cfg->trunk.force_aligned_timing = 0;
686 return CMD_SUCCESS;
687}
688
689DEFUN(cfg_mgcp_no_patch_rtp,
690 cfg_mgcp_no_patch_rtp_cmd,
691 "no rtp-patch",
692 NO_STR RTP_PATCH_STR)
693{
694 g_cfg->trunk.force_constant_ssrc = 0;
695 g_cfg->trunk.force_aligned_timing = 0;
696 return CMD_SUCCESS;
697}
698
699DEFUN(cfg_mgcp_rtp_keepalive,
700 cfg_mgcp_rtp_keepalive_cmd,
701 "rtp keep-alive <1-120>",
702 RTP_STR RTP_KEEPALIVE_STR
703 "Keep alive interval in secs\n"
704 )
705{
706 mgcp_trunk_set_keepalive(&g_cfg->trunk, atoi(argv[0]));
707 return CMD_SUCCESS;
708}
709
710DEFUN(cfg_mgcp_rtp_keepalive_once,
711 cfg_mgcp_rtp_keepalive_once_cmd,
712 "rtp keep-alive once",
713 RTP_STR RTP_KEEPALIVE_STR
714 "Send dummy packet only once after CRCX/MDCX\n"
715 )
716{
717 mgcp_trunk_set_keepalive(&g_cfg->trunk, MGCP_KEEPALIVE_ONCE);
718 return CMD_SUCCESS;
719}
720
721DEFUN(cfg_mgcp_no_rtp_keepalive,
722 cfg_mgcp_no_rtp_keepalive_cmd,
723 "no rtp keep-alive",
724 NO_STR RTP_STR RTP_KEEPALIVE_STR
725 )
726{
727 mgcp_trunk_set_keepalive(&g_cfg->trunk, 0);
728 return CMD_SUCCESS;
729}
730
731
732
733#define CALL_AGENT_STR "Callagent information\n"
734DEFUN(cfg_mgcp_agent_addr,
735 cfg_mgcp_agent_addr_cmd,
736 "call-agent ip A.B.C.D",
737 CALL_AGENT_STR IP_STR
738 "IPv4 Address of the callagent\n")
739{
740 osmo_talloc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
741 return CMD_SUCCESS;
742}
743
744ALIAS_DEPRECATED(cfg_mgcp_agent_addr, cfg_mgcp_agent_addr_cmd_old,
745 "call agent ip A.B.C.D",
746 CALL_AGENT_STR CALL_AGENT_STR IP_STR
747 "IPv4 Address of the callagent\n")
748
749
750DEFUN(cfg_mgcp_transcoder,
751 cfg_mgcp_transcoder_cmd,
752 "transcoder-mgw A.B.C.D",
753 "Use a MGW to detranscoder RTP\n"
754 "The IP address of the MGW")
755{
756 osmo_talloc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
757 inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in);
758
759 return CMD_SUCCESS;
760}
761
762DEFUN(cfg_mgcp_no_transcoder,
763 cfg_mgcp_no_transcoder_cmd,
764 "no transcoder-mgw",
765 NO_STR "Disable the transcoding\n")
766{
767 if (g_cfg->transcoder_ip) {
768 LOGP(DLMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n");
769 talloc_free(g_cfg->transcoder_ip);
770 g_cfg->transcoder_ip = NULL;
771 }
772
773 return CMD_SUCCESS;
774}
775
776DEFUN(cfg_mgcp_transcoder_remote_base,
777 cfg_mgcp_transcoder_remote_base_cmd,
778 "transcoder-remote-base <0-65534>",
779 "Set the base port for the transcoder\n" "The RTP base port on the transcoder")
780{
781 g_cfg->transcoder_remote_base = atoi(argv[0]);
782 return CMD_SUCCESS;
783}
784
785DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
786 "trunk <1-64>",
787 "Configure a SS7 trunk\n" "Trunk Nr\n")
788{
789 struct mgcp_trunk_config *trunk;
790 int index = atoi(argv[0]);
791
792 trunk = mgcp_trunk_num(g_cfg, index);
793 if (!trunk)
794 trunk = mgcp_trunk_alloc(g_cfg, index);
795
796 if (!trunk) {
797 vty_out(vty, "%%Unable to allocate trunk %u.%s",
798 index, VTY_NEWLINE);
799 return CMD_WARNING;
800 }
801
802 vty->node = TRUNK_NODE;
803 vty->index = trunk;
804 return CMD_SUCCESS;
805}
806
807static int config_write_trunk(struct vty *vty)
808{
809 struct mgcp_trunk_config *trunk;
810
811 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
812 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
813 vty_out(vty, " sdp audio-payload number %d%s",
814 trunk->audio_payload, VTY_NEWLINE);
815 vty_out(vty, " sdp audio-payload name %s%s",
816 trunk->audio_name, VTY_NEWLINE);
817 vty_out(vty, " %ssdp audio-payload send-ptime%s",
818 trunk->audio_send_ptime ? "" : "no ", VTY_NEWLINE);
819 vty_out(vty, " %ssdp audio-payload send-name%s",
820 trunk->audio_send_name ? "" : "no ", VTY_NEWLINE);
821
822 if (trunk->keepalive_interval == MGCP_KEEPALIVE_ONCE)
823 vty_out(vty, " rtp keep-alive once%s", VTY_NEWLINE);
824 else if (trunk->keepalive_interval)
825 vty_out(vty, " rtp keep-alive %d%s",
826 trunk->keepalive_interval, VTY_NEWLINE);
827 else
828 vty_out(vty, " no rtp keep-alive%s", VTY_NEWLINE);
829 vty_out(vty, " loop %d%s",
830 trunk->audio_loop, VTY_NEWLINE);
831 vty_out(vty, " force-realloc %d%s",
832 trunk->force_realloc, VTY_NEWLINE);
833 if (trunk->omit_rtcp)
834 vty_out(vty, " rtcp-omit%s", VTY_NEWLINE);
835 else
836 vty_out(vty, " no rtcp-omit%s", VTY_NEWLINE);
837 if (trunk->force_constant_ssrc || trunk->force_aligned_timing) {
838 vty_out(vty, " %srtp-patch ssrc%s",
839 trunk->force_constant_ssrc ? "" : "no ", VTY_NEWLINE);
840 vty_out(vty, " %srtp-patch timestamp%s",
841 trunk->force_aligned_timing ? "" : "no ", VTY_NEWLINE);
842 } else
843 vty_out(vty, " no rtp-patch%s", VTY_NEWLINE);
844 if (trunk->audio_fmtp_extra)
845 vty_out(vty, " sdp audio fmtp-extra %s%s",
846 trunk->audio_fmtp_extra, VTY_NEWLINE);
847 vty_out(vty, " %sallow-transcoding%s",
848 trunk->no_audio_transcoding ? "no " : "", VTY_NEWLINE);
849 }
850
851 return CMD_SUCCESS;
852}
853
854DEFUN(cfg_trunk_sdp_fmtp_extra,
855 cfg_trunk_sdp_fmtp_extra_cmd,
856 "sdp audio fmtp-extra .NAME",
857 "Add extra fmtp for the SDP file\n" "Audio\n" "Fmtp-extra\n"
858 "Extra Information\n")
859{
860 struct mgcp_trunk_config *trunk = vty->index;
861 char *txt = argv_concat(argv, argc, 0);
862 if (!txt)
863 return CMD_WARNING;
864
865 osmo_talloc_replace_string(g_cfg, &trunk->audio_fmtp_extra, txt);
866 talloc_free(txt);
867 return CMD_SUCCESS;
868}
869
870DEFUN(cfg_trunk_payload_number,
871 cfg_trunk_payload_number_cmd,
872 "sdp audio-payload number <0-255>",
873 SDP_STR AUDIO_STR "Number\n" "Payload Number\n")
874{
875 struct mgcp_trunk_config *trunk = vty->index;
876 unsigned int payload = atoi(argv[0]);
877
878 trunk->audio_payload = payload;
879 return CMD_SUCCESS;
880}
881
882ALIAS_DEPRECATED(cfg_trunk_payload_number, cfg_trunk_payload_number_cmd_old,
883 "sdp audio payload number <0-255>",
884 SDP_STR AUDIO_STR AUDIO_STR "Number\n" "Payload Number\n")
885
886DEFUN(cfg_trunk_payload_name,
887 cfg_trunk_payload_name_cmd,
888 "sdp audio-payload name NAME",
889 SDP_STR AUDIO_STR "Payload\n" "Payload Name\n")
890{
891 struct mgcp_trunk_config *trunk = vty->index;
892
893 osmo_talloc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
894 return CMD_SUCCESS;
895}
896
897ALIAS_DEPRECATED(cfg_trunk_payload_name, cfg_trunk_payload_name_cmd_old,
898 "sdp audio payload name NAME",
899 SDP_STR AUDIO_STR AUDIO_STR "Payload\n" "Payload Name\n")
900
901
902DEFUN(cfg_trunk_loop,
903 cfg_trunk_loop_cmd,
904 "loop (0|1)",
905 "Loop audio for all endpoints on this trunk\n"
906 "Don't Loop\n" "Loop\n")
907{
908 struct mgcp_trunk_config *trunk = vty->index;
909
910 if (g_cfg->osmux) {
911 vty_out(vty, "Cannot use `loop' with `osmux'.%s", VTY_NEWLINE);
912 return CMD_WARNING;
913 }
914 trunk->audio_loop = atoi(argv[0]);
915 return CMD_SUCCESS;
916}
917
918DEFUN(cfg_trunk_sdp_payload_send_ptime,
919 cfg_trunk_sdp_payload_send_ptime_cmd,
920 "sdp audio-payload send-ptime",
921 SDP_STR AUDIO_STR
922 "Send SDP ptime (packet duration) attribute\n")
923{
924 struct mgcp_trunk_config *trunk = vty->index;
925 trunk->audio_send_ptime = 1;
926 return CMD_SUCCESS;
927}
928
929DEFUN(cfg_trunk_no_sdp_payload_send_ptime,
930 cfg_trunk_no_sdp_payload_send_ptime_cmd,
931 "no sdp audio-payload send-ptime",
932 NO_STR SDP_STR AUDIO_STR
933 "Send SDP ptime (packet duration) attribute\n")
934{
935 struct mgcp_trunk_config *trunk = vty->index;
936 trunk->audio_send_ptime = 0;
937 return CMD_SUCCESS;
938}
939
940DEFUN(cfg_trunk_sdp_payload_send_name,
941 cfg_trunk_sdp_payload_send_name_cmd,
942 "sdp audio-payload send-name",
943 SDP_STR AUDIO_STR
944 "Send SDP rtpmap with the audio name\n")
945{
946 struct mgcp_trunk_config *trunk = vty->index;
947 trunk->audio_send_name = 1;
948 return CMD_SUCCESS;
949}
950
951DEFUN(cfg_trunk_no_sdp_payload_send_name,
952 cfg_trunk_no_sdp_payload_send_name_cmd,
953 "no sdp audio-payload send-name",
954 NO_STR SDP_STR AUDIO_STR
955 "Send SDP rtpmap with the audio name\n")
956{
957 struct mgcp_trunk_config *trunk = vty->index;
958 trunk->audio_send_name = 0;
959 return CMD_SUCCESS;
960}
961
962DEFUN(cfg_trunk_omit_rtcp,
963 cfg_trunk_omit_rtcp_cmd,
964 "rtcp-omit",
965 RTCP_OMIT_STR)
966{
967 struct mgcp_trunk_config *trunk = vty->index;
968 trunk->omit_rtcp = 1;
969 return CMD_SUCCESS;
970}
971
972DEFUN(cfg_trunk_no_omit_rtcp,
973 cfg_trunk_no_omit_rtcp_cmd,
974 "no rtcp-omit",
975 NO_STR RTCP_OMIT_STR)
976{
977 struct mgcp_trunk_config *trunk = vty->index;
978 trunk->omit_rtcp = 0;
979 return CMD_SUCCESS;
980}
981
982DEFUN(cfg_trunk_patch_rtp_ssrc,
983 cfg_trunk_patch_rtp_ssrc_cmd,
984 "rtp-patch ssrc",
985 RTP_PATCH_STR
986 "Force a fixed SSRC\n"
987 )
988{
989 struct mgcp_trunk_config *trunk = vty->index;
990 trunk->force_constant_ssrc = 1;
991 return CMD_SUCCESS;
992}
993
994DEFUN(cfg_trunk_no_patch_rtp_ssrc,
995 cfg_trunk_no_patch_rtp_ssrc_cmd,
996 "no rtp-patch ssrc",
997 NO_STR RTP_PATCH_STR
998 "Force a fixed SSRC\n"
999 )
1000{
1001 struct mgcp_trunk_config *trunk = vty->index;
1002 trunk->force_constant_ssrc = 0;
1003 return CMD_SUCCESS;
1004}
1005
1006DEFUN(cfg_trunk_patch_rtp_ts,
1007 cfg_trunk_patch_rtp_ts_cmd,
1008 "rtp-patch timestamp",
1009 RTP_PATCH_STR
1010 "Adjust RTP timestamp\n"
1011 )
1012{
1013 struct mgcp_trunk_config *trunk = vty->index;
1014 trunk->force_aligned_timing = 1;
1015 return CMD_SUCCESS;
1016}
1017
1018DEFUN(cfg_trunk_no_patch_rtp_ts,
1019 cfg_trunk_no_patch_rtp_ts_cmd,
1020 "no rtp-patch timestamp",
1021 NO_STR RTP_PATCH_STR
1022 "Adjust RTP timestamp\n"
1023 )
1024{
1025 struct mgcp_trunk_config *trunk = vty->index;
1026 trunk->force_aligned_timing = 0;
1027 return CMD_SUCCESS;
1028}
1029
1030DEFUN(cfg_trunk_no_patch_rtp,
1031 cfg_trunk_no_patch_rtp_cmd,
1032 "no rtp-patch",
1033 NO_STR RTP_PATCH_STR)
1034{
1035 struct mgcp_trunk_config *trunk = vty->index;
1036 trunk->force_constant_ssrc = 0;
1037 trunk->force_aligned_timing = 0;
1038 return CMD_SUCCESS;
1039}
1040
1041DEFUN(cfg_trunk_rtp_keepalive,
1042 cfg_trunk_rtp_keepalive_cmd,
1043 "rtp keep-alive <1-120>",
1044 RTP_STR RTP_KEEPALIVE_STR
1045 "Keep-alive interval in secs\n"
1046 )
1047{
1048 struct mgcp_trunk_config *trunk = vty->index;
1049 mgcp_trunk_set_keepalive(trunk, atoi(argv[0]));
1050 return CMD_SUCCESS;
1051}
1052
1053DEFUN(cfg_trunk_rtp_keepalive_once,
1054 cfg_trunk_rtp_keepalive_once_cmd,
1055 "rtp keep-alive once",
1056 RTP_STR RTP_KEEPALIVE_STR
1057 "Send dummy packet only once after CRCX/MDCX\n"
1058 )
1059{
1060 struct mgcp_trunk_config *trunk = vty->index;
1061 mgcp_trunk_set_keepalive(trunk, MGCP_KEEPALIVE_ONCE);
1062 return CMD_SUCCESS;
1063}
1064
1065DEFUN(cfg_trunk_no_rtp_keepalive,
1066 cfg_trunk_no_rtp_keepalive_cmd,
1067 "no rtp keep-alive",
1068 NO_STR RTP_STR RTP_KEEPALIVE_STR
1069 )
1070{
1071 struct mgcp_trunk_config *trunk = vty->index;
1072 mgcp_trunk_set_keepalive(trunk, 0);
1073 return CMD_SUCCESS;
1074}
1075
1076DEFUN(cfg_trunk_allow_transcoding,
1077 cfg_trunk_allow_transcoding_cmd,
1078 "allow-transcoding",
1079 "Allow transcoding\n")
1080{
1081 struct mgcp_trunk_config *trunk = vty->index;
1082 trunk->no_audio_transcoding = 0;
1083 return CMD_SUCCESS;
1084}
1085
1086DEFUN(cfg_trunk_no_allow_transcoding,
1087 cfg_trunk_no_allow_transcoding_cmd,
1088 "no allow-transcoding",
1089 NO_STR "Allow transcoding\n")
1090{
1091 struct mgcp_trunk_config *trunk = vty->index;
1092 trunk->no_audio_transcoding = 1;
1093 return CMD_SUCCESS;
1094}
1095
1096DEFUN(loop_endp,
1097 loop_endp_cmd,
1098 "loop-endpoint <0-64> NAME (0|1)",
1099 "Loop a given endpoint\n" "Trunk number\n"
1100 "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n")
1101{
1102 struct mgcp_trunk_config *trunk;
1103 struct mgcp_endpoint *endp;
1104
1105 trunk = find_trunk(g_cfg, atoi(argv[0]));
1106 if (!trunk) {
1107 vty_out(vty, "%%Trunk %d not found in the config.%s",
1108 atoi(argv[0]), VTY_NEWLINE);
1109 return CMD_WARNING;
1110 }
1111
1112 if (!trunk->endpoints) {
1113 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1114 trunk->trunk_nr, VTY_NEWLINE);
1115 return CMD_WARNING;
1116 }
1117
1118 int endp_no = strtoul(argv[1], NULL, 16);
1119 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1120 vty_out(vty, "Loopback number %s/%d is invalid.%s",
1121 argv[1], endp_no, VTY_NEWLINE);
1122 return CMD_WARNING;
1123 }
1124
1125
1126 endp = &trunk->endpoints[endp_no];
1127 int loop = atoi(argv[2]);
1128
1129 if (loop)
1130 endp->conn_mode = MGCP_CONN_LOOPBACK;
1131 else
1132 endp->conn_mode = endp->orig_mode;
1133
1134 /* Handle it like a MDCX, switch on SSRC patching if enabled */
1135 mgcp_rtp_end_config(endp, 1, &endp->bts_end);
1136 mgcp_rtp_end_config(endp, 1, &endp->net_end);
1137
1138 return CMD_SUCCESS;
1139}
1140
1141DEFUN(tap_call,
1142 tap_call_cmd,
1143 "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
1144 "Forward data on endpoint to a different system\n" "Trunk number\n"
1145 "The endpoint in hex\n"
1146 "Forward the data coming from the bts\n"
1147 "Forward the data coming from the bts leaving to the network\n"
1148 "Forward the data coming from the net\n"
1149 "Forward the data coming from the net leaving to the bts\n"
1150 "destination IP of the data\n" "destination port\n")
1151{
1152 struct mgcp_rtp_tap *tap;
1153 struct mgcp_trunk_config *trunk;
1154 struct mgcp_endpoint *endp;
1155 int port = 0;
1156
1157 trunk = find_trunk(g_cfg, atoi(argv[0]));
1158 if (!trunk) {
1159 vty_out(vty, "%%Trunk %d not found in the config.%s",
1160 atoi(argv[0]), VTY_NEWLINE);
1161 return CMD_WARNING;
1162 }
1163
1164 if (!trunk->endpoints) {
1165 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1166 trunk->trunk_nr, VTY_NEWLINE);
1167 return CMD_WARNING;
1168 }
1169
1170 int endp_no = strtoul(argv[1], NULL, 16);
1171 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1172 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
1173 argv[1], endp_no, VTY_NEWLINE);
1174 return CMD_WARNING;
1175 }
1176
1177 endp = &trunk->endpoints[endp_no];
1178
1179 if (strcmp(argv[2], "bts-in") == 0) {
1180 port = MGCP_TAP_BTS_IN;
1181 } else if (strcmp(argv[2], "bts-out") == 0) {
1182 port = MGCP_TAP_BTS_OUT;
1183 } else if (strcmp(argv[2], "net-in") == 0) {
1184 port = MGCP_TAP_NET_IN;
1185 } else if (strcmp(argv[2], "net-out") == 0) {
1186 port = MGCP_TAP_NET_OUT;
1187 } else {
1188 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
1189 return CMD_WARNING;
1190 }
1191
1192 tap = &endp->taps[port];
1193 memset(&tap->forward, 0, sizeof(tap->forward));
1194 inet_aton(argv[3], &tap->forward.sin_addr);
1195 tap->forward.sin_port = htons(atoi(argv[4]));
1196 tap->enabled = 1;
1197 return CMD_SUCCESS;
1198}
1199
1200DEFUN(free_endp, free_endp_cmd,
1201 "free-endpoint <0-64> NUMBER",
1202 "Free the given endpoint\n" "Trunk number\n"
1203 "Endpoint number in hex.\n")
1204{
1205 struct mgcp_trunk_config *trunk;
1206 struct mgcp_endpoint *endp;
1207
1208 trunk = find_trunk(g_cfg, atoi(argv[0]));
1209 if (!trunk) {
1210 vty_out(vty, "%%Trunk %d not found in the config.%s",
1211 atoi(argv[0]), VTY_NEWLINE);
1212 return CMD_WARNING;
1213 }
1214
1215 if (!trunk->endpoints) {
1216 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1217 trunk->trunk_nr, VTY_NEWLINE);
1218 return CMD_WARNING;
1219 }
1220
1221 int endp_no = strtoul(argv[1], NULL, 16);
1222 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1223 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
1224 argv[1], endp_no, VTY_NEWLINE);
1225 return CMD_WARNING;
1226 }
1227
1228 endp = &trunk->endpoints[endp_no];
1229 mgcp_release_endp(endp);
1230 return CMD_SUCCESS;
1231}
1232
1233DEFUN(reset_endp, reset_endp_cmd,
1234 "reset-endpoint <0-64> NUMBER",
1235 "Reset the given endpoint\n" "Trunk number\n"
1236 "Endpoint number in hex.\n")
1237{
1238 struct mgcp_trunk_config *trunk;
1239 struct mgcp_endpoint *endp;
1240 int endp_no, rc;
1241
1242 trunk = find_trunk(g_cfg, atoi(argv[0]));
1243 if (!trunk) {
1244 vty_out(vty, "%%Trunk %d not found in the config.%s",
1245 atoi(argv[0]), VTY_NEWLINE);
1246 return CMD_WARNING;
1247 }
1248
1249 if (!trunk->endpoints) {
1250 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
1251 trunk->trunk_nr, VTY_NEWLINE);
1252 return CMD_WARNING;
1253 }
1254
1255 endp_no = strtoul(argv[1], NULL, 16);
1256 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
1257 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
1258 argv[1], endp_no, VTY_NEWLINE);
1259 return CMD_WARNING;
1260 }
1261
1262 endp = &trunk->endpoints[endp_no];
1263 rc = mgcp_send_reset_ep(endp, ENDPOINT_NUMBER(endp));
1264 if (rc < 0) {
1265 vty_out(vty, "Error %d sending reset.%s", rc, VTY_NEWLINE);
1266 return CMD_WARNING;
1267 }
1268 return CMD_SUCCESS;
1269}
1270
1271DEFUN(reset_all_endp, reset_all_endp_cmd,
1272 "reset-all-endpoints",
1273 "Reset all endpoints\n")
1274{
1275 int rc;
1276
1277 rc = mgcp_send_reset_all(g_cfg);
1278 if (rc < 0) {
1279 vty_out(vty, "Error %d during endpoint reset.%s",
1280 rc, VTY_NEWLINE);
1281 return CMD_WARNING;
1282 }
1283 return CMD_SUCCESS;
1284}
1285
1286#define OSMUX_STR "RTP multiplexing\n"
1287DEFUN(cfg_mgcp_osmux,
1288 cfg_mgcp_osmux_cmd,
1289 "osmux (on|off|only)",
1290 OSMUX_STR "Enable OSMUX\n" "Disable OSMUX\n" "Only use OSMUX\n")
1291{
1292 if (strcmp(argv[0], "off") == 0) {
1293 g_cfg->osmux = OSMUX_USAGE_OFF;
1294 return CMD_SUCCESS;
1295 }
1296
1297 if (strcmp(argv[0], "on") == 0)
1298 g_cfg->osmux = OSMUX_USAGE_ON;
1299 else if (strcmp(argv[0], "only") == 0)
1300 g_cfg->osmux = OSMUX_USAGE_ONLY;
1301
1302 if (g_cfg->trunk.audio_loop) {
1303 vty_out(vty, "Cannot use `loop' with `osmux'.%s",
1304 VTY_NEWLINE);
1305 return CMD_WARNING;
1306 }
1307
1308 return CMD_SUCCESS;
1309}
1310
1311DEFUN(cfg_mgcp_osmux_ip,
1312 cfg_mgcp_osmux_ip_cmd,
1313 "osmux bind-ip A.B.C.D",
1314 OSMUX_STR IP_STR "IPv4 Address to bind to\n")
1315{
1316 osmo_talloc_replace_string(g_cfg, &g_cfg->osmux_addr, argv[0]);
1317 return CMD_SUCCESS;
1318}
1319
1320DEFUN(cfg_mgcp_osmux_batch_factor,
1321 cfg_mgcp_osmux_batch_factor_cmd,
1322 "osmux batch-factor <1-8>",
1323 OSMUX_STR "Batching factor\n" "Number of messages in the batch\n")
1324{
1325 g_cfg->osmux_batch = atoi(argv[0]);
1326 return CMD_SUCCESS;
1327}
1328
1329DEFUN(cfg_mgcp_osmux_batch_size,
1330 cfg_mgcp_osmux_batch_size_cmd,
1331 "osmux batch-size <1-65535>",
1332 OSMUX_STR "batch size\n" "Batch size in bytes\n")
1333{
1334 g_cfg->osmux_batch_size = atoi(argv[0]);
1335 return CMD_SUCCESS;
1336}
1337
1338DEFUN(cfg_mgcp_osmux_port,
1339 cfg_mgcp_osmux_port_cmd,
1340 "osmux port <1-65535>",
1341 OSMUX_STR "port\n" "UDP port\n")
1342{
1343 g_cfg->osmux_port = atoi(argv[0]);
1344 return CMD_SUCCESS;
1345}
1346
1347DEFUN(cfg_mgcp_osmux_dummy,
1348 cfg_mgcp_osmux_dummy_cmd,
1349 "osmux dummy (on|off)",
1350 OSMUX_STR "Dummy padding\n" "Enable dummy padding\n" "Disable dummy padding\n")
1351{
1352 if (strcmp(argv[0], "on") == 0)
1353 g_cfg->osmux_dummy = 1;
1354 else if (strcmp(argv[0], "off") == 0)
1355 g_cfg->osmux_dummy = 0;
1356
1357 return CMD_SUCCESS;
1358}
1359
Pau Espin Pedrolba61f682018-05-16 14:03:38 +02001360#define DEJITTER_STR "Uplink Jitter Buffer"
1361DEFUN(cfg_mgcp_bts_use_jibuf,
1362 cfg_mgcp_bts_use_jibuf_cmd,
1363 "bts-jitter-buffer",
1364 DEJITTER_STR "\n")
1365{
1366 g_cfg->bts_use_jibuf = true;
1367 return CMD_SUCCESS;
1368}
1369
1370DEFUN(cfg_mgcp_no_bts_use_jibuf,
1371 cfg_mgcp_no_bts_use_jibuf_cmd,
1372 "no bts-jitter-buffer",
1373 NO_STR DEJITTER_STR "\n")
1374{
1375 g_cfg->bts_use_jibuf = false;
1376 return CMD_SUCCESS;
1377}
1378
1379DEFUN(cfg_mgcp_bts_jitter_delay_min,
1380 cfg_mgcp_bts_jitter_delay_min_cmd,
1381 "bts-jitter-buffer-delay-min <1-65535>",
1382 DEJITTER_STR " Minimum Delay in ms\n" "Minimum Delay in ms\n")
1383{
1384 g_cfg->bts_jitter_delay_min = atoi(argv[0]);
1385 if (!g_cfg->bts_jitter_delay_min) {
1386 vty_out(vty, "bts-jitter-buffer-delay-min cannot be zero.%s", VTY_NEWLINE);
1387 return CMD_WARNING;
1388 }
1389 if (g_cfg->bts_jitter_delay_min && g_cfg->bts_jitter_delay_max &&
1390 g_cfg->bts_jitter_delay_min > g_cfg->bts_jitter_delay_max) {
1391 vty_out(vty, "bts-jitter-buffer-delay-min cannot be bigger than " \
1392 "bts-jitter-buffer-delay-max.%s", VTY_NEWLINE);
1393 return CMD_WARNING;
1394 }
1395 return CMD_SUCCESS;
1396}
1397
1398DEFUN(cfg_mgcp_bts_jitter_delay_max,
1399 cfg_mgcp_bts_jitter_delay_max_cmd,
1400 "bts-jitter-buffer-delay-max <1-65535>",
1401 DEJITTER_STR " Maximum Delay in ms\n" "Maximum Delay in ms\n")
1402{
1403 g_cfg->bts_jitter_delay_max = atoi(argv[0]);
1404 if (!g_cfg->bts_jitter_delay_max) {
1405 vty_out(vty, "bts-jitter-buffer-delay-max cannot be zero.%s", VTY_NEWLINE);
1406 return CMD_WARNING;
1407 }
1408 if (g_cfg->bts_jitter_delay_min && g_cfg->bts_jitter_delay_max &&
1409 g_cfg->bts_jitter_delay_min > g_cfg->bts_jitter_delay_max) {
1410 vty_out(vty, "bts-jitter-buffer-delay-max cannot be smaller than " \
1411 "bts-jitter-buffer-delay-min.%s", VTY_NEWLINE);
1412 return CMD_WARNING;
1413 }
1414 return CMD_SUCCESS;
1415}
1416
Neels Hofmeyre9920f22017-07-10 15:07:22 +02001417int mgcp_vty_init(void)
1418{
1419 install_element_ve(&show_mgcp_cmd);
1420 install_element(ENABLE_NODE, &loop_endp_cmd);
1421 install_element(ENABLE_NODE, &tap_call_cmd);
1422 install_element(ENABLE_NODE, &free_endp_cmd);
1423 install_element(ENABLE_NODE, &reset_endp_cmd);
1424 install_element(ENABLE_NODE, &reset_all_endp_cmd);
1425
1426 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
1427 install_node(&mgcp_node, config_write_mgcp);
1428
Neels Hofmeyre9920f22017-07-10 15:07:22 +02001429 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
1430 install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
1431 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
1432 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
1433 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
1434 install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd);
1435 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
1436 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
1437 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
1438 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_bind_ip_cmd);
1439 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_bts_bind_ip_cmd);
1440 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
1441 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_bind_ip_cmd);
1442 install_element(MGCP_NODE, &cfg_mgcp_rtp_no_net_bind_ip_cmd);
1443 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
1444 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
1445 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
1446 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
1447 install_element(MGCP_NODE, &cfg_mgcp_rtp_force_ptime_cmd);
1448 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_force_ptime_cmd);
1449 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_cmd);
1450 install_element(MGCP_NODE, &cfg_mgcp_rtp_keepalive_once_cmd);
1451 install_element(MGCP_NODE, &cfg_mgcp_no_rtp_keepalive_cmd);
1452 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
1453 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd_old);
1454 install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
1455 install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
1456 install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
1457 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
1458 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
1459 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd_old);
1460 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd_old);
1461 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
1462 install_element(MGCP_NODE, &cfg_mgcp_force_realloc_cmd);
1463 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
1464 install_element(MGCP_NODE, &cfg_mgcp_omit_rtcp_cmd);
1465 install_element(MGCP_NODE, &cfg_mgcp_no_omit_rtcp_cmd);
1466 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ssrc_cmd);
1467 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ssrc_cmd);
1468 install_element(MGCP_NODE, &cfg_mgcp_patch_rtp_ts_cmd);
1469 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_ts_cmd);
1470 install_element(MGCP_NODE, &cfg_mgcp_no_patch_rtp_cmd);
1471 install_element(MGCP_NODE, &cfg_mgcp_sdp_fmtp_extra_cmd);
1472 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_ptime_cmd);
1473 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_ptime_cmd);
1474 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_send_name_cmd);
1475 install_element(MGCP_NODE, &cfg_mgcp_no_sdp_payload_send_name_cmd);
1476 install_element(MGCP_NODE, &cfg_mgcp_osmux_cmd);
1477 install_element(MGCP_NODE, &cfg_mgcp_osmux_ip_cmd);
1478 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_factor_cmd);
1479 install_element(MGCP_NODE, &cfg_mgcp_osmux_batch_size_cmd);
1480 install_element(MGCP_NODE, &cfg_mgcp_osmux_port_cmd);
1481 install_element(MGCP_NODE, &cfg_mgcp_osmux_dummy_cmd);
1482 install_element(MGCP_NODE, &cfg_mgcp_allow_transcoding_cmd);
1483 install_element(MGCP_NODE, &cfg_mgcp_no_allow_transcoding_cmd);
Pau Espin Pedrolba61f682018-05-16 14:03:38 +02001484 install_element(MGCP_NODE, &cfg_mgcp_bts_use_jibuf_cmd);
1485 install_element(MGCP_NODE, &cfg_mgcp_no_bts_use_jibuf_cmd);
1486 install_element(MGCP_NODE, &cfg_mgcp_bts_jitter_delay_min_cmd);
1487 install_element(MGCP_NODE, &cfg_mgcp_bts_jitter_delay_max_cmd);
Neels Hofmeyre9920f22017-07-10 15:07:22 +02001488
1489
1490 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
1491 install_node(&trunk_node, config_write_trunk);
Neels Hofmeyre9920f22017-07-10 15:07:22 +02001492 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_cmd);
1493 install_element(TRUNK_NODE, &cfg_trunk_rtp_keepalive_once_cmd);
1494 install_element(TRUNK_NODE, &cfg_trunk_no_rtp_keepalive_cmd);
1495 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
1496 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
1497 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd_old);
1498 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd_old);
1499 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
1500 install_element(TRUNK_NODE, &cfg_trunk_omit_rtcp_cmd);
1501 install_element(TRUNK_NODE, &cfg_trunk_no_omit_rtcp_cmd);
1502 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ssrc_cmd);
1503 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ssrc_cmd);
1504 install_element(TRUNK_NODE, &cfg_trunk_patch_rtp_ts_cmd);
1505 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_ts_cmd);
1506 install_element(TRUNK_NODE, &cfg_trunk_no_patch_rtp_cmd);
1507 install_element(TRUNK_NODE, &cfg_trunk_sdp_fmtp_extra_cmd);
1508 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_ptime_cmd);
1509 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_ptime_cmd);
1510 install_element(TRUNK_NODE, &cfg_trunk_sdp_payload_send_name_cmd);
1511 install_element(TRUNK_NODE, &cfg_trunk_no_sdp_payload_send_name_cmd);
1512 install_element(TRUNK_NODE, &cfg_trunk_allow_transcoding_cmd);
1513 install_element(TRUNK_NODE, &cfg_trunk_no_allow_transcoding_cmd);
1514
1515 return 0;
1516}
1517
1518static int allocate_trunk(struct mgcp_trunk_config *trunk)
1519{
1520 int i;
1521 struct mgcp_config *cfg = trunk->cfg;
1522
1523 if (mgcp_endpoints_allocate(trunk) != 0) {
1524 LOGP(DLMGCP, LOGL_ERROR,
1525 "Failed to allocate %d endpoints on trunk %d.\n",
1526 trunk->number_endpoints, trunk->trunk_nr);
1527 return -1;
1528 }
1529
1530 /* early bind */
1531 for (i = 1; i < trunk->number_endpoints; ++i) {
1532 struct mgcp_endpoint *endp = &trunk->endpoints[i];
1533
1534 if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
1535 cfg->last_bts_port += 2;
1536 if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) {
1537 LOGP(DLMGCP, LOGL_FATAL,
1538 "Failed to bind: %d\n", cfg->last_bts_port);
1539 return -1;
1540 }
1541 endp->bts_end.local_alloc = PORT_ALLOC_STATIC;
1542 }
1543
1544 if (cfg->net_ports.mode == PORT_ALLOC_STATIC) {
1545 cfg->last_net_port += 2;
1546 if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) {
1547 LOGP(DLMGCP, LOGL_FATAL,
1548 "Failed to bind: %d\n", cfg->last_net_port);
1549 return -1;
1550 }
1551 endp->net_end.local_alloc = PORT_ALLOC_STATIC;
1552 }
1553
1554 if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL &&
1555 cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
1556 int rtp_port;
1557
1558 /* network side */
1559 rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
1560 cfg->transcoder_ports.base_port);
1561 if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
1562 LOGP(DLMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
1563 return -1;
1564 }
1565 endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
1566
1567 /* bts side */
1568 rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
1569 cfg->transcoder_ports.base_port);
1570 if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
1571 LOGP(DLMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
1572 return -1;
1573 }
1574 endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
1575 }
1576 }
1577
1578 return 0;
1579}
1580
1581int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg,
1582 enum mgcp_role role)
1583{
1584 int rc;
1585 struct mgcp_trunk_config *trunk;
1586
1587 cfg->osmux_port = OSMUX_PORT;
1588 cfg->osmux_batch = 4;
1589 cfg->osmux_batch_size = OSMUX_BATCH_DEFAULT_MAX;
1590
1591 g_cfg = cfg;
1592 rc = vty_read_config_file(config_file, NULL);
1593 if (rc < 0) {
1594 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
1595 return rc;
1596 }
1597
1598
1599 if (!g_cfg->bts_ip)
1600 fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
1601
1602 if (!g_cfg->source_addr) {
1603 fprintf(stderr, "You need to specify a bind address.\n");
1604 return -1;
1605 }
1606
1607 /* initialize the last ports */
1608 g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
1609 g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
1610
1611 if (allocate_trunk(&g_cfg->trunk) != 0) {
1612 LOGP(DLMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
1613 return -1;
1614 }
1615
1616 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
1617 if (allocate_trunk(trunk) != 0) {
1618 LOGP(DLMGCP, LOGL_ERROR,
1619 "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
1620 return -1;
1621 }
1622 }
1623 cfg->role = role;
1624
1625 return 0;
1626}
1627