[mgcp] Add a simple mgcp gateway used for the BSC

The python script is a simple call-agent driving the
client. Currently it is sending a AuditEndpoint message
and is printing the result.

The bsc_mgcp.c is a standalone process that will implement
a MGCP Gateway for the MSC. On call handling the Call-Agent
will ask the Gateway to "CreateConnection" and then this
gateway needs to communicate with OpenBSC.

Currently CreateConnection,ModifiyConnection,DeleteConnection
and Endpoint auditing is implemented.

[mgcp] Send RSIP on start and on first receive of any message

Ignore the first request and send a RSIP. We do that because
we might tunnel UDP through some other things and have no direct
way to connect to the call-agent.
Also the transaction is not checked and we ignore the response
from the call-agent, actually we print the '200 ' or any other
value as unhandled...

[mgcp] Print the MGCP command next to the response code

This allows to see which commands were sent by the server

mgcp: Terminate it with a new line

[mgcp] Make number of endpoints static...

For now this is fixed to the number of endpoints as of the GSM

[mgcp] The endpoint names seem to be base 16... use strtoul to parse

Use strtoul to parse the base 16 number from the mgw string.

[mgcp] Log the endpoints as hex numbers...

[mgcp] Only send the RSIP on the first incoming message..

Remove call_agent option (also remove the number from the getopt

[mgcp] Start couting at 1 for the mgcp

[mgcp] Slight attempt to improve the grammar of the strings

[mgcp] Share validation routines between DLCX and MDCX

[mgcp] Remove help for dead config options

[mgcp] Specify a different IN addr in the SDP records

In case of NAT traversal be able to listen on a given
interface (like but claim to receive data
at the beginning of the tunnel.

[mgcp] Fix the static copy of the SDP file

WIP verify out factoring broken..

[mgcp] Introduce VTY to the mgcp for config file parsing...

Parse the MGCP config file via the VTY framework.

[mgcp] Handle SDP parameters through VTY..

Currently the payload type, name and rate can be specified
in the config file.

[mgcp] Add an option to bind all rtp ports early

This can be useful for testing and in deployment to make sure
no runtime resource limit can be hit.

[mgcp] Add some API doc comment

[mgcp] Convert the packets of the example server to ascii

This will allow to easily patch the call id... to run the
server in a loop and make it work with the mediagateway

[mgcp] Assign CI_UNUSED... to be more obvious...

[mgcp] Use DEBUG and not DEBUGPC and specially not printf

Improve the logging a bit in the mgcp

[mgcp] Change the fake server to change the call id

This assume the call-agent will just increment the id
as well.... this is true for our implementation

[mgcp] Generate the transaction id dynamically..

This way wireshark will be more happy about it...

[mgcp] Recognize responses from the network..

This is just recognizing the response code and
then is doing nothing with it. Also change the
script to generate response messages...

[mgcp] Improve debug messages for CRCX/MDCX..

Log on which ports the media gateway is listening
and where the other (server) gateway is located
Holger Hans Peter Freyther 14 years ago
parent b1b0bc2ace
commit f67945f004
  1. 54
  2. 48
  3. 1
  4. 6
  5. 1117
  6. 17

@ -0,0 +1,54 @@
#!/usr/bin/env python
# Simple server for mgcp... send audit, receive response..
import socket, time
rsip_resp = """200 321321332\r\n"""
audit_packet = """AUEP %d 13@mgw MGCP 1.0\r\n"""
crcx_packet = """CRCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n"""
dlcx_packet = """DLCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\n"""
mdcx_packet = """MDCX %d 14@mgw MGCP 1.0\r\nC: 4a84ad5d25f\r\nI: %d\r\nL: p:20, a:GSM-EFR, nt:IN\r\nM: recvonly\r\n\r\nv=0\r\no=- 258696477 0 IN IP4\r\ns=-\r\nc=IN IP4\r\nt=0 0\r\nm=audio 4400 RTP/AVP 127\r\na=rtpmap:127 GSM-EFR/8000/1\r\na=ptime:20\r\na=recvonly\r\nm=image 4402 udptl t38\r\na=T38FaxVersion:0\r\na=T38MaxBitRate:14400\r\n"""
def hexdump(src, length=8):
"""Recipe is from http://code.activestate.com/recipes/142812/"""
result = []
digits = 4 if isinstance(src, unicode) else 2
for i in xrange(0, len(src), length):
s = src[i:i+length]
hexa = b' '.join(["%0*X" % (digits, ord(x)) for x in s])
text = b''.join([x if 0x20 <= ord(x) < 0x7F else b'.' for x in s])
result.append( b"%04X %-*s %s" % (i, length*(digits + 1), hexa, text) )
return b'\n'.join(result)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(("", MGCP_CALLAGENT_PORT))
def send_receive(packet):
server_socket.sendto(packet, ("", MGCP_GATEWAY_PORT))
data, addr = server_socket.recvfrom(4096)
print hexdump(data), addr
except socket.error:
def generate_tid():
import random
return random.randint(0, 65123)
i = 1
while True:
send_receive(crcx_packet % generate_tid() )
send_receive(mdcx_packet % (generate_tid(), i))
send_receive(dlcx_packet % (generate_tid(), i))
i = i + 1

@ -0,0 +1,48 @@
/* A Media Gateway Control Protocol Media Gateway: RFC 3435 */
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* (C) 2009 by on-waves.com
* All Rights Reserved
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
unsigned int rtp_base_port = 4000;
* Calculate the RTP audio port for the given multiplex
* and the direction. This allows a semi static endpoint
* to port calculation removing the need for the BSC
* and the MediaGateway to communicate.
* Port usage explained:
* base + (multiplex * 2) + 0 == local port to wait for network packets
* base + (multiplex * 2) + 1 == local port for rtcp
* The above port will receive packets from the BTS that need
* to be patched and forwarded to the network.
* The above port will receive packets from the network that
* need to be patched and forwarded to the BTS.
* We assume to have a static BTS IP address so we can differentiate
* network and BTS.
int rtp_calculate_port(int multiplex, int base)
return base + (multiplex * 2);

@ -106,6 +106,7 @@ enum node_type {
/* Node which has some commands and prompt string and configuration

@ -1,7 +1,8 @@
INCLUDES = $(all_includes) -I$(top_srcdir)/include
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config isdnsync
sbin_PROGRAMS = bsc_hack bs11_config ipaccess-find ipaccess-config isdnsync \
isdnsync bsc_mgcp
noinst_LIBRARIES = libbsc.a libmsc.a libvty.a libsccp.a
noinst_HEADERS = vty/cardshell.h
@ -32,3 +33,6 @@ ipaccess_config_SOURCES = ipaccess-config.c
ipaccess_config_LDADD = libbsc.a libmsc.a libbsc.a libvty.a -ldl -ldbi $(LIBCRYPT)
isdnsync_SOURCES = isdnsync.c
bsc_mgcp_SOURCES = bsc_mgcp.c msgb.c talloc.c debug.c select.c timer.c
bsc_mgcp_LDADD = libvty.a

File diff suppressed because it is too large Load Diff

@ -0,0 +1,17 @@
! MGCP configuration hand edited
! !
password foo
line vty
no login
local ip
bts ip
bind ip
bind port 2427
bind early 1
rtp base 4000
sdp audio payload number 97
sdp audio payload name GSM-EFR/8000