blob: be77b83efa10f3a612f76a5b21d5d68cec340694 [file] [log] [blame]
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +01001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The protocol implementation */
3
4/*
Holger Hans Peter Freyther88ad7722011-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 Freyther7bdc6372010-02-20 21:21:02 +01007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-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 Freyther7bdc6372010-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 Welte9af6ddf2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010018 *
Harald Welte9af6ddf2011-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 Freyther7bdc6372010-02-20 21:21:02 +010021 *
22 */
23
24#include <sys/types.h>
25
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010026#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther1ebad742010-02-26 20:16:37 +010027
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010028#include <openbsc/mgcp.h>
29#include <openbsc/mgcp_internal.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020030#include <openbsc/vty.h>
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010031
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020032#include <string.h>
33
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010034static struct mgcp_config *g_cfg = NULL;
35
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010036static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010037{
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010038 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010039
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010040 if (nr == 0)
41 trunk = &cfg->trunk;
42 else
43 trunk = mgcp_trunk_num(cfg, nr);
44
45 return trunk;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010046}
47
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010048/*
49 * vty code for mgcp below
50 */
51struct cmd_node mgcp_node = {
52 MGCP_NODE,
53 "%s(mgcp)#",
54 1,
55};
56
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +010057struct cmd_node trunk_node = {
58 TRUNK_NODE,
59 "%s(trunk)#",
60 1,
61};
62
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010063static int config_write_mgcp(struct vty *vty)
64{
65 vty_out(vty, "mgcp%s", VTY_NEWLINE);
66 if (g_cfg->local_ip)
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020067 vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
68 if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010069 vty_out(vty, " bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
70 vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
71 vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
Holger Hans Peter Freyther15e73892010-08-05 07:10:56 +080072
73 if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC)
74 vty_out(vty, " rtp bts-base %u%s", g_cfg->bts_ports.base_port, VTY_NEWLINE);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +080075 else
76 vty_out(vty, " rtp bts-range %u %u%s",
77 g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE);
78
Holger Hans Peter Freyther15e73892010-08-05 07:10:56 +080079 if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
80 vty_out(vty, " rtp net-base %u%s", g_cfg->net_ports.base_port, VTY_NEWLINE);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +080081 else
82 vty_out(vty, " rtp net-range %u %u%s",
83 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
84
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +080085 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +010086 if (g_cfg->trunk.audio_payload != -1)
87 vty_out(vty, " sdp audio payload number %d%s",
88 g_cfg->trunk.audio_payload, VTY_NEWLINE);
89 if (g_cfg->trunk.audio_name)
90 vty_out(vty, " sdp audio payload name %s%s",
91 g_cfg->trunk.audio_name, VTY_NEWLINE);
92 vty_out(vty, " loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
93 vty_out(vty, " number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +020094 if (g_cfg->call_agent_addr)
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020095 vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +080096 if (g_cfg->transcoder_ip)
97 vty_out(vty, " transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010098
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +080099 if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC)
100 vty_out(vty, " rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE);
101 else
102 vty_out(vty, " rtp transcoder-range %u %u%s",
103 g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE);
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800104 vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800105
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100106 return CMD_SUCCESS;
107}
108
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100109static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg)
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100110{
111 int i;
112
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100113 vty_out(vty, "%s trunk nr %d with %d endpoints:%s",
114 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
115 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
116
Holger Hans Peter Freythercdba0492011-02-28 12:27:47 +0100117 if (!cfg->endpoints) {
118 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
119 return;
120 }
121
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100122 for (i = 1; i < cfg->number_endpoints; ++i) {
123 struct mgcp_endpoint *endp = &cfg->endpoints[i];
124 vty_out(vty,
125 " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s "
126 "traffic received bts: %u/%u remote: %u/%u transcoder: %u/%u%s",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100127 i, endp->ci,
Holger Hans Peter Freythera17d7012010-08-05 01:34:51 +0800128 ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
129 ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port),
130 inet_ntoa(endp->bts_end.addr),
131 endp->bts_end.packets, endp->bts_state.lost_no,
132 endp->net_end.packets, endp->net_state.lost_no,
Holger Hans Peter Freytherbd7b3c52010-11-01 21:04:54 +0100133 endp->trans_net.packets, endp->trans_bts.packets,
Holger Hans Peter Freytherb4b135e2010-04-07 09:37:17 +0200134 VTY_NEWLINE);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100135 }
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100136}
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100137
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100138DEFUN(show_mcgp, show_mgcp_cmd, "show mgcp",
139 SHOW_STR "Display information about the MGCP Media Gateway")
140{
Holger Hans Peter Freythercdba0492011-02-28 12:27:47 +0100141 struct mgcp_trunk_config *trunk;
142
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100143 dump_trunk(vty, &g_cfg->trunk);
Holger Hans Peter Freythercdba0492011-02-28 12:27:47 +0100144
145 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
146 dump_trunk(vty, trunk);
147
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100148 return CMD_SUCCESS;
149}
150
151DEFUN(cfg_mgcp,
152 cfg_mgcp_cmd,
153 "mgcp",
154 "Configure the MGCP")
155{
156 vty->node = MGCP_NODE;
157 return CMD_SUCCESS;
158}
159
160DEFUN(cfg_mgcp_local_ip,
161 cfg_mgcp_local_ip_cmd,
Holger Hans Peter Freyther1384af62010-05-14 02:27:50 +0800162 "local ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100163 "Set the IP to be used in SDP records")
164{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200165 bsc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100166 return CMD_SUCCESS;
167}
168
169DEFUN(cfg_mgcp_bts_ip,
170 cfg_mgcp_bts_ip_cmd,
Holger Hans Peter Freyther1384af62010-05-14 02:27:50 +0800171 "bts ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100172 "Set the IP of the BTS for RTP forwarding")
173{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200174 bsc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100175 inet_aton(g_cfg->bts_ip, &g_cfg->bts_in);
176 return CMD_SUCCESS;
177}
178
179DEFUN(cfg_mgcp_bind_ip,
180 cfg_mgcp_bind_ip_cmd,
Holger Hans Peter Freyther1384af62010-05-14 02:27:50 +0800181 "bind ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100182 "Bind the MGCP to this local addr")
183{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200184 bsc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100185 return CMD_SUCCESS;
186}
187
188DEFUN(cfg_mgcp_bind_port,
189 cfg_mgcp_bind_port_cmd,
190 "bind port <0-65534>",
191 "Bind the MGCP to this port")
192{
193 unsigned int port = atoi(argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100194 g_cfg->source_port = port;
195 return CMD_SUCCESS;
196}
197
198DEFUN(cfg_mgcp_bind_early,
199 cfg_mgcp_bind_early_cmd,
200 "bind early (0|1)",
201 "Bind all RTP ports early")
202{
Holger Hans Peter Freytherf1a168d2010-08-05 03:22:24 +0800203 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
204 return CMD_WARNING;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100205}
206
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800207static void parse_base(struct mgcp_port_range *range, const char **argv)
208{
209 unsigned int port = atoi(argv[0]);
210 range->mode = PORT_ALLOC_STATIC;
211 range->base_port = port;
212}
213
214static void parse_range(struct mgcp_port_range *range, const char **argv)
215{
216 range->mode = PORT_ALLOC_DYNAMIC;
217 range->range_start = atoi(argv[0]);
218 range->range_end = atoi(argv[1]);
219 range->last_port = g_cfg->bts_ports.range_start;
220}
221
222
Holger Hans Peter Freyther196349d2010-08-05 03:46:07 +0800223DEFUN(cfg_mgcp_rtp_bts_base_port,
224 cfg_mgcp_rtp_bts_base_port_cmd,
225 "rtp bts-base <0-65534>",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100226 "Base port to use")
227{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800228 parse_base(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100229 return CMD_SUCCESS;
230}
231
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800232DEFUN(cfg_mgcp_rtp_bts_range,
233 cfg_mgcp_rtp_bts_range_cmd,
234 "rtp bts-range <0-65534> <0-65534>",
235 "Range of ports to allocate for endpoints\n"
236 "Start of the range of ports\n" "End of the range of ports\n")
237{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800238 parse_range(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800239 return CMD_SUCCESS;
240}
241
242DEFUN(cfg_mgcp_rtp_net_range,
243 cfg_mgcp_rtp_net_range_cmd,
244 "rtp net-range <0-65534> <0-65534>",
245 "Range of ports to allocate for endpoints\n"
246 "Start of the range of ports\n" "End of the range of ports\n")
247{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800248 parse_range(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800249 return CMD_SUCCESS;
250}
251
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800252DEFUN(cfg_mgcp_rtp_net_base_port,
253 cfg_mgcp_rtp_net_base_port_cmd,
254 "rtp net-base <0-65534>",
255 "Base port to use for network port\n" "Port\n")
256{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800257 parse_base(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800258 return CMD_SUCCESS;
259}
260
Holger Hans Peter Freyther196349d2010-08-05 03:46:07 +0800261ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd,
262 "rtp base <0-65534>", "Base port to use")
263
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800264DEFUN(cfg_mgcp_rtp_transcoder_range,
265 cfg_mgcp_rtp_transcoder_range_cmd,
266 "rtp transcoder-range <0-65534> <0-65534>",
267 "Range of ports to allocate for the transcoder\n"
268 "Start of the range of ports\n" "End of the range of ports\n")
269{
270 parse_range(&g_cfg->transcoder_ports, argv);
271 return CMD_SUCCESS;
272}
273
274DEFUN(cfg_mgcp_rtp_transcoder_base,
275 cfg_mgcp_rtp_transcoder_base_cmd,
276 "rtp transcoder-base <0-65534>",
277 "Base port for the transcoder range\n" "Port\n")
278{
279 parse_base(&g_cfg->transcoder_ports, argv);
280 return CMD_SUCCESS;
281}
282
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800283DEFUN(cfg_mgcp_rtp_ip_dscp,
284 cfg_mgcp_rtp_ip_dscp_cmd,
285 "rtp ip-dscp <0-255>",
286 "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800287{
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800288 int dscp = atoi(argv[0]);
289 g_cfg->endp_dscp = dscp;
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800290 return CMD_SUCCESS;
291}
292
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800293ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
294 "rtp ip-tos <0-255>",
295 "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
296
297
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100298DEFUN(cfg_mgcp_sdp_payload_number,
299 cfg_mgcp_sdp_payload_number_cmd,
300 "sdp audio payload number <1-255>",
301 "Set the audio codec to use")
302{
303 unsigned int payload = atoi(argv[0]);
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100304 g_cfg->trunk.audio_payload = payload;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100305 return CMD_SUCCESS;
306}
307
308DEFUN(cfg_mgcp_sdp_payload_name,
309 cfg_mgcp_sdp_payload_name_cmd,
310 "sdp audio payload name NAME",
311 "Set the audio name to use")
312{
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100313 bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100314 return CMD_SUCCESS;
315}
316
317DEFUN(cfg_mgcp_loop,
318 cfg_mgcp_loop_cmd,
319 "loop (0|1)",
320 "Loop the audio")
321{
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100322 g_cfg->trunk.audio_loop = atoi(argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100323 return CMD_SUCCESS;
324}
325
326DEFUN(cfg_mgcp_number_endp,
327 cfg_mgcp_number_endp_cmd,
328 "number endpoints <0-65534>",
329 "The number of endpoints to allocate. This is not dynamic.")
330{
331 /* + 1 as we start counting at one */
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100332 g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100333 return CMD_SUCCESS;
334}
335
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200336DEFUN(cfg_mgcp_agent_addr,
337 cfg_mgcp_agent_addr_cmd,
338 "call agent ip IP",
339 "Set the address of the call agent.")
340{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200341 bsc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200342 return CMD_SUCCESS;
343}
344
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800345DEFUN(cfg_mgcp_transcoder,
346 cfg_mgcp_transcoder_cmd,
347 "transcoder-mgw A.B.C.D",
348 "Use a MGW to detranscoder RTP\n"
349 "The IP address of the MGW")
350{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200351 bsc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800352 inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in);
353
354 return CMD_SUCCESS;
355}
356
Holger Hans Peter Freyther88b597e2010-11-01 20:06:45 +0100357DEFUN(cfg_mgcp_no_transcoder,
358 cfg_mgcp_no_transcoder_cmd,
359 NO_STR "transcoder-mgw",
360 "Disable the transcoding\n")
361{
362 if (g_cfg->transcoder_ip) {
363 LOGP(DMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n");
364 talloc_free(g_cfg->transcoder_ip);
365 g_cfg->transcoder_ip = NULL;
366 }
367
368 return CMD_SUCCESS;
369}
370
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800371DEFUN(cfg_mgcp_transcoder_remote_base,
372 cfg_mgcp_transcoder_remote_base_cmd,
373 "transcoder-remote-base <0-65534>",
374 "Set the base port for the transcoder\n" "The RTP base port on the transcoder")
375{
376 g_cfg->transcoder_remote_base = atoi(argv[0]);
377 return CMD_SUCCESS;
378}
379
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +0100380DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
381 "trunk <1-64>",
382 "Configure a SS7 trunk\n" "Trunk Nr\n")
383{
384 struct mgcp_trunk_config *trunk;
385 int index = atoi(argv[0]);
386
387 trunk = mgcp_trunk_num(g_cfg, index);
388 if (!trunk)
389 trunk = mgcp_trunk_alloc(g_cfg, index);
390
391 if (!trunk) {
392 vty_out(vty, "%%Unable to allocate trunk %u.%s",
393 index, VTY_NEWLINE);
394 return CMD_WARNING;
395 }
396
397 vty->node = TRUNK_NODE;
398 vty->index = trunk;
399 return CMD_SUCCESS;
400}
401
402static int config_write_trunk(struct vty *vty)
403{
404 struct mgcp_trunk_config *trunk;
405
406 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
407 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
408 vty_out(vty, " sdp audio payload number %d%s",
409 trunk->audio_payload, VTY_NEWLINE);
410 vty_out(vty, " sdp audio payload name %s%s",
411 trunk->audio_name, VTY_NEWLINE);
412 vty_out(vty, " loop %d%s",
413 trunk->audio_loop, VTY_NEWLINE);
414 }
415
416 return CMD_SUCCESS;
417}
418
419DEFUN(cfg_trunk_payload_number,
420 cfg_trunk_payload_number_cmd,
421 "sdp audio payload number <1-255>",
422 "SDP related\n" "Audio\n" "Payload\n" "Payload Number\n")
423{
424 struct mgcp_trunk_config *trunk = vty->index;
425 unsigned int payload = atoi(argv[0]);
426
427 trunk->audio_payload = payload;
428 return CMD_SUCCESS;
429}
430
431DEFUN(cfg_trunk_payload_name,
432 cfg_trunk_payload_name_cmd,
433 "sdp audio payload name NAME",
434 "SDP related\n" "Audio\n" "Payload\n" "Payload Name\n")
435{
436 struct mgcp_trunk_config *trunk = vty->index;
437
438 bsc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
439 return CMD_SUCCESS;
440}
441
442DEFUN(cfg_trunk_loop,
443 cfg_trunk_loop_cmd,
444 "loop (0|1)",
445 "Loop the audio")
446{
447 struct mgcp_trunk_config *trunk = vty->index;
448
449 trunk->audio_loop = atoi(argv[0]);
450 return CMD_SUCCESS;
451}
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800452
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800453DEFUN(loop_endp,
454 loop_endp_cmd,
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100455 "loop-endpoint <0-64> NAME (0|1)",
456 "Loop a given endpoint\n" "Trunk number\n"
Holger Hans Peter Freytherebc824c2010-08-03 23:00:03 +0800457 "The name in hex of the endpoint\n" "Disable the loop\n" "Enable the loop\n")
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800458{
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100459 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800460 struct mgcp_endpoint *endp;
461
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100462 trunk = find_trunk(g_cfg, atoi(argv[0]));
463 if (!trunk) {
464 vty_out(vty, "%%Trunk %d not found in the config.%s",
465 atoi(argv[0]), VTY_NEWLINE);
466 return CMD_WARNING;
467 }
468
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +0100469 if (!trunk->endpoints) {
470 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
471 trunk->trunk_nr, VTY_NEWLINE);
472 return CMD_WARNING;
473 }
474
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100475 int endp_no = strtoul(argv[1], NULL, 16);
476 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800477 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100478 argv[1], endp_no, VTY_NEWLINE);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800479 return CMD_WARNING;
480 }
481
482
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100483 endp = &trunk->endpoints[endp_no];
484 int loop = atoi(argv[2]);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800485
486 if (loop)
487 endp->conn_mode = MGCP_CONN_LOOPBACK;
488 else
489 endp->conn_mode = endp->orig_mode;
Holger Hans Peter Freyther6357a8e2010-08-05 12:07:00 +0000490 endp->allow_patch = 1;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800491
492 return CMD_SUCCESS;
493}
494
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800495DEFUN(tap_call,
496 tap_call_cmd,
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100497 "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
498 "Forward data on endpoint to a different system\n" "Trunk number\n"
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800499 "The endpoint in hex\n"
500 "Forward the data coming from the bts\n"
501 "Forward the data coming from the bts leaving to the network\n"
502 "Forward the data coming from the net\n"
503 "Forward the data coming from the net leaving to the bts\n"
504 "destination IP of the data\n" "destination port\n")
505{
506 struct mgcp_rtp_tap *tap;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100507 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800508 struct mgcp_endpoint *endp;
509 int port = 0;
510
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100511 trunk = find_trunk(g_cfg, atoi(argv[0]));
512 if (!trunk) {
513 vty_out(vty, "%%Trunk %d not found in the config.%s",
514 atoi(argv[0]), VTY_NEWLINE);
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800515 return CMD_WARNING;
516 }
517
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +0100518 if (!trunk->endpoints) {
519 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
520 trunk->trunk_nr, VTY_NEWLINE);
521 return CMD_WARNING;
522 }
523
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100524 int endp_no = strtoul(argv[1], NULL, 16);
525 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
526 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
527 argv[1], endp_no, VTY_NEWLINE);
528 return CMD_WARNING;
529 }
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800530
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100531 endp = &trunk->endpoints[endp_no];
532
533 if (strcmp(argv[2], "bts-in") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800534 port = MGCP_TAP_BTS_IN;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100535 } else if (strcmp(argv[2], "bts-out") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800536 port = MGCP_TAP_BTS_OUT;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100537 } else if (strcmp(argv[2], "net-in") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800538 port = MGCP_TAP_NET_IN;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100539 } else if (strcmp(argv[2], "net-out") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800540 port = MGCP_TAP_NET_OUT;
541 } else {
542 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
543 return CMD_WARNING;
544 }
545
546 tap = &endp->taps[port];
547 memset(&tap->forward, 0, sizeof(tap->forward));
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100548 inet_aton(argv[3], &tap->forward.sin_addr);
549 tap->forward.sin_port = htons(atoi(argv[4]));
Holger Hans Peter Freyther0e01d092010-08-06 02:05:15 +0800550 tap->enabled = 1;
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800551 return CMD_SUCCESS;
552}
553
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800554DEFUN(free_endp, free_endp_cmd,
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100555 "free-endpoint <0-64> NUMBER",
556 "Free the given endpoint\n" "Trunk number\n"
557 "Endpoint number in hex.\n")
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800558{
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100559 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800560 struct mgcp_endpoint *endp;
561
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100562 trunk = find_trunk(g_cfg, atoi(argv[0]));
563 if (!trunk) {
564 vty_out(vty, "%%Trunk %d not found in the config.%s",
565 atoi(argv[0]), VTY_NEWLINE);
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800566 return CMD_WARNING;
567 }
568
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +0100569 if (!trunk->endpoints) {
570 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
571 trunk->trunk_nr, VTY_NEWLINE);
572 return CMD_WARNING;
573 }
574
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100575 int endp_no = strtoul(argv[1], NULL, 16);
576 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
577 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
578 argv[1], endp_no, VTY_NEWLINE);
579 return CMD_WARNING;
580 }
581
582 endp = &trunk->endpoints[endp_no];
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800583 mgcp_free_endp(endp);
584 return CMD_SUCCESS;
585}
586
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100587int mgcp_vty_init(void)
588{
Holger Hans Peter Freytherb5be7ac2010-05-14 02:45:52 +0800589 install_element_ve(&show_mgcp_cmd);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800590 install_element(ENABLE_NODE, &loop_endp_cmd);
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800591 install_element(ENABLE_NODE, &tap_call_cmd);
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800592 install_element(ENABLE_NODE, &free_endp_cmd);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100593
594 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
595 install_node(&mgcp_node, config_write_mgcp);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800596
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100597 install_default(MGCP_NODE);
Harald Welte62ab20c2010-05-14 18:59:17 +0200598 install_element(MGCP_NODE, &ournode_exit_cmd);
Harald Welte54f74242010-05-14 19:11:04 +0200599 install_element(MGCP_NODE, &ournode_end_cmd);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100600 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
601 install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
602 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
603 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
604 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
605 install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd);
Holger Hans Peter Freyther196349d2010-08-05 03:46:07 +0800606 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800607 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800608 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
609 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800610 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
611 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800612 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800613 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200614 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800615 install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
Holger Hans Peter Freyther88b597e2010-11-01 20:06:45 +0100616 install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800617 install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +0100618 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
619 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
620 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
621 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
622
623 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
624 install_node(&trunk_node, config_write_trunk);
625 install_default(TRUNK_NODE);
626 install_element(TRUNK_NODE, &ournode_exit_cmd);
627 install_element(TRUNK_NODE, &ournode_end_cmd);
628 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
629 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
630 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
631
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100632 return 0;
633}
634
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100635static int allocate_trunk(struct mgcp_trunk_config *trunk)
636{
637 int i;
638 struct mgcp_config *cfg = trunk->cfg;
639
640 if (mgcp_endpoints_allocate(trunk) != 0) {
641 LOGP(DMGCP, LOGL_ERROR,
642 "Failed to allocate %d endpoints on trunk %d.\n",
643 trunk->number_endpoints, trunk->trunk_nr);
644 return -1;
645 }
646
647 /* early bind */
648 for (i = 1; i < trunk->number_endpoints; ++i) {
649 struct mgcp_endpoint *endp = &trunk->endpoints[i];
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100650
651 if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100652 cfg->last_bts_port += 2;
653 if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) {
654 LOGP(DMGCP, LOGL_FATAL,
655 "Failed to bind: %d\n", cfg->last_bts_port);
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100656 return -1;
657 }
658 endp->bts_end.local_alloc = PORT_ALLOC_STATIC;
659 }
660
661 if (cfg->net_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100662 cfg->last_net_port += 2;
663 if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) {
664 LOGP(DMGCP, LOGL_FATAL,
665 "Failed to bind: %d\n", cfg->last_net_port);
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100666 return -1;
667 }
668 endp->net_end.local_alloc = PORT_ALLOC_STATIC;
669 }
670
Holger Hans Peter Freyther69906872011-02-28 14:51:48 +0100671 if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL &&
672 cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100673 int rtp_port;
674
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100675 /* network side */
676 rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
677 cfg->transcoder_ports.base_port);
678 if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
679 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
680 return -1;
681 }
682 endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
683
684 /* bts side */
685 rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
686 cfg->transcoder_ports.base_port);
687 if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
688 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
689 return -1;
690 }
691 endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
692 }
693 }
694
695 return 0;
696}
697
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100698int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
699{
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100700 int rc;
701 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100702
703 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200704 rc = vty_read_config_file(config_file, NULL);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100705 if (rc < 0) {
706 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
707 return rc;
708 }
709
710
711 if (!g_cfg->bts_ip)
712 fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
713
Holger Hans Peter Freyther95e4d342010-03-30 13:00:10 +0200714 if (!g_cfg->source_addr) {
715 fprintf(stderr, "You need to specify a bind address.\n");
716 return -1;
717 }
718
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100719 /* initialize the last ports */
720 g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
721 g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
722
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100723 if (allocate_trunk(&g_cfg->trunk) != 0) {
724 LOGP(DMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100725 return -1;
726 }
727
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100728 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
729 if (allocate_trunk(trunk) != 0) {
730 LOGP(DMGCP, LOGL_ERROR,
731 "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
732 return -1;
Holger Hans Peter Freyther218f8562010-09-18 02:30:02 +0800733 }
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100734 }
735
Holger Hans Peter Freyther8b5772e2010-08-05 01:28:22 +0800736 return 0;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100737}
738