blob: 0b7a97eb872637053e8a2c283209613feb954d72 [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
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010024
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010025#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther1ebad742010-02-26 20:16:37 +010026
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010027#include <openbsc/mgcp.h>
28#include <openbsc/mgcp_internal.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020029#include <openbsc/vty.h>
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010030
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020031#include <string.h>
32
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010033static struct mgcp_config *g_cfg = NULL;
34
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010035static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010036{
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010037 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010038
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010039 if (nr == 0)
40 trunk = &cfg->trunk;
41 else
42 trunk = mgcp_trunk_num(cfg, nr);
43
44 return trunk;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010045}
46
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010047/*
48 * vty code for mgcp below
49 */
50struct cmd_node mgcp_node = {
51 MGCP_NODE,
52 "%s(mgcp)#",
53 1,
54};
55
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +010056struct cmd_node trunk_node = {
57 TRUNK_NODE,
58 "%s(trunk)#",
59 1,
60};
61
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010062static int config_write_mgcp(struct vty *vty)
63{
64 vty_out(vty, "mgcp%s", VTY_NEWLINE);
65 if (g_cfg->local_ip)
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020066 vty_out(vty, " local ip %s%s", g_cfg->local_ip, VTY_NEWLINE);
67 if (g_cfg->bts_ip && strlen(g_cfg->bts_ip) != 0)
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010068 vty_out(vty, " bts ip %s%s", g_cfg->bts_ip, VTY_NEWLINE);
69 vty_out(vty, " bind ip %s%s", g_cfg->source_addr, VTY_NEWLINE);
70 vty_out(vty, " bind port %u%s", g_cfg->source_port, VTY_NEWLINE);
Holger Hans Peter Freyther15e73892010-08-05 07:10:56 +080071
72 if (g_cfg->bts_ports.mode == PORT_ALLOC_STATIC)
73 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 +080074 else
75 vty_out(vty, " rtp bts-range %u %u%s",
76 g_cfg->bts_ports.range_start, g_cfg->bts_ports.range_end, VTY_NEWLINE);
77
Holger Hans Peter Freyther15e73892010-08-05 07:10:56 +080078 if (g_cfg->net_ports.mode == PORT_ALLOC_STATIC)
79 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 +080080 else
81 vty_out(vty, " rtp net-range %u %u%s",
82 g_cfg->net_ports.range_start, g_cfg->net_ports.range_end, VTY_NEWLINE);
83
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +080084 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +010085 if (g_cfg->trunk.audio_payload != -1)
86 vty_out(vty, " sdp audio payload number %d%s",
87 g_cfg->trunk.audio_payload, VTY_NEWLINE);
88 if (g_cfg->trunk.audio_name)
89 vty_out(vty, " sdp audio payload name %s%s",
90 g_cfg->trunk.audio_name, VTY_NEWLINE);
91 vty_out(vty, " loop %u%s", !!g_cfg->trunk.audio_loop, VTY_NEWLINE);
92 vty_out(vty, " number endpoints %u%s", g_cfg->trunk.number_endpoints - 1, VTY_NEWLINE);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +020093 if (g_cfg->call_agent_addr)
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020094 vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +080095 if (g_cfg->transcoder_ip)
96 vty_out(vty, " transcoder-mgw %s%s", g_cfg->transcoder_ip, VTY_NEWLINE);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010097
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +080098 if (g_cfg->transcoder_ports.mode == PORT_ALLOC_STATIC)
99 vty_out(vty, " rtp transcoder-base %u%s", g_cfg->transcoder_ports.base_port, VTY_NEWLINE);
100 else
101 vty_out(vty, " rtp transcoder-range %u %u%s",
102 g_cfg->transcoder_ports.range_start, g_cfg->transcoder_ports.range_end, VTY_NEWLINE);
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800103 vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800104
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100105 return CMD_SUCCESS;
106}
107
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100108static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg)
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100109{
110 int i;
111
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100112 vty_out(vty, "%s trunk nr %d with %d endpoints:%s",
113 cfg->trunk_type == MGCP_TRUNK_VIRTUAL ? "Virtual" : "E1",
114 cfg->trunk_nr, cfg->number_endpoints - 1, VTY_NEWLINE);
115
Holger Hans Peter Freythercdba0492011-02-28 12:27:47 +0100116 if (!cfg->endpoints) {
117 vty_out(vty, "No endpoints allocated yet.%s", VTY_NEWLINE);
118 return;
119 }
120
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100121 for (i = 1; i < cfg->number_endpoints; ++i) {
122 struct mgcp_endpoint *endp = &cfg->endpoints[i];
123 vty_out(vty,
124 " Endpoint 0x%.2x: CI: %d net: %u/%u bts: %u/%u on %s "
125 "traffic received bts: %u/%u remote: %u/%u transcoder: %u/%u%s",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100126 i, endp->ci,
Holger Hans Peter Freythera17d7012010-08-05 01:34:51 +0800127 ntohs(endp->net_end.rtp_port), ntohs(endp->net_end.rtcp_port),
128 ntohs(endp->bts_end.rtp_port), ntohs(endp->bts_end.rtcp_port),
129 inet_ntoa(endp->bts_end.addr),
130 endp->bts_end.packets, endp->bts_state.lost_no,
131 endp->net_end.packets, endp->net_state.lost_no,
Holger Hans Peter Freytherbd7b3c52010-11-01 21:04:54 +0100132 endp->trans_net.packets, endp->trans_bts.packets,
Holger Hans Peter Freytherb4b135e2010-04-07 09:37:17 +0200133 VTY_NEWLINE);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100134 }
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100135}
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100136
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100137DEFUN(show_mcgp, show_mgcp_cmd, "show mgcp",
138 SHOW_STR "Display information about the MGCP Media Gateway")
139{
Holger Hans Peter Freythercdba0492011-02-28 12:27:47 +0100140 struct mgcp_trunk_config *trunk;
141
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100142 dump_trunk(vty, &g_cfg->trunk);
Holger Hans Peter Freythercdba0492011-02-28 12:27:47 +0100143
144 llist_for_each_entry(trunk, &g_cfg->trunks, entry)
145 dump_trunk(vty, trunk);
146
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100147 return CMD_SUCCESS;
148}
149
150DEFUN(cfg_mgcp,
151 cfg_mgcp_cmd,
152 "mgcp",
153 "Configure the MGCP")
154{
155 vty->node = MGCP_NODE;
156 return CMD_SUCCESS;
157}
158
159DEFUN(cfg_mgcp_local_ip,
160 cfg_mgcp_local_ip_cmd,
Holger Hans Peter Freyther1384af62010-05-14 02:27:50 +0800161 "local ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100162 "Set the IP to be used in SDP records")
163{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200164 bsc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100165 return CMD_SUCCESS;
166}
167
168DEFUN(cfg_mgcp_bts_ip,
169 cfg_mgcp_bts_ip_cmd,
Holger Hans Peter Freyther1384af62010-05-14 02:27:50 +0800170 "bts ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100171 "Set the IP of the BTS for RTP forwarding")
172{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200173 bsc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100174 inet_aton(g_cfg->bts_ip, &g_cfg->bts_in);
175 return CMD_SUCCESS;
176}
177
178DEFUN(cfg_mgcp_bind_ip,
179 cfg_mgcp_bind_ip_cmd,
Holger Hans Peter Freyther1384af62010-05-14 02:27:50 +0800180 "bind ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100181 "Bind the MGCP to this local addr")
182{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200183 bsc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100184 return CMD_SUCCESS;
185}
186
187DEFUN(cfg_mgcp_bind_port,
188 cfg_mgcp_bind_port_cmd,
189 "bind port <0-65534>",
190 "Bind the MGCP to this port")
191{
192 unsigned int port = atoi(argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100193 g_cfg->source_port = port;
194 return CMD_SUCCESS;
195}
196
197DEFUN(cfg_mgcp_bind_early,
198 cfg_mgcp_bind_early_cmd,
199 "bind early (0|1)",
200 "Bind all RTP ports early")
201{
Holger Hans Peter Freytherf1a168d2010-08-05 03:22:24 +0800202 vty_out(vty, "bind early is deprecated, remove it from the config.\n");
203 return CMD_WARNING;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100204}
205
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800206static void parse_base(struct mgcp_port_range *range, const char **argv)
207{
208 unsigned int port = atoi(argv[0]);
209 range->mode = PORT_ALLOC_STATIC;
210 range->base_port = port;
211}
212
213static void parse_range(struct mgcp_port_range *range, const char **argv)
214{
215 range->mode = PORT_ALLOC_DYNAMIC;
216 range->range_start = atoi(argv[0]);
217 range->range_end = atoi(argv[1]);
218 range->last_port = g_cfg->bts_ports.range_start;
219}
220
221
Holger Hans Peter Freyther196349d2010-08-05 03:46:07 +0800222DEFUN(cfg_mgcp_rtp_bts_base_port,
223 cfg_mgcp_rtp_bts_base_port_cmd,
224 "rtp bts-base <0-65534>",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100225 "Base port to use")
226{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800227 parse_base(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100228 return CMD_SUCCESS;
229}
230
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800231DEFUN(cfg_mgcp_rtp_bts_range,
232 cfg_mgcp_rtp_bts_range_cmd,
233 "rtp bts-range <0-65534> <0-65534>",
234 "Range of ports to allocate for endpoints\n"
235 "Start of the range of ports\n" "End of the range of ports\n")
236{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800237 parse_range(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800238 return CMD_SUCCESS;
239}
240
241DEFUN(cfg_mgcp_rtp_net_range,
242 cfg_mgcp_rtp_net_range_cmd,
243 "rtp net-range <0-65534> <0-65534>",
244 "Range of ports to allocate for endpoints\n"
245 "Start of the range of ports\n" "End of the range of ports\n")
246{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800247 parse_range(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800248 return CMD_SUCCESS;
249}
250
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800251DEFUN(cfg_mgcp_rtp_net_base_port,
252 cfg_mgcp_rtp_net_base_port_cmd,
253 "rtp net-base <0-65534>",
254 "Base port to use for network port\n" "Port\n")
255{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800256 parse_base(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800257 return CMD_SUCCESS;
258}
259
Holger Hans Peter Freyther196349d2010-08-05 03:46:07 +0800260ALIAS_DEPRECATED(cfg_mgcp_rtp_bts_base_port, cfg_mgcp_rtp_base_port_cmd,
261 "rtp base <0-65534>", "Base port to use")
262
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800263DEFUN(cfg_mgcp_rtp_transcoder_range,
264 cfg_mgcp_rtp_transcoder_range_cmd,
265 "rtp transcoder-range <0-65534> <0-65534>",
266 "Range of ports to allocate for the transcoder\n"
267 "Start of the range of ports\n" "End of the range of ports\n")
268{
269 parse_range(&g_cfg->transcoder_ports, argv);
270 return CMD_SUCCESS;
271}
272
273DEFUN(cfg_mgcp_rtp_transcoder_base,
274 cfg_mgcp_rtp_transcoder_base_cmd,
275 "rtp transcoder-base <0-65534>",
276 "Base port for the transcoder range\n" "Port\n")
277{
278 parse_base(&g_cfg->transcoder_ports, argv);
279 return CMD_SUCCESS;
280}
281
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800282DEFUN(cfg_mgcp_rtp_ip_dscp,
283 cfg_mgcp_rtp_ip_dscp_cmd,
284 "rtp ip-dscp <0-255>",
285 "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800286{
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800287 int dscp = atoi(argv[0]);
288 g_cfg->endp_dscp = dscp;
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800289 return CMD_SUCCESS;
290}
291
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800292ALIAS_DEPRECATED(cfg_mgcp_rtp_ip_dscp, cfg_mgcp_rtp_ip_tos_cmd,
293 "rtp ip-tos <0-255>",
294 "Set the IP_TOS socket attribute on the RTP/RTCP sockets.\n" "The DSCP value.")
295
296
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100297DEFUN(cfg_mgcp_sdp_payload_number,
298 cfg_mgcp_sdp_payload_number_cmd,
299 "sdp audio payload number <1-255>",
300 "Set the audio codec to use")
301{
302 unsigned int payload = atoi(argv[0]);
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100303 g_cfg->trunk.audio_payload = payload;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100304 return CMD_SUCCESS;
305}
306
307DEFUN(cfg_mgcp_sdp_payload_name,
308 cfg_mgcp_sdp_payload_name_cmd,
309 "sdp audio payload name NAME",
310 "Set the audio name to use")
311{
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100312 bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100313 return CMD_SUCCESS;
314}
315
316DEFUN(cfg_mgcp_loop,
317 cfg_mgcp_loop_cmd,
318 "loop (0|1)",
319 "Loop the audio")
320{
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100321 g_cfg->trunk.audio_loop = atoi(argv[0]);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100322 return CMD_SUCCESS;
323}
324
325DEFUN(cfg_mgcp_number_endp,
326 cfg_mgcp_number_endp_cmd,
327 "number endpoints <0-65534>",
328 "The number of endpoints to allocate. This is not dynamic.")
329{
330 /* + 1 as we start counting at one */
Holger Hans Peter Freyther88ad7722011-02-28 00:56:17 +0100331 g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100332 return CMD_SUCCESS;
333}
334
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200335DEFUN(cfg_mgcp_agent_addr,
336 cfg_mgcp_agent_addr_cmd,
337 "call agent ip IP",
338 "Set the address of the call agent.")
339{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200340 bsc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200341 return CMD_SUCCESS;
342}
343
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800344DEFUN(cfg_mgcp_transcoder,
345 cfg_mgcp_transcoder_cmd,
346 "transcoder-mgw A.B.C.D",
347 "Use a MGW to detranscoder RTP\n"
348 "The IP address of the MGW")
349{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200350 bsc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800351 inet_aton(g_cfg->transcoder_ip, &g_cfg->transcoder_in);
352
353 return CMD_SUCCESS;
354}
355
Holger Hans Peter Freyther88b597e2010-11-01 20:06:45 +0100356DEFUN(cfg_mgcp_no_transcoder,
357 cfg_mgcp_no_transcoder_cmd,
358 NO_STR "transcoder-mgw",
359 "Disable the transcoding\n")
360{
361 if (g_cfg->transcoder_ip) {
362 LOGP(DMGCP, LOGL_NOTICE, "Disabling transcoding on future calls.\n");
363 talloc_free(g_cfg->transcoder_ip);
364 g_cfg->transcoder_ip = NULL;
365 }
366
367 return CMD_SUCCESS;
368}
369
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800370DEFUN(cfg_mgcp_transcoder_remote_base,
371 cfg_mgcp_transcoder_remote_base_cmd,
372 "transcoder-remote-base <0-65534>",
373 "Set the base port for the transcoder\n" "The RTP base port on the transcoder")
374{
375 g_cfg->transcoder_remote_base = atoi(argv[0]);
376 return CMD_SUCCESS;
377}
378
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +0100379DEFUN(cfg_mgcp_trunk, cfg_mgcp_trunk_cmd,
380 "trunk <1-64>",
381 "Configure a SS7 trunk\n" "Trunk Nr\n")
382{
383 struct mgcp_trunk_config *trunk;
384 int index = atoi(argv[0]);
385
386 trunk = mgcp_trunk_num(g_cfg, index);
387 if (!trunk)
388 trunk = mgcp_trunk_alloc(g_cfg, index);
389
390 if (!trunk) {
391 vty_out(vty, "%%Unable to allocate trunk %u.%s",
392 index, VTY_NEWLINE);
393 return CMD_WARNING;
394 }
395
396 vty->node = TRUNK_NODE;
397 vty->index = trunk;
398 return CMD_SUCCESS;
399}
400
401static int config_write_trunk(struct vty *vty)
402{
403 struct mgcp_trunk_config *trunk;
404
405 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
406 vty_out(vty, " trunk %d%s", trunk->trunk_nr, VTY_NEWLINE);
407 vty_out(vty, " sdp audio payload number %d%s",
408 trunk->audio_payload, VTY_NEWLINE);
409 vty_out(vty, " sdp audio payload name %s%s",
410 trunk->audio_name, VTY_NEWLINE);
411 vty_out(vty, " loop %d%s",
412 trunk->audio_loop, VTY_NEWLINE);
413 }
414
415 return CMD_SUCCESS;
416}
417
418DEFUN(cfg_trunk_payload_number,
419 cfg_trunk_payload_number_cmd,
420 "sdp audio payload number <1-255>",
421 "SDP related\n" "Audio\n" "Payload\n" "Payload Number\n")
422{
423 struct mgcp_trunk_config *trunk = vty->index;
424 unsigned int payload = atoi(argv[0]);
425
426 trunk->audio_payload = payload;
427 return CMD_SUCCESS;
428}
429
430DEFUN(cfg_trunk_payload_name,
431 cfg_trunk_payload_name_cmd,
432 "sdp audio payload name NAME",
433 "SDP related\n" "Audio\n" "Payload\n" "Payload Name\n")
434{
435 struct mgcp_trunk_config *trunk = vty->index;
436
437 bsc_replace_string(g_cfg, &trunk->audio_name, argv[0]);
438 return CMD_SUCCESS;
439}
440
441DEFUN(cfg_trunk_loop,
442 cfg_trunk_loop_cmd,
443 "loop (0|1)",
444 "Loop the audio")
445{
446 struct mgcp_trunk_config *trunk = vty->index;
447
448 trunk->audio_loop = atoi(argv[0]);
449 return CMD_SUCCESS;
450}
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800451
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800452DEFUN(loop_endp,
453 loop_endp_cmd,
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100454 "loop-endpoint <0-64> NAME (0|1)",
455 "Loop a given endpoint\n" "Trunk number\n"
Holger Hans Peter Freytherebc824c2010-08-03 23:00:03 +0800456 "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 +0800457{
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100458 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800459 struct mgcp_endpoint *endp;
460
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100461 trunk = find_trunk(g_cfg, atoi(argv[0]));
462 if (!trunk) {
463 vty_out(vty, "%%Trunk %d not found in the config.%s",
464 atoi(argv[0]), VTY_NEWLINE);
465 return CMD_WARNING;
466 }
467
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +0100468 if (!trunk->endpoints) {
469 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
470 trunk->trunk_nr, VTY_NEWLINE);
471 return CMD_WARNING;
472 }
473
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100474 int endp_no = strtoul(argv[1], NULL, 16);
475 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800476 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100477 argv[1], endp_no, VTY_NEWLINE);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800478 return CMD_WARNING;
479 }
480
481
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100482 endp = &trunk->endpoints[endp_no];
483 int loop = atoi(argv[2]);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800484
485 if (loop)
486 endp->conn_mode = MGCP_CONN_LOOPBACK;
487 else
488 endp->conn_mode = endp->orig_mode;
Holger Hans Peter Freyther6357a8e2010-08-05 12:07:00 +0000489 endp->allow_patch = 1;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800490
491 return CMD_SUCCESS;
492}
493
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800494DEFUN(tap_call,
495 tap_call_cmd,
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100496 "tap-call <0-64> ENDPOINT (bts-in|bts-out|net-in|net-out) A.B.C.D <0-65534>",
497 "Forward data on endpoint to a different system\n" "Trunk number\n"
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800498 "The endpoint in hex\n"
499 "Forward the data coming from the bts\n"
500 "Forward the data coming from the bts leaving to the network\n"
501 "Forward the data coming from the net\n"
502 "Forward the data coming from the net leaving to the bts\n"
503 "destination IP of the data\n" "destination port\n")
504{
505 struct mgcp_rtp_tap *tap;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100506 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800507 struct mgcp_endpoint *endp;
508 int port = 0;
509
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100510 trunk = find_trunk(g_cfg, atoi(argv[0]));
511 if (!trunk) {
512 vty_out(vty, "%%Trunk %d not found in the config.%s",
513 atoi(argv[0]), VTY_NEWLINE);
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800514 return CMD_WARNING;
515 }
516
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +0100517 if (!trunk->endpoints) {
518 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
519 trunk->trunk_nr, VTY_NEWLINE);
520 return CMD_WARNING;
521 }
522
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100523 int endp_no = strtoul(argv[1], NULL, 16);
524 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
525 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
526 argv[1], endp_no, VTY_NEWLINE);
527 return CMD_WARNING;
528 }
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800529
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100530 endp = &trunk->endpoints[endp_no];
531
532 if (strcmp(argv[2], "bts-in") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800533 port = MGCP_TAP_BTS_IN;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100534 } else if (strcmp(argv[2], "bts-out") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800535 port = MGCP_TAP_BTS_OUT;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100536 } else if (strcmp(argv[2], "net-in") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800537 port = MGCP_TAP_NET_IN;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100538 } else if (strcmp(argv[2], "net-out") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800539 port = MGCP_TAP_NET_OUT;
540 } else {
541 vty_out(vty, "Unknown mode... tricked vty?%s", VTY_NEWLINE);
542 return CMD_WARNING;
543 }
544
545 tap = &endp->taps[port];
546 memset(&tap->forward, 0, sizeof(tap->forward));
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100547 inet_aton(argv[3], &tap->forward.sin_addr);
548 tap->forward.sin_port = htons(atoi(argv[4]));
Holger Hans Peter Freyther0e01d092010-08-06 02:05:15 +0800549 tap->enabled = 1;
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800550 return CMD_SUCCESS;
551}
552
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800553DEFUN(free_endp, free_endp_cmd,
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100554 "free-endpoint <0-64> NUMBER",
555 "Free the given endpoint\n" "Trunk number\n"
556 "Endpoint number in hex.\n")
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800557{
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100558 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800559 struct mgcp_endpoint *endp;
560
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100561 trunk = find_trunk(g_cfg, atoi(argv[0]));
562 if (!trunk) {
563 vty_out(vty, "%%Trunk %d not found in the config.%s",
564 atoi(argv[0]), VTY_NEWLINE);
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800565 return CMD_WARNING;
566 }
567
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +0100568 if (!trunk->endpoints) {
569 vty_out(vty, "%%Trunk %d has no endpoints allocated.%s",
570 trunk->trunk_nr, VTY_NEWLINE);
571 return CMD_WARNING;
572 }
573
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100574 int endp_no = strtoul(argv[1], NULL, 16);
575 if (endp_no < 1 || endp_no >= trunk->number_endpoints) {
576 vty_out(vty, "Endpoint number %s/%d is invalid.%s",
577 argv[1], endp_no, VTY_NEWLINE);
578 return CMD_WARNING;
579 }
580
581 endp = &trunk->endpoints[endp_no];
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800582 mgcp_free_endp(endp);
583 return CMD_SUCCESS;
584}
585
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100586int mgcp_vty_init(void)
587{
Holger Hans Peter Freytherb5be7ac2010-05-14 02:45:52 +0800588 install_element_ve(&show_mgcp_cmd);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800589 install_element(ENABLE_NODE, &loop_endp_cmd);
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800590 install_element(ENABLE_NODE, &tap_call_cmd);
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800591 install_element(ENABLE_NODE, &free_endp_cmd);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100592
593 install_element(CONFIG_NODE, &cfg_mgcp_cmd);
594 install_node(&mgcp_node, config_write_mgcp);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800595
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100596 install_default(MGCP_NODE);
Harald Welte62ab20c2010-05-14 18:59:17 +0200597 install_element(MGCP_NODE, &ournode_exit_cmd);
Harald Welte54f74242010-05-14 19:11:04 +0200598 install_element(MGCP_NODE, &ournode_end_cmd);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100599 install_element(MGCP_NODE, &cfg_mgcp_local_ip_cmd);
600 install_element(MGCP_NODE, &cfg_mgcp_bts_ip_cmd);
601 install_element(MGCP_NODE, &cfg_mgcp_bind_ip_cmd);
602 install_element(MGCP_NODE, &cfg_mgcp_bind_port_cmd);
603 install_element(MGCP_NODE, &cfg_mgcp_bind_early_cmd);
604 install_element(MGCP_NODE, &cfg_mgcp_rtp_base_port_cmd);
Holger Hans Peter Freyther196349d2010-08-05 03:46:07 +0800605 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800606 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800607 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_range_cmd);
608 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_range_cmd);
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800609 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_range_cmd);
610 install_element(MGCP_NODE, &cfg_mgcp_rtp_transcoder_base_cmd);
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800611 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800612 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200613 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800614 install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
Holger Hans Peter Freyther88b597e2010-11-01 20:06:45 +0100615 install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800616 install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
Holger Hans Peter Freyther0e939fe2011-02-28 12:11:02 +0100617 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_number_cmd);
618 install_element(MGCP_NODE, &cfg_mgcp_sdp_payload_name_cmd);
619 install_element(MGCP_NODE, &cfg_mgcp_loop_cmd);
620 install_element(MGCP_NODE, &cfg_mgcp_number_endp_cmd);
621
622 install_element(MGCP_NODE, &cfg_mgcp_trunk_cmd);
623 install_node(&trunk_node, config_write_trunk);
624 install_default(TRUNK_NODE);
625 install_element(TRUNK_NODE, &ournode_exit_cmd);
626 install_element(TRUNK_NODE, &ournode_end_cmd);
627 install_element(TRUNK_NODE, &cfg_trunk_payload_number_cmd);
628 install_element(TRUNK_NODE, &cfg_trunk_payload_name_cmd);
629 install_element(TRUNK_NODE, &cfg_trunk_loop_cmd);
630
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100631 return 0;
632}
633
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100634static int allocate_trunk(struct mgcp_trunk_config *trunk)
635{
636 int i;
637 struct mgcp_config *cfg = trunk->cfg;
638
639 if (mgcp_endpoints_allocate(trunk) != 0) {
640 LOGP(DMGCP, LOGL_ERROR,
641 "Failed to allocate %d endpoints on trunk %d.\n",
642 trunk->number_endpoints, trunk->trunk_nr);
643 return -1;
644 }
645
646 /* early bind */
647 for (i = 1; i < trunk->number_endpoints; ++i) {
648 struct mgcp_endpoint *endp = &trunk->endpoints[i];
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100649
650 if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100651 cfg->last_bts_port += 2;
652 if (mgcp_bind_bts_rtp_port(endp, cfg->last_bts_port) != 0) {
653 LOGP(DMGCP, LOGL_FATAL,
654 "Failed to bind: %d\n", cfg->last_bts_port);
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100655 return -1;
656 }
657 endp->bts_end.local_alloc = PORT_ALLOC_STATIC;
658 }
659
660 if (cfg->net_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100661 cfg->last_net_port += 2;
662 if (mgcp_bind_net_rtp_port(endp, cfg->last_net_port) != 0) {
663 LOGP(DMGCP, LOGL_FATAL,
664 "Failed to bind: %d\n", cfg->last_net_port);
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100665 return -1;
666 }
667 endp->net_end.local_alloc = PORT_ALLOC_STATIC;
668 }
669
Holger Hans Peter Freyther69906872011-02-28 14:51:48 +0100670 if (trunk->trunk_type == MGCP_TRUNK_VIRTUAL &&
671 cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100672 int rtp_port;
673
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100674 /* network side */
675 rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
676 cfg->transcoder_ports.base_port);
677 if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
678 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
679 return -1;
680 }
681 endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
682
683 /* bts side */
684 rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
685 cfg->transcoder_ports.base_port);
686 if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
687 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
688 return -1;
689 }
690 endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
691 }
692 }
693
694 return 0;
695}
696
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100697int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
698{
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100699 int rc;
700 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100701
702 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200703 rc = vty_read_config_file(config_file, NULL);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100704 if (rc < 0) {
705 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
706 return rc;
707 }
708
709
710 if (!g_cfg->bts_ip)
711 fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
712
Holger Hans Peter Freyther95e4d342010-03-30 13:00:10 +0200713 if (!g_cfg->source_addr) {
714 fprintf(stderr, "You need to specify a bind address.\n");
715 return -1;
716 }
717
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100718 /* initialize the last ports */
719 g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
720 g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
721
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100722 if (allocate_trunk(&g_cfg->trunk) != 0) {
723 LOGP(DMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100724 return -1;
725 }
726
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100727 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
728 if (allocate_trunk(trunk) != 0) {
729 LOGP(DMGCP, LOGL_ERROR,
730 "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
731 return -1;
Holger Hans Peter Freyther218f8562010-09-18 02:30:02 +0800732 }
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100733 }
734
Holger Hans Peter Freyther8b5772e2010-08-05 01:28:22 +0800735 return 0;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100736}
737