blob: 0b7a97eb872637053e8a2c283209613feb954d72 [file] [log] [blame]
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +01001/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
2/* The protocol implementation */
3
4/*
Holger Hans Peter Freytherab56ce12011-02-28 00:56:17 +01005 * (C) 2009-2011 by Holger Hans Peter Freyther <zecke@selfish.org>
6 * (C) 2009-2011 by On-Waves
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +01007 * All Rights Reserved
8 *
9 * This program is free software; you can redistribute it and/or modify
Harald Welte0e3e88e2011-01-01 15:25:50 +010010 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010012 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte0e3e88e2011-01-01 15:25:50 +010017 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010018 *
Harald Welte0e3e88e2011-01-01 15:25:50 +010019 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010021 *
22 */
23
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010024
Pablo Neira Ayusodd5fff42011-03-22 16:47:59 +010025#include <osmocom/core/talloc.h>
Holger Hans Peter Freytherf41fb1f2010-02-26 20:16:37 +010026
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010027#include <openbsc/mgcp.h>
28#include <openbsc/mgcp_internal.h>
Harald Welte58ed1cb2010-05-14 18:59:17 +020029#include <openbsc/vty.h>
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010030
Holger Hans Peter Freythere8d13712010-04-16 16:59:48 +020031#include <string.h>
32
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +010033static struct mgcp_config *g_cfg = NULL;
34
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +010035static struct mgcp_trunk_config *find_trunk(struct mgcp_config *cfg, int nr)
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +010036{
Holger Hans Peter Freyther1ca419d2011-02-28 12:32:18 +010037 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +010038
Holger Hans Peter Freyther1ca419d2011-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 Freyther75cf62d2011-02-28 01:29:02 +010045}
46
Holger Hans Peter Freyther6f38c062010-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 Freyther06bfe792011-02-28 12:11:02 +010056struct cmd_node trunk_node = {
57 TRUNK_NODE,
58 "%s(trunk)#",
59 1,
60};
61
Holger Hans Peter Freyther6f38c062010-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 Freythere8d13712010-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 Freyther6f38c062010-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 Freyther2ea91182010-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 Freytherf3307292010-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 Freyther2ea91182010-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 Freytherf3307292010-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 Freyther3140c4f2010-07-27 20:34:45 +080084 vty_out(vty, " rtp ip-dscp %d%s", g_cfg->endp_dscp, VTY_NEWLINE);
Holger Hans Peter Freytherab56ce12011-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 Freyther19ff6792010-03-31 11:46:41 +020093 if (g_cfg->call_agent_addr)
Holger Hans Peter Freythere8d13712010-04-16 16:59:48 +020094 vty_out(vty, " call agent ip %s%s", g_cfg->call_agent_addr, VTY_NEWLINE);
Holger Hans Peter Freythercab38342010-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 Freyther6f38c062010-02-20 21:21:02 +010097
Holger Hans Peter Freyther39f2f6d2010-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 Freytherd582b202010-09-19 04:21:39 +0800103 vty_out(vty, " transcoder-remote-base %u%s", g_cfg->transcoder_remote_base, VTY_NEWLINE);
Holger Hans Peter Freyther39f2f6d2010-09-17 23:35:53 +0800104
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100105 return CMD_SUCCESS;
106}
107
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100108static void dump_trunk(struct vty *vty, struct mgcp_trunk_config *cfg)
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100109{
110 int i;
111
Holger Hans Peter Freyther1584bdb2011-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 Freyther088bc282011-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 Freyther1584bdb2011-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 Freyther6f38c062010-02-20 21:21:02 +0100126 i, endp->ci,
Holger Hans Peter Freytherfab76aa2010-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 Freytherc983f832010-11-01 21:04:54 +0100132 endp->trans_net.packets, endp->trans_bts.packets,
Holger Hans Peter Freyther6de5b112010-04-07 09:37:17 +0200133 VTY_NEWLINE);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100134 }
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100135}
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100136
Holger Hans Peter Freyther1584bdb2011-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 Freyther088bc282011-02-28 12:27:47 +0100140 struct mgcp_trunk_config *trunk;
141
Holger Hans Peter Freyther1584bdb2011-02-28 01:12:33 +0100142 dump_trunk(vty, &g_cfg->trunk);
Holger Hans Peter Freyther088bc282011-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 Freyther6f38c062010-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 Freyther5c9a6452010-05-14 02:27:50 +0800161 "local ip A.B.C.D",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100162 "Set the IP to be used in SDP records")
163{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200164 bsc_replace_string(g_cfg, &g_cfg->local_ip, argv[0]);
Holger Hans Peter Freyther6f38c062010-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 Freyther5c9a6452010-05-14 02:27:50 +0800170 "bts ip A.B.C.D",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100171 "Set the IP of the BTS for RTP forwarding")
172{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200173 bsc_replace_string(g_cfg, &g_cfg->bts_ip, argv[0]);
Holger Hans Peter Freyther6f38c062010-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 Freyther5c9a6452010-05-14 02:27:50 +0800180 "bind ip A.B.C.D",
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100181 "Bind the MGCP to this local addr")
182{
Holger Hans Peter Freyther7c831f62010-10-12 23:21:54 +0200183 bsc_replace_string(g_cfg, &g_cfg->source_addr, argv[0]);
Holger Hans Peter Freyther6f38c062010-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 Freyther6f38c062010-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 Freyther7140dae2010-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 Freyther6f38c062010-02-20 21:21:02 +0100204}
205
Holger Hans Peter Freytherd3b7d772010-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 Freytheree4657c2010-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 Freyther6f38c062010-02-20 21:21:02 +0100225 "Base port to use")
226{
Holger Hans Peter Freytherd3b7d772010-09-17 23:34:36 +0800227 parse_base(&g_cfg->bts_ports, argv);
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100228 return CMD_SUCCESS;
229}
230
Holger Hans Peter Freytherf3307292010-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 Freytherd3b7d772010-09-17 23:34:36 +0800237 parse_range(&g_cfg->bts_ports, argv);
Holger Hans Peter Freytherf3307292010-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 Freytherd3b7d772010-09-17 23:34:36 +0800247 parse_range(&g_cfg->net_ports, argv);
Holger Hans Peter Freytherf3307292010-08-05 07:20:09 +0800248 return CMD_SUCCESS;
249}
250
Holger Hans Peter Freyther81938e92010-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 Freytherd3b7d772010-09-17 23:34:36 +0800256 parse_base(&g_cfg->net_ports, argv);
Holger Hans Peter Freyther81938e92010-08-05 04:10:21 +0800257 return CMD_SUCCESS;
258}
259
Holger Hans Peter Freytheree4657c2010-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 Freyther39f2f6d2010-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 Freyther3140c4f2010-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 Freyther489d0a62010-05-31 10:22:00 +0800286{
Holger Hans Peter Freyther3140c4f2010-07-27 20:34:45 +0800287 int dscp = atoi(argv[0]);
288 g_cfg->endp_dscp = dscp;
Holger Hans Peter Freyther489d0a62010-05-31 10:22:00 +0800289 return CMD_SUCCESS;
290}
291
Holger Hans Peter Freyther3140c4f2010-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 Freyther6f38c062010-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 Freytherab56ce12011-02-28 00:56:17 +0100303 g_cfg->trunk.audio_payload = payload;
Holger Hans Peter Freyther6f38c062010-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 Freytherab56ce12011-02-28 00:56:17 +0100312 bsc_replace_string(g_cfg, &g_cfg->trunk.audio_name, argv[0]);
Holger Hans Peter Freyther6f38c062010-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 Freytherab56ce12011-02-28 00:56:17 +0100321 g_cfg->trunk.audio_loop = atoi(argv[0]);
Holger Hans Peter Freyther6f38c062010-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 Freytherab56ce12011-02-28 00:56:17 +0100331 g_cfg->trunk.number_endpoints = atoi(argv[0]) + 1;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100332 return CMD_SUCCESS;
333}
334
Holger Hans Peter Freyther19ff6792010-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 Freyther7c831f62010-10-12 23:21:54 +0200340 bsc_replace_string(g_cfg, &g_cfg->call_agent_addr, argv[0]);
Holger Hans Peter Freyther19ff6792010-03-31 11:46:41 +0200341 return CMD_SUCCESS;
342}
343
Holger Hans Peter Freythercab38342010-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 Freyther7c831f62010-10-12 23:21:54 +0200350 bsc_replace_string(g_cfg, &g_cfg->transcoder_ip, argv[0]);
Holger Hans Peter Freythercab38342010-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 Freythered1a5a52010-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 Freytherd582b202010-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 Freyther06bfe792011-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 Freytherd582b202010-09-19 04:21:39 +0800451
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800452DEFUN(loop_endp,
453 loop_endp_cmd,
Holger Hans Peter Freyther75cf62d2011-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 Freyther84d88992010-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 Freytherb33ded12010-08-03 02:57:02 +0800457{
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100458 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800459 struct mgcp_endpoint *endp;
460
Holger Hans Peter Freyther75cf62d2011-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 Freyther1ca419d2011-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 Freyther75cf62d2011-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 Freytherb33ded12010-08-03 02:57:02 +0800476 vty_out(vty, "Loopback number %s/%d is invalid.%s",
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100477 argv[1], endp_no, VTY_NEWLINE);
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800478 return CMD_WARNING;
479 }
480
481
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100482 endp = &trunk->endpoints[endp_no];
483 int loop = atoi(argv[2]);
Holger Hans Peter Freytherb33ded12010-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 Freyther73aa5142010-08-05 12:07:00 +0000489 endp->allow_patch = 1;
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800490
491 return CMD_SUCCESS;
492}
493
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800494DEFUN(tap_call,
495 tap_call_cmd,
Holger Hans Peter Freyther75cf62d2011-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 Freyther8fdb95e2010-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 Freyther75cf62d2011-02-28 01:29:02 +0100506 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800507 struct mgcp_endpoint *endp;
508 int port = 0;
509
Holger Hans Peter Freyther75cf62d2011-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 Freyther8fdb95e2010-08-06 01:12:21 +0800514 return CMD_WARNING;
515 }
516
Holger Hans Peter Freyther1ca419d2011-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 Freyther75cf62d2011-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 Freyther8fdb95e2010-08-06 01:12:21 +0800529
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100530 endp = &trunk->endpoints[endp_no];
531
532 if (strcmp(argv[2], "bts-in") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800533 port = MGCP_TAP_BTS_IN;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100534 } else if (strcmp(argv[2], "bts-out") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800535 port = MGCP_TAP_BTS_OUT;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100536 } else if (strcmp(argv[2], "net-in") == 0) {
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800537 port = MGCP_TAP_NET_IN;
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100538 } else if (strcmp(argv[2], "net-out") == 0) {
Holger Hans Peter Freyther8fdb95e2010-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 Freyther75cf62d2011-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 Freyther079f0332010-08-06 02:05:15 +0800549 tap->enabled = 1;
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800550 return CMD_SUCCESS;
551}
552
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800553DEFUN(free_endp, free_endp_cmd,
Holger Hans Peter Freyther75cf62d2011-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 Freyther175b9a12010-08-08 16:39:57 +0800557{
Holger Hans Peter Freyther75cf62d2011-02-28 01:29:02 +0100558 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800559 struct mgcp_endpoint *endp;
560
Holger Hans Peter Freyther75cf62d2011-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 Freyther175b9a12010-08-08 16:39:57 +0800565 return CMD_WARNING;
566 }
567
Holger Hans Peter Freyther1ca419d2011-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 Freyther75cf62d2011-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 Freyther175b9a12010-08-08 16:39:57 +0800582 mgcp_free_endp(endp);
583 return CMD_SUCCESS;
584}
585
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100586int mgcp_vty_init(void)
587{
Holger Hans Peter Freyther8a223852010-05-14 02:45:52 +0800588 install_element_ve(&show_mgcp_cmd);
Holger Hans Peter Freytherb33ded12010-08-03 02:57:02 +0800589 install_element(ENABLE_NODE, &loop_endp_cmd);
Holger Hans Peter Freyther8fdb95e2010-08-06 01:12:21 +0800590 install_element(ENABLE_NODE, &tap_call_cmd);
Holger Hans Peter Freyther175b9a12010-08-08 16:39:57 +0800591 install_element(ENABLE_NODE, &free_endp_cmd);
Holger Hans Peter Freyther6f38c062010-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 Freytherb33ded12010-08-03 02:57:02 +0800595
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100596 install_default(MGCP_NODE);
Harald Welte58ed1cb2010-05-14 18:59:17 +0200597 install_element(MGCP_NODE, &ournode_exit_cmd);
Harald Weltedc82b9b2010-05-14 19:11:04 +0200598 install_element(MGCP_NODE, &ournode_end_cmd);
Holger Hans Peter Freyther6f38c062010-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 Freytheree4657c2010-08-05 03:46:07 +0800605 install_element(MGCP_NODE, &cfg_mgcp_rtp_bts_base_port_cmd);
Holger Hans Peter Freyther81938e92010-08-05 04:10:21 +0800606 install_element(MGCP_NODE, &cfg_mgcp_rtp_net_base_port_cmd);
Holger Hans Peter Freytherf3307292010-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 Freyther39f2f6d2010-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 Freyther3140c4f2010-07-27 20:34:45 +0800611 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_dscp_cmd);
Holger Hans Peter Freyther489d0a62010-05-31 10:22:00 +0800612 install_element(MGCP_NODE, &cfg_mgcp_rtp_ip_tos_cmd);
Holger Hans Peter Freyther19ff6792010-03-31 11:46:41 +0200613 install_element(MGCP_NODE, &cfg_mgcp_agent_addr_cmd);
Holger Hans Peter Freythercab38342010-09-17 03:58:52 +0800614 install_element(MGCP_NODE, &cfg_mgcp_transcoder_cmd);
Holger Hans Peter Freythered1a5a52010-11-01 20:06:45 +0100615 install_element(MGCP_NODE, &cfg_mgcp_no_transcoder_cmd);
Holger Hans Peter Freytherd582b202010-09-19 04:21:39 +0800616 install_element(MGCP_NODE, &cfg_mgcp_transcoder_remote_base_cmd);
Holger Hans Peter Freyther06bfe792011-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 Freyther6f38c062010-02-20 21:21:02 +0100631 return 0;
632}
633
Holger Hans Peter Freyther49e170b2011-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 Freyther49e170b2011-02-28 14:37:03 +0100649
650 if (cfg->bts_ports.mode == PORT_ALLOC_STATIC) {
Holger Hans Peter Freytherba9c7632011-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 Freyther49e170b2011-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 Freytherba9c7632011-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 Freyther49e170b2011-02-28 14:37:03 +0100665 return -1;
666 }
667 endp->net_end.local_alloc = PORT_ALLOC_STATIC;
668 }
669
Holger Hans Peter Freyther1b8eaf42011-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 Freytherba9c7632011-02-28 14:46:01 +0100672 int rtp_port;
673
Holger Hans Peter Freyther49e170b2011-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 Freyther6f38c062010-02-20 21:21:02 +0100697int mgcp_parse_config(const char *config_file, struct mgcp_config *cfg)
698{
Holger Hans Peter Freyther49e170b2011-02-28 14:37:03 +0100699 int rc;
700 struct mgcp_trunk_config *trunk;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100701
702 g_cfg = cfg;
Harald Welte40152872010-05-16 20:52:23 +0200703 rc = vty_read_config_file(config_file, NULL);
Holger Hans Peter Freyther6f38c062010-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 Freytherbdd3cc32010-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 Freytherba9c7632011-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 Freyther49e170b2011-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 Freyther6f38c062010-02-20 21:21:02 +0100724 return -1;
725 }
726
Holger Hans Peter Freyther49e170b2011-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 Freyther56ac2692010-09-18 02:30:02 +0800732 }
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100733 }
734
Holger Hans Peter Freyther64344522010-08-05 01:28:22 +0800735 return 0;
Holger Hans Peter Freyther6f38c062010-02-20 21:21:02 +0100736}
737