blob: f71c17be483fa2a5b9914fbc2170740ee64e7eb6 [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
Holger Hans Peter Freyther1ebad742010-02-26 20:16:37 +010026#include <osmocore/talloc.h>
27
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010028#include <openbsc/debug.h>
29#include <openbsc/mgcp.h>
30#include <openbsc/mgcp_internal.h>
Harald Welte62ab20c2010-05-14 18:59:17 +020031#include <openbsc/vty.h>
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010032
Harald Welte4b037e42010-05-19 19:45:32 +020033#include <osmocom/vty/command.h>
34#include <osmocom/vty/vty.h>
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010035
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020036#include <string.h>
37
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +010038static struct mgcp_config *g_cfg = NULL;
39
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010040static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010041{
Holger Hans Peter Freyther6ea7e772011-02-28 12:32:18 +010042 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +010043
Holger Hans Peter Freyther6ea7e772011-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 Freytherab3bb9d2011-02-28 01:29:02 +010050}
51
Holger Hans Peter Freyther7bdc6372010-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 Freyther0e939fe2011-02-28 12:11:02 +010061struct cmd_node trunk_node = {
62 TRUNK_NODE,
63 "%s(trunk)#",
64 1,
65};
66
Holger Hans Peter Freyther7bdc6372010-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 Freyther8d9833e2010-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 Freyther7bdc6372010-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 Freyther15e73892010-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 Freyther1be9f2f2010-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 Freyther15e73892010-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 Freyther1be9f2f2010-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 Freytherd0c32292010-07-27 20:34:45 +080089 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
Holger Hans Peter Freyther88ad7722011-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 Freytherb79994c2010-03-31 11:46:41 +020098 if (g_cfg->call_agent_addr)
Holger Hans Peter Freyther8d9833e2010-04-16 16:59:48 +020099 vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
Holger Hans Peter Freythera2a10eb2010-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 Freyther7bdc6372010-02-20 21:21:02 +0100102
Holger Hans Peter Freyther54aaa0f2010-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 Freytherb98ba722010-09-19 04:21:39 +0800108 vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
Holger Hans Peter Freyther54aaa0f2010-09-17 23:35:53 +0800109
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100110 return CMD_SUCCESS;
111}
112
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100113static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg)
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100114{
115 int i;
116
Holger Hans Peter Freytherd011c912011-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 Freythercdba0492011-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 Freytherd011c912011-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 Freyther7bdc6372010-02-20 21:21:02 +0100131 i, endp->ci,
Holger Hans Peter Freythera17d7012010-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 Freytherbd7b3c52010-11-01 21:04:54 +0100137 endp->trans_net.packets, endp->trans_bts.packets,
Holger Hans Peter Freytherb4b135e2010-04-07 09:37:17 +0200138 VTY_NEWLINE);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100139 }
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100140}
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100141
Holger Hans Peter Freytherd011c912011-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 Freythercdba0492011-02-28 12:27:47 +0100145 struct mgcp_trunk_config *trunk;
146
Holger Hans Peter Freytherd011c912011-02-28 01:12:33 +0100147 dump_trunk(vty, &g_cfg->trunk);
Holger Hans Peter Freythercdba0492011-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 Freyther7bdc6372010-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 Freyther1384af62010-05-14 02:27:50 +0800166 "local ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100167 "Set the IP to be used in SDP records")
168{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200169 bsc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
Holger Hans Peter Freyther7bdc6372010-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 Freyther1384af62010-05-14 02:27:50 +0800175 "bts ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100176 "Set the IP of the BTS for RTP forwarding")
177{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200178 bsc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
Holger Hans Peter Freyther7bdc6372010-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 Freyther1384af62010-05-14 02:27:50 +0800185 "bind ip A.B.C.D",
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100186 "Bind the MGCP to this local addr")
187{
Holger Hans Peter Freyther3e9a7f82010-10-12 23:21:54 +0200188 bsc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
Holger Hans Peter Freyther7bdc6372010-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 Freyther7bdc6372010-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 Freytherf1a168d2010-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 Freyther7bdc6372010-02-20 21:21:02 +0100209}
210
Holger Hans Peter Freytherc5f92482010-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 Freyther196349d2010-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 Freyther7bdc6372010-02-20 21:21:02 +0100230 "Base port to use")
231{
Holger Hans Peter Freytherc5f92482010-09-17 23:34:36 +0800232 parse_base(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100233 return CMD_SUCCESS;
234}
235
Holger Hans Peter Freyther1be9f2f2010-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 Freytherc5f92482010-09-17 23:34:36 +0800242 parse_range(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther1be9f2f2010-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 Freytherc5f92482010-09-17 23:34:36 +0800252 parse_range(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther1be9f2f2010-08-05 07:20:09 +0800253 return CMD_SUCCESS;
254}
255
Holger Hans Peter Freyther314584a2010-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 Freytherc5f92482010-09-17 23:34:36 +0800261 parse_base(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800262 return CMD_SUCCESS;
263}
264
Holger Hans Peter Freyther196349d2010-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 Freyther54aaa0f2010-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 Freytherd0c32292010-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 Freyther75492e62010-05-31 10:22:00 +0800291{
Holger Hans Peter Freytherd0c32292010-07-27 20:34:45 +0800292 int dscp = atoi(argv[0]);
293 g_cfg->endp_dscp = dscp;
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800294 return CMD_SUCCESS;
295}
296
Holger Hans Peter Freytherd0c32292010-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 Freyther7bdc6372010-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 Freyther88ad7722011-02-28 00:56:17 +0100308 g_cfg->trunk.audio_payload = payload;
Holger Hans Peter Freyther7bdc6372010-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 Freyther88ad7722011-02-28 00:56:17 +0100317 bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
Holger Hans Peter Freyther7bdc6372010-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 Freyther88ad7722011-02-28 00:56:17 +0100326 g_cfg->trunk.audio_loop = atoi(argv[0]);
Holger Hans Peter Freyther7bdc6372010-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 Freyther88ad7722011-02-28 00:56:17 +0100336 g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100337 return CMD_SUCCESS;
338}
339
Holger Hans Peter Freytherb79994c2010-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 Freyther3e9a7f82010-10-12 23:21:54 +0200345 bsc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200346 return CMD_SUCCESS;
347}
348
Holger Hans Peter Freythera2a10eb2010-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 Freyther3e9a7f82010-10-12 23:21:54 +0200355 bsc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
Holger Hans Peter Freythera2a10eb2010-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 Freyther88b597e2010-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 Freytherb98ba722010-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 Freyther0e939fe2011-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 Freytherb98ba722010-09-19 04:21:39 +0800456
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800457DEFUN(loop_endp,
458 loop_endp_cmd,
Holger Hans Peter Freytherab3bb9d2011-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 Freytherebc824c2010-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 Freytherc597a4e2010-08-03 02:57:02 +0800462{
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100463 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800464 struct mgcp_endpoint *endp;
465
Holger Hans Peter Freytherab3bb9d2011-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 Freyther6ea7e772011-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 Freytherab3bb9d2011-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 Freytherc597a4e2010-08-03 02:57:02 +0800481 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100482 argv[1], endp_no, VTY_NEWLINE);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800483 return CMD_WARNING;
484 }
485
486
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100487 endp = &trunk->endpoints[endp_no];
488 int loop = atoi(argv[2]);
Holger Hans Peter Freytherc597a4e2010-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 Freyther6357a8e2010-08-05 12:07:00 +0000494 endp->allow_patch = 1;
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800495
496 return CMD_SUCCESS;
497}
498
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800499DEFUN(tap_call,
500 tap_call_cmd,
Holger Hans Peter Freytherab3bb9d2011-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 Freyther260d6ed2010-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 Freytherab3bb9d2011-02-28 01:29:02 +0100511 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800512 struct mgcp_endpoint *endp;
513 int port = 0;
514
Holger Hans Peter Freytherab3bb9d2011-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 Freyther260d6ed2010-08-06 01:12:21 +0800519 return CMD_WARNING;
520 }
521
Holger Hans Peter Freyther6ea7e772011-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 Freytherab3bb9d2011-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 Freyther260d6ed2010-08-06 01:12:21 +0800534
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100535 endp = &trunk->endpoints[endp_no];
536
537 if (strcmp(argv[2], "bts-in") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800538 port = MGCP_TAP_BTS_IN;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100539 } else if (strcmp(argv[2], "bts-out") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800540 port = MGCP_TAP_BTS_OUT;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100541 } else if (strcmp(argv[2], "net-in") == 0) {
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800542 port = MGCP_TAP_NET_IN;
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100543 } else if (strcmp(argv[2], "net-out") == 0) {
Holger Hans Peter Freyther260d6ed2010-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 Freytherab3bb9d2011-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 Freyther0e01d092010-08-06 02:05:15 +0800554 tap->enabled = 1;
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800555 return CMD_SUCCESS;
556}
557
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800558DEFUN(free_endp, free_endp_cmd,
Holger Hans Peter Freytherab3bb9d2011-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 Freyther5508fe32010-08-08 16:39:57 +0800562{
Holger Hans Peter Freytherab3bb9d2011-02-28 01:29:02 +0100563 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800564 struct mgcp_endpoint *endp;
565
Holger Hans Peter Freytherab3bb9d2011-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 Freyther5508fe32010-08-08 16:39:57 +0800570 return CMD_WARNING;
571 }
572
Holger Hans Peter Freyther6ea7e772011-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 Freytherab3bb9d2011-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 Freyther5508fe32010-08-08 16:39:57 +0800587 mgcp_free_endp(endp);
588 return CMD_SUCCESS;
589}
590
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100591int mgcp_vty_init(void)
592{
Holger Hans Peter Freytherb5be7ac2010-05-14 02:45:52 +0800593 install_element_ve(&show_mgcp_cmd);
Holger Hans Peter Freytherc597a4e2010-08-03 02:57:02 +0800594 install_element(ENABLE_NODE, &loop_endp_cmd);
Holger Hans Peter Freyther260d6ed2010-08-06 01:12:21 +0800595 install_element(ENABLE_NODE, &tap_call_cmd);
Holger Hans Peter Freyther5508fe32010-08-08 16:39:57 +0800596 install_element(ENABLE_NODE, &free_endp_cmd);
Holger Hans Peter Freyther7bdc6372010-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 Freytherc597a4e2010-08-03 02:57:02 +0800600
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100601 install_default(MGCP_NODE);
Harald Welte62ab20c2010-05-14 18:59:17 +0200602 install_element(MGCP_NODE, &ournode_exit_cmd);
Harald Welte54f74242010-05-14 19:11:04 +0200603 install_element(MGCP_NODE, &ournode_end_cmd);
Holger Hans Peter Freyther7bdc6372010-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 Freyther196349d2010-08-05 03:46:07 +0800610 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
Holger Hans Peter Freyther314584a2010-08-05 04:10:21 +0800611 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
Holger Hans Peter Freyther1be9f2f2010-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 Freyther54aaa0f2010-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 Freytherd0c32292010-07-27 20:34:45 +0800616 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
Holger Hans Peter Freyther75492e62010-05-31 10:22:00 +0800617 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
Holger Hans Peter Freytherb79994c2010-03-31 11:46:41 +0200618 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
Holger Hans Peter Freythera2a10eb2010-09-17 03:58:52 +0800619 install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
Holger Hans Peter Freyther88b597e2010-11-01 20:06:45 +0100620 install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
Holger Hans Peter Freytherb98ba722010-09-19 04:21:39 +0800621 install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
Holger Hans Peter Freyther0e939fe2011-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 Freyther7bdc6372010-02-20 21:21:02 +0100636 return 0;
637}
638
Holger Hans Peter Freyther1f0c5b42011-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 Freyther1f0c5b42011-02-28 14:37:03 +0100654
655 if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-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 Freyther1f0c5b42011-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 Freyther44016fe2011-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 Freyther1f0c5b42011-02-28 14:37:03 +0100670 return -1;
671 }
672 endp->net_end.local_alloc = PORT_ALLOC_STATIC;
673 }
674
675 if (cfg->transcoder_ip && cfg->transcoder_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100676 int rtp_port;
677
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100678 /* network side */
679 rtp_port = rtp_calculate_port(ENDPOINT_NUMBER(endp),
680 cfg->transcoder_ports.base_port);
681 if (mgcp_bind_trans_net_rtp_port(endp, rtp_port) != 0) {
682 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
683 return -1;
684 }
685 endp->trans_net.local_alloc = PORT_ALLOC_STATIC;
686
687 /* bts side */
688 rtp_port = rtp_calculate_port(endp_back_channel(ENDPOINT_NUMBER(endp)),
689 cfg->transcoder_ports.base_port);
690 if (mgcp_bind_trans_bts_rtp_port(endp, rtp_port) != 0) {
691 LOGP(DMGCP, LOGL_FATAL, "Failed to bind: %d\n", rtp_port);
692 return -1;
693 }
694 endp->trans_bts.local_alloc = PORT_ALLOC_STATIC;
695 }
696 }
697
698 return 0;
699}
700
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100701int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
702{
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100703 int rc;
704 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100705
706 g_cfg = cfg;
Harald Weltedcccb182010-05-16 20:52:23 +0200707 rc = vty_read_config_file(config_file, NULL);
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100708 if (rc < 0) {
709 fprintf(stderr, "Failed to parse the config file: '%s'\n", config_file);
710 return rc;
711 }
712
713
714 if (!g_cfg->bts_ip)
715 fprintf(stderr, "No BTS ip address specified. This will allow everyone to connect.\n");
716
Holger Hans Peter Freyther95e4d342010-03-30 13:00:10 +0200717 if (!g_cfg->source_addr) {
718 fprintf(stderr, "You need to specify a bind address.\n");
719 return -1;
720 }
721
Holger Hans Peter Freyther44016fe2011-02-28 14:46:01 +0100722 /* initialize the last ports */
723 g_cfg->last_bts_port = rtp_calculate_port(0, g_cfg->bts_ports.base_port);
724 g_cfg->last_net_port = rtp_calculate_port(0, g_cfg->net_ports.base_port);
725
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100726 if (allocate_trunk(&g_cfg->trunk) != 0) {
727 LOGP(DMGCP, LOGL_ERROR, "Failed to initialize the virtual trunk.\n");
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100728 return -1;
729 }
730
Holger Hans Peter Freyther1f0c5b42011-02-28 14:37:03 +0100731 llist_for_each_entry(trunk, &g_cfg->trunks, entry) {
732 if (allocate_trunk(trunk) != 0) {
733 LOGP(DMGCP, LOGL_ERROR,
734 "Failed to initialize E1 trunk %d.\n", trunk->trunk_nr);
735 return -1;
Holger Hans Peter Freyther218f8562010-09-18 02:30:02 +0800736 }
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100737 }
738
Holger Hans Peter Freyther8b5772e2010-08-05 01:28:22 +0800739 return 0;
Holger Hans Peter Freyther7bdc6372010-02-20 21:21:02 +0100740}
741