blob: c299a98ccf0899df564d477b47985698693a1559 [file] [log] [blame]
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +01001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The protocol implementation */
3
4/*
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +01005 * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2011 by On-Waves
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +01007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +010010 * 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
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010012 * (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
Harald Welte0e3e88e2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010018 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010019 * 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/>.
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010021 *
22 */
23
24#include <sys/types.h>
25
Holger Hans Peter Freytherf41fb1f2010-02-26 20:16:37 +010026#include <osmocore/talloc.h>
27
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010028#include <openbsc/debug.h>
29#include <openbsc/mgcp.h>
30#include <openbsc/mgcp_internal.h>
Harald Welte58ed1cb2010-05-14 18:59:17 +020031#include <openbsc/vty.h>
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010032
Harald Weltebd9591f2010-05-19 19:45:32 +020033#include <osmocom/vty/command.h>
34#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010035
Holger Hans Peter Freythere8d13712010-04-16 16:59:48 +020036#include <string.h>
37
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010038static struct mgcp_config *g_cfg = NULL;
39
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +010040static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +010041{
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +010042 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +010043
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +010044 if (nr == 0)
45 trunk = &cfg->trunk;
46 else
47 trunk = mgcp_trunk_num(cfg, nr);
48
49 return trunk;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +010050}
51
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010052/*
53 * vty code for mgcp below
54 */
55struct cmd_node mgcp_node = {
56 MGCP_NODE,
57 "%s(mgcp)#",
58 1,
59};
60
Holger Hans Peter Freyther06bfe792011-02-28 12:11:02 +010061struct cmd_node trunk_node = {
62 TRUNK_NODE,
63 "%s(trunk)#",
64 1,
65};
66
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010067static int config_write_mgcp(struct vty *vty)
68{
69 vty_out(vty, "mgcp%s", VTY_NEWLINE);
70 if (g_cfg->local_ip)
Holger Hans Peter Freythere8d13712010-04-16 16:59:48 +020071 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)
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010073 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);
Holger Hans Peter Freyther2ea91182010-08-05 07:10:56 +080076
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);
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +080079 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
Holger Hans Peter Freyther2ea91182010-08-05 07:10:56 +080083 if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
84 vty_out(vty, " rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE);
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +080085 else
86 vty_out(vty, " rtp net-range %u %u%s",
87 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
88
Holger Hans Peter Freyther3140c4f2010-07-27 20:34:45 +080089 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +010090 if (g_cfg->trunk.audio_payload != -1)
91 vty_out(vty, " sdp audio payload number %d%s",
92 g_cfg->trunk.audio_payload, VTY_NEWLINE);
93 if (g_cfg->trunk.audio_name)
94 vty_out(vty, " sdp audio payload name %s%s",
95 g_cfg->trunk.audio_name, VTY_NEWLINE);
96 vty_out(vty, " loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
97 vty_out(vty, " number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
Holger Hans Peter Freyther19ff6792010-03-31 11:46:41 +020098 if (g_cfg->call_agent_addr)
Holger Hans Peter Freythere8d13712010-04-16 16:59:48 +020099 vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
Holger Hans Peter Freythercab38342010-09-17 03:58:52 +0800100 if (g_cfg->transcoder_ip)
101 vty_out(vty, " transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100102
Holger Hans Peter Freyther39f2f6d2010-09-17 23:35:53 +0800103 if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC)
104 vty_out(vty, " rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE);
105 else
106 vty_out(vty, " rtp transcoder-range %u %u%s",
107 g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE);
Holger Hans Peter Freytherd582b202010-09-19 04:21:39 +0800108 vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
Holger Hans Peter Freyther39f2f6d2010-09-17 23:35:53 +0800109
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100110 return CMD_SUCCESS;
111}
112
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100113static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg)
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100114{
115 int i;
116
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100117 vty_out(vty, "%s trunk nr %d with %d endpoints:%s",
118 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
119 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
120
Holger Hans Peter Freyther088bc282011-02-28 12:27:47 +0100121 if (!cfg->endpoints) {
122 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
123 return;
124 }
125
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100126 for (i = 1; i < cfg->number_endpoints; ++i) {
127 struct mgcp_endpoint *endp = &cfg->endpoints[i];
128 vty_out(vty,
129 " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s "
130 "traffic received bts: %u/%u remote: %u/%u transcoder: %u/%u%s",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100131 i, endp->ci,
Holger Hans Peter Freytherfab76aa2010-08-05 01:34:51 +0800132 ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
133 ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port),
134 inet_ntoa(endp->bts_end.addr),
135 endp->bts_end.packets, endp->bts_state.lost_no,
136 endp->net_end.packets, endp->net_state.lost_no,
Holger Hans Peter Freytherc983f832010-11-01 21:04:54 +0100137 endp->trans_net.packets, endp->trans_bts.packets,
Holger Hans Peter Freyther6de5b112010-04-07 09:37:17 +0200138 VTY_NEWLINE);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100139 }
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100140}
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100141
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100142DEFUN(show_mcgp, show_mgcp_cmd, "show mgcp",
143 SHOW_STR "Display information about the MGCP Media Gateway")
144{
Holger Hans Peter Freyther088bc282011-02-28 12:27:47 +0100145 struct mgcp_trunk_config *trunk;
146
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100147 dump_trunk(vty, &g_cfg->trunk);
Holger Hans Peter Freyther088bc282011-02-28 12:27:47 +0100148
149 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
150 dump_trunk(vty, trunk);
151
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100152 return CMD_SUCCESS;
153}
154
155DEFUN(cfg_mgcp,
156 cfg_mgcp_cmd,
157 "mgcp",
158 "Configure the MGCP")
159{
160 vty->node = MGCP_NODE;
161 return CMD_SUCCESS;
162}
163
164DEFUN(cfg_mgcp_local_ip,
165 cfg_mgcp_local_ip_cmd,
Holger Hans Peter Freyther5c9a6452010-05-14 02:27:50 +0800166 "local ip A.B.C.D",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100167 "Set the IP to be used in SDP records")
168{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200169 bsc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100170 return CMD_SUCCESS;
171}
172
173DEFUN(cfg_mgcp_bts_ip,
174 cfg_mgcp_bts_ip_cmd,
Holger Hans Peter Freyther5c9a6452010-05-14 02:27:50 +0800175 "bts ip A.B.C.D",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100176 "Set the IP of the BTS for RTP forwarding")
177{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200178 bsc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100179 inet_aton(g_cfg->bts_ip, &g_cfg->bts_in);
180 return CMD_SUCCESS;
181}
182
183DEFUN(cfg_mgcp_bind_ip,
184 cfg_mgcp_bind_ip_cmd,
Holger Hans Peter Freyther5c9a6452010-05-14 02:27:50 +0800185 "bind ip A.B.C.D",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100186 "Bind the MGCP to this local addr")
187{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200188 bsc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100189 return CMD_SUCCESS;
190}
191
192DEFUN(cfg_mgcp_bind_port,
193 cfg_mgcp_bind_port_cmd,
194 "bind port <0-65534>",
195 "Bind the MGCP to this port")
196{
197 unsigned int port = atoi(argv[0]);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100198 g_cfg->source_port = port;
199 return CMD_SUCCESS;
200}
201
202DEFUN(cfg_mgcp_bind_early,
203 cfg_mgcp_bind_early_cmd,
204 "bind early (0|1)",
205 "Bind all RTP ports early")
206{
Holger Hans Peter Freyther7140dae2010-08-05 03:22:24 +0800207 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
208 return CMD_WARNING;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100209}
210
Holger Hans Peter Freytherd3b7d772010-09-17 23:34:36 +0800211static void parse_base(struct mgcp_port_range *range, const char **argv)
212{
213 unsigned int port = atoi(argv[0]);
214 range->mode = PORT_ALLOC_STATIC;
215 range->base_port = port;
216}
217
218static void parse_range(struct mgcp_port_range *range, const char **argv)
219{
220 range->mode = PORT_ALLOC_DYNAMIC;
221 range->range_start = atoi(argv[0]);
222 range->range_end = atoi(argv[1]);
223 range->last_port = g_cfg->bts_ports.range_start;
224}
225
226
Holger Hans Peter Freytheree4657c2010-08-05 03:46:07 +0800227DEFUN(cfg_mgcp_rtp_bts_base_port,
228 cfg_mgcp_rtp_bts_base_port_cmd,
229 "rtp bts-base <0-65534>",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100230 "Base port to use")
231{
Holger Hans Peter Freytherd3b7d772010-09-17 23:34:36 +0800232 parse_base(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100233 return CMD_SUCCESS;
234}
235
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +0800236DEFUN(cfg_mgcp_rtp_bts_range,
237 cfg_mgcp_rtp_bts_range_cmd,
238 "rtp bts-range <0-65534> <0-65534>",
239 "Range of ports to allocate for endpoints\n"
240 "Start of the range of ports\n" "End of the range of ports\n")
241{
Holger Hans Peter Freytherd3b7d772010-09-17 23:34:36 +0800242 parse_range(&g_cfg->bts_ports, argv);
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +0800243 return CMD_SUCCESS;
244}
245
246DEFUN(cfg_mgcp_rtp_net_range,
247 cfg_mgcp_rtp_net_range_cmd,
248 "rtp net-range <0-65534> <0-65534>",
249 "Range of ports to allocate for endpoints\n"
250 "Start of the range of ports\n" "End of the range of ports\n")
251{
Holger Hans Peter Freytherd3b7d772010-09-17 23:34:36 +0800252 parse_range(&g_cfg->net_ports, argv);
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +0800253 return CMD_SUCCESS;
254}
255
Holger Hans Peter Freyther81938e92010-08-05 04:10:21 +0800256DEFUN(cfg_mgcp_rtp_net_base_port,
257 cfg_mgcp_rtp_net_base_port_cmd,
258 "rtp net-base <0-65534>",
259 "Base port to use for network port\n" "Port\n")
260{
Holger Hans Peter Freytherd3b7d772010-09-17 23:34:36 +0800261 parse_base(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther81938e92010-08-05 04:10:21 +0800262 return CMD_SUCCESS;
263}
264
Holger Hans Peter Freytheree4657c2010-08-05 03:46:07 +0800265ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd,
266 "rtp base <0-65534>", "Base port to use")
267
Holger Hans Peter Freyther39f2f6d2010-09-17 23:35:53 +0800268DEFUN(cfg_mgcp_rtp_transcoder_range,
269 cfg_mgcp_rtp_transcoder_range_cmd,
270 "rtp transcoder-range <0-65534> <0-65534>",
271 "Range of ports to allocate for the transcoder\n"
272 "Start of the range of ports\n" "End of the range of ports\n")
273{
274 parse_range(&g_cfg->transcoder_ports, argv);
275 return CMD_SUCCESS;
276}
277
278DEFUN(cfg_mgcp_rtp_transcoder_base,
279 cfg_mgcp_rtp_transcoder_base_cmd,
280 "rtp transcoder-base <0-65534>",
281 "Base port for the transcoder range\n" "Port\n")
282{
283 parse_base(&g_cfg->transcoder_ports, argv);
284 return CMD_SUCCESS;
285}
286
Holger Hans Peter Freyther3140c4f2010-07-27 20:34:45 +0800287DEFUN(cfg_mgcp_rtp_ip_dscp,
288 cfg_mgcp_rtp_ip_dscp_cmd,
289 "rtp ip-dscp <0-255>",
290 "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
Holger Hans Peter Freyther489d0a62010-05-31 10:22:00 +0800291{
Holger Hans Peter Freyther3140c4f2010-07-27 20:34:45 +0800292 int dscp = atoi(argv[0]);
293 g_cfg->endp_dscp = dscp;
Holger Hans Peter Freyther489d0a62010-05-31 10:22:00 +0800294 return CMD_SUCCESS;
295}
296
Holger Hans Peter Freyther3140c4f2010-07-27 20:34:45 +0800297ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
298 "rtp ip-tos <0-255>",
299 "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
300
301
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100302DEFUN(cfg_mgcp_sdp_payload_number,
303 cfg_mgcp_sdp_payload_number_cmd,
304 "sdp audio payload number <1-255>",
305 "Set the audio codec to use")
306{
307 unsigned int payload = atoi(argv[0]);
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +0100308 g_cfg->trunk.audio_payload = payload;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100309 return CMD_SUCCESS;
310}
311
312DEFUN(cfg_mgcp_sdp_payload_name,
313 cfg_mgcp_sdp_payload_name_cmd,
314 "sdp audio payload name NAME",
315 "Set the audio name to use")
316{
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +0100317 bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100318 return CMD_SUCCESS;
319}
320
321DEFUN(cfg_mgcp_loop,
322 cfg_mgcp_loop_cmd,
323 "loop (0|1)",
324 "Loop the audio")
325{
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +0100326 g_cfg->trunk.audio_loop = atoi(argv[0]);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100327 return CMD_SUCCESS;
328}
329
330DEFUN(cfg_mgcp_number_endp,
331 cfg_mgcp_number_endp_cmd,
332 "number endpoints <0-65534>",
333 "The number of endpoints to allocate. This is not dynamic.")
334{
335 /* + 1 as we start counting at one */
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +0100336 g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100337 return CMD_SUCCESS;
338}
339
Holger Hans Peter Freyther19ff6792010-03-31 11:46:41 +0200340DEFUN(cfg_mgcp_agent_addr,
341 cfg_mgcp_agent_addr_cmd,
342 "call agent ip IP",
343 "Set the address of the call agent.")
344{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200345 bsc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
Holger Hans Peter Freyther19ff6792010-03-31 11:46:41 +0200346 return CMD_SUCCESS;
347}
348
Holger Hans Peter Freythercab38342010-09-17 03:58:52 +0800349DEFUN(cfg_mgcp_transcoder,
350 cfg_mgcp_transcoder_cmd,
351 "transcoder-mgw A.B.C.D",
352 "Use a MGW to detranscoder RTP\n"
353 "The IP address of the MGW")
354{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200355 bsc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
Holger Hans Peter Freythercab38342010-09-17 03:58:52 +0800356 inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in);
357
358 return CMD_SUCCESS;
359}
360
Holger Hans Peter Freythered1a5a52010-11-01 20:06:45 +0100361DEFUN(cfg_mgcp_no_transcoder,
362 cfg_mgcp_no_transcoder_cmd,
363 NO_STR "transcoder-mgw",
364 "Disable the transcoding\n")
365{
366 if (g_cfg->transcoder_ip) {
367 LOGP(DMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n");
368 talloc_free(g_cfg->transcoder_ip);
369 g_cfg->transcoder_ip = NULL;
370 }
371
372 return CMD_SUCCESS;
373}
374
Holger Hans Peter Freytherd582b202010-09-19 04:21:39 +0800375DEFUN(cfg_mgcp_transcoder_remote_base,
376 cfg_mgcp_transcoder_remote_base_cmd,
377 "transcoder-remote-base <0-65534>",
378 "Set the base port for the transcoder\n" "The RTP base port on the transcoder")
379{
380 g_cfg->transcoder_remote_base = atoi(argv[0]);
381 return CMD_SUCCESS;
382}
383
Holger Hans Peter Freyther06bfe792011-02-28 12:11:02 +0100384DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
385 "trunk <1-64>",
386 "Configure a SS7 trunk\n" "Trunk Nr\n")
387{
388 struct mgcp_trunk_config *trunk;
389 int index = atoi(argv[0]);
390
391 trunk = mgcp_trunk_num(g_cfg, index);
392 if (!trunk)
393 trunk = mgcp_trunk_alloc(g_cfg, index);
394
395 if (!trunk) {
396 vty_out(vty, "%%Unable to allocate trunk %u.%s",
397 index, VTY_NEWLINE);
398 return CMD_WARNING;
399 }
400
401 vty->node = TRUNK_NODE;
402 vty->index = trunk;
403 return CMD_SUCCESS;
404}
405
406static int config_write_trunk(struct vty *vty)
407{
408 struct mgcp_trunk_config *trunk;
409
410 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
411 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
412 vty_out(vty, " sdp audio payload number %d%s",
413 trunk->audio_payload, VTY_NEWLINE);
414 vty_out(vty, " sdp audio payload name %s%s",
415 trunk->audio_name, VTY_NEWLINE);
416 vty_out(vty, " loop %d%s",
417 trunk->audio_loop, VTY_NEWLINE);
418 }
419
420 return CMD_SUCCESS;
421}
422
423DEFUN(cfg_trunk_payload_number,
424 cfg_trunk_payload_number_cmd,
425 "sdp audio payload number <1-255>",
426 "SDP related\n" "Audio\n" "Payload\n" "Payload Number\n")
427{
428 struct mgcp_trunk_config *trunk = vty->index;
429 unsigned int payload = atoi(argv[0]);
430
431 trunk->audio_payload = payload;
432 return CMD_SUCCESS;
433}
434
435DEFUN(cfg_trunk_payload_name,
436 cfg_trunk_payload_name_cmd,
437 "sdp audio payload name NAME",
438 "SDP related\n" "Audio\n" "Payload\n" "Payload Name\n")
439{
440 struct mgcp_trunk_config *trunk = vty->index;
441
442 bsc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
443 return CMD_SUCCESS;
444}
445
446DEFUN(cfg_trunk_loop,
447 cfg_trunk_loop_cmd,
448 "loop (0|1)",
449 "Loop the audio")
450{
451 struct mgcp_trunk_config *trunk = vty->index;
452
453 trunk->audio_loop = atoi(argv[0]);
454 return CMD_SUCCESS;
455}
Holger Hans Peter Freytherd582b202010-09-19 04:21:39 +0800456
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800457DEFUN(loop_endp,
458 loop_endp_cmd,
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100459 "loop-endpoint <0-64> NAME (0|1)",
460 "Loop a given endpoint\n" "Trunk number\n"
Holger Hans Peter Freyther84d88992010-08-03 23:00:03 +0800461 "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n")
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800462{
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100463 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800464 struct mgcp_endpoint *endp;
465
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100466 trunk = find_trunk(g_cfg, atoi(argv[0]));
467 if (!trunk) {
468 vty_out(vty, "%%Trunk %d not found in the config.%s",
469 atoi(argv[0]), VTY_NEWLINE);
470 return CMD_WARNING;
471 }
472
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +0100473 if (!trunk->endpoints) {
474 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
475 trunk->trunk_nr, VTY_NEWLINE);
476 return CMD_WARNING;
477 }
478
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100479 int endp_no = strtoul(argv[1], NULL, 16);
480 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800481 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100482 argv[1], endp_no, VTY_NEWLINE);
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800483 return CMD_WARNING;
484 }
485
486
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100487 endp = &trunk->endpoints[endp_no];
488 int loop = atoi(argv[2]);
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800489
490 if (loop)
491 endp->conn_mode = MGCP_CONN_LOOPBACK;
492 else
493 endp->conn_mode = endp->orig_mode;
Holger Hans Peter Freyther73aa5142010-08-05 12:07:00 +0000494 endp->allow_patch = 1;
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800495
496 return CMD_SUCCESS;
497}
498
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800499DEFUN(tap_call,
500 tap_call_cmd,
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100501 "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
502 "Forward data on endpoint to a different system\n" "Trunk number\n"
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800503 "The endpoint in hex\n"
504 "Forward the data coming from the bts\n"
505 "Forward the data coming from the bts leaving to the network\n"
506 "Forward the data coming from the net\n"
507 "Forward the data coming from the net leaving to the bts\n"
508 "destination IP of the data\n" "destination port\n")
509{
510 struct mgcp_rtp_tap *tap;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100511 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800512 struct mgcp_endpoint *endp;
513 int port = 0;
514
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100515 trunk = find_trunk(g_cfg, atoi(argv[0]));
516 if (!trunk) {
517 vty_out(vty, "%%Trunk %d not found in the config.%s",
518 atoi(argv[0]), VTY_NEWLINE);
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800519 return CMD_WARNING;
520 }
521
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +0100522 if (!trunk->endpoints) {
523 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
524 trunk->trunk_nr, VTY_NEWLINE);
525 return CMD_WARNING;
526 }
527
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100528 int endp_no = strtoul(argv[1], NULL, 16);
529 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
530 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
531 argv[1], endp_no, VTY_NEWLINE);
532 return CMD_WARNING;
533 }
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800534
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100535 endp = &trunk->endpoints[endp_no];
536
537 if (strcmp(argv[2], "bts-in") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800538 port = MGCP_TAP_BTS_IN;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100539 } else if (strcmp(argv[2], "bts-out") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800540 port = MGCP_TAP_BTS_OUT;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100541 } else if (strcmp(argv[2], "net-in") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800542 port = MGCP_TAP_NET_IN;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100543 } else if (strcmp(argv[2], "net-out") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800544 port = MGCP_TAP_NET_OUT;
545 } else {
546 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
547 return CMD_WARNING;
548 }
549
550 tap = &endp->taps[port];
551 memset(&tap->forward, 0, sizeof(tap->forward));
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100552 inet_aton(argv[3], &tap->forward.sin_addr);
553 tap->forward.sin_port = htons(atoi(argv[4]));
Holger Hans Peter Freyther079f0332010-08-06 02:05:15 +0800554 tap->enabled = 1;
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800555 return CMD_SUCCESS;
556}
557
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800558DEFUN(free_endp, free_endp_cmd,
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100559 "free-endpoint <0-64> NUMBER",
560 "Free the given endpoint\n" "Trunk number\n"
561 "Endpoint number in hex.\n")
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800562{
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100563 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800564 struct mgcp_endpoint *endp;
565
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100566 trunk = find_trunk(g_cfg, atoi(argv[0]));
567 if (!trunk) {
568 vty_out(vty, "%%Trunk %d not found in the config.%s",
569 atoi(argv[0]), VTY_NEWLINE);
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800570 return CMD_WARNING;
571 }
572
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +0100573 if (!trunk->endpoints) {
574 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
575 trunk->trunk_nr, VTY_NEWLINE);
576 return CMD_WARNING;
577 }
578
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100579 int endp_no = strtoul(argv[1], NULL, 16);
580 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
581 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
582 argv[1], endp_no, VTY_NEWLINE);
583 return CMD_WARNING;
584 }
585
586 endp = &trunk->endpoints[endp_no];
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800587 mgcp_free_endp(endp);
588 return CMD_SUCCESS;
589}
590
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100591int mgcp_vty_init(void)
592{
Holger Hans Peter Freyther8a223852010-05-14 02:45:52 +0800593 install_element_ve(&show_mgcp_cmd);
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800594 install_element(ENABLE_NODE, &loop_endp_cmd);
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800595 install_element(ENABLE_NODE, &tap_call_cmd);
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800596 install_element(ENABLE_NODE, &free_endp_cmd);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100597
598 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
599 install_node(&mgcp_node, config_write_mgcp);
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800600
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100601 install_default(MGCP_NODE);
Harald Welte58ed1cb2010-05-14 18:59:17 +0200602 install_element(MGCP_NODE, &ournode_exit_cmd);
Harald Weltedc82b9b2010-05-14 19:11:04 +0200603 install_element(MGCP_NODE, &ournode_end_cmd);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100604 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
605 install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
606 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
607 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
608 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
609 install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd);
Holger Hans Peter Freytheree4657c2010-08-05 03:46:07 +0800610 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
Holger Hans Peter Freyther81938e92010-08-05 04:10:21 +0800611 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +0800612 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
613 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Holger Hans Peter Freyther39f2f6d2010-09-17 23:35:53 +0800614 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
615 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
Holger Hans Peter Freyther3140c4f2010-07-27 20:34:45 +0800616 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
Holger Hans Peter Freyther489d0a62010-05-31 10:22:00 +0800617 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
Holger Hans Peter Freyther19ff6792010-03-31 11:46:41 +0200618 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
Holger Hans Peter Freythercab38342010-09-17 03:58:52 +0800619 install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
Holger Hans Peter Freythered1a5a52010-11-01 20:06:45 +0100620 install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
Holger Hans Peter Freytherd582b202010-09-19 04:21:39 +0800621 install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
Holger Hans Peter Freyther06bfe792011-02-28 12:11:02 +0100622 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
623 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
624 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
625 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
626
627 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
628 install_node(&trunk_node, config_write_trunk);
629 install_default(TRUNK_NODE);
630 install_element(TRUNK_NODE, &ournode_exit_cmd);
631 install_element(TRUNK_NODE, &ournode_end_cmd);
632 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
633 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
634 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
635
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100636 return 0;
637}
638
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100639static int allocate_trunk(struct mgcp_trunk_config *trunk)
640{
641 int i;
642 struct mgcp_config *cfg = trunk->cfg;
643
644 if (mgcp_endpoints_allocate(trunk) != 0) {
645 LOGP(DMGCP, LOGL_ERROR,
646 "Failed to allocate %d endpoints on trunk %d.\n",
647 trunk->number_endpoints, trunk->trunk_nr);
648 return -1;
649 }
650
651 /* early bind */
652 for (i = 1; i < trunk->number_endpoints; ++i) {
653 struct mgcp_endpoint *endp = &trunk->endpoints[i];
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100654
655 if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freytherba9c7632011-02-28 14:46:01 +0100656 cfg->last_bts_port += 2;
657 if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) {
658 LOGP(DMGCP, LOGL_FATAL,
659 "Failed to bind: %d\n", cfg->last_bts_port);
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100660 return -1;
661 }
662 endp->bts_end.local_alloc = PORT_ALLOC_STATIC;
663 }
664
665 if (cfg->net_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freytherba9c7632011-02-28 14:46:01 +0100666 cfg->last_net_port += 2;
667 if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) {
668 LOGP(DMGCP, LOGL_FATAL,
669 "Failed to bind: %d\n", cfg->last_net_port);
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100670 return -1;
671 }
672 endp->net_end.local_alloc = PORT_ALLOC_STATIC;
673 }
674
Holger Hans Peter Freyther1b8eaf42011-02-28 14:51:48 +0100675 if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL &&
676 cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freytherba9c7632011-02-28 14:46:01 +0100677 int rtp_port;
678
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100679 /* network side */
680 rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
681 cfg->transcoder_ports.base_port);
682 if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
683 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
684 return -1;
685 }
686 endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
687
688 /* bts side */
689 rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
690 cfg->transcoder_ports.base_port);
691 if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
692 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
693 return -1;
694 }
695 endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
696 }
697 }
698
699 return 0;
700}
701
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100702int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
703{
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100704 int rc;
705 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100706
707 g_cfg = cfg;
Harald Welte40152872010-05-16 20:52:23 +0200708 rc = vty_read_config_file(config_file, NULL);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100709 if (rc < 0) {
710 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
711 return rc;
712 }
713
714
715 if (!g_cfg->bts_ip)
716 fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
717
Holger Hans Peter Freytherbdd3cc32010-03-30 13:00:10 +0200718 if (!g_cfg->source_addr) {
719 fprintf(stderr, "You need to specify a bind address.\n");
720 return -1;
721 }
722
Holger Hans Peter Freytherba9c7632011-02-28 14:46:01 +0100723 /* initialize the last ports */
724 g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
725 g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
726
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100727 if (allocate_trunk(&g_cfg->trunk) != 0) {
728 LOGP(DMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100729 return -1;
730 }
731
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100732 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
733 if (allocate_trunk(trunk) != 0) {
734 LOGP(DMGCP, LOGL_ERROR,
735 "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
736 return -1;
Holger Hans Peter Freyther56ac2692010-09-18 02:30:02 +0800737 }
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100738 }
739
Holger Hans Peter Freyther64344522010-08-05 01:28:22 +0800740 return 0;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100741}
742