split off osmo-mgw: remove files, apply build, rename

Add vty and logging previously used from libcommon

Rename libmgcp to libosmo-legacy-mgcp and install.

Use DLMGCP, not DMGCP.

Slim down the public mgcpgw_client API, move all elements not actually used by
current callers to private headers / static c.

Depends: libosmocore I09c587e2d59472cbde852d467d457254746d9e67
Change-Id: I71a0a16ebaaef881c34235849601fc40aa12cfd7
This commit is contained in:
Neels Hofmeyr 2017-07-10 15:07:22 +02:00
parent b6f6c23fa1
commit e9920f24b1
465 changed files with 442 additions and 150603 deletions

View File

@ -17,7 +17,7 @@ SUBDIRS = \
$(NULL)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = openbsc.pc
pkgconfig_DATA = libosmo-legacy-mgcp.pc
BUILT_SOURCES = $(top_srcdir)/.version
EXTRA_DIST = git-version-gen osmoappdesc.py .version

View File

@ -1,5 +1,5 @@
dnl Process this file with autoconf to produce a configure script
AC_INIT([openbsc],
AC_INIT([osmo-mgw],
m4_esyscmd([./git-version-gen .tarball-version]),
[openbsc@lists.osmocom.org])
@ -41,41 +41,7 @@ AC_SUBST(LIBRARY_DL)
PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.9.5)
PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.3.0)
PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl)
PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm >= 0.9.5)
PKG_CHECK_MODULES(LIBOSMOABIS, libosmoabis >= 0.2.0)
PKG_CHECK_MODULES(LIBOSMOGB, libosmogb >= 0.6.4)
PKG_CHECK_MODULES(LIBOSMONETIF, libosmo-netif >= 0.0.1)
PKG_CHECK_MODULES(LIBOSMOSIGTRAN, libosmo-sigtran) # TODO version?
PKG_CHECK_MODULES(LIBCRYPTO, libcrypto >= 0.9.5)
# Enabke/disable the NAT?
AC_ARG_ENABLE([nat], [AS_HELP_STRING([--enable-nat], [Build the BSC NAT. Requires SCCP])],
[osmo_ac_build_nat="$enableval"],[osmo_ac_build_nat="no"])
if test "$osmo_ac_build_nat" = "yes" ; then
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.2)
fi
AM_CONDITIONAL(BUILD_NAT, test "x$osmo_ac_build_nat" = "xyes")
AC_SUBST(osmo_ac_build_nat)
# Enable/disable the BSC?
AC_ARG_ENABLE([osmo-bsc], [AS_HELP_STRING([--enable-osmo-bsc], [Build the Osmo BSC])],
[osmo_ac_build_bsc="$enableval"],[osmo_ac_build_bsc="no"])
if test "$osmo_ac_build_bsc" = "yes" ; then
PKG_CHECK_MODULES(LIBOSMOSCCP, libosmo-sccp >= 0.0.6)
fi
AM_CONDITIONAL(BUILD_BSC, test "x$osmo_ac_build_bsc" = "xyes")
AC_SUBST(osmo_ac_build_bsc)
# Enable/disable smpp support in the msc?
AC_ARG_ENABLE([smpp], [AS_HELP_STRING([--enable-smpp], [Build the SMPP interface])],
[osmo_ac_build_smpp="$enableval"],[osmo_ac_build_smpp="no"])
if test "$osmo_ac_build_smpp" = "yes" ; then
PKG_CHECK_MODULES(LIBSMPP34, libsmpp34 >= 1.12)
AC_DEFINE(BUILD_SMPP, 1, [Define if we want to build SMPP])
fi
AM_CONDITIONAL(BUILD_SMPP, test "x$osmo_ac_build_smpp" = "xyes")
AC_SUBST(osmo_ac_build_smpp)
# Enable/disable transcoding within osmo-bsc_mgcp?
AC_ARG_ENABLE([mgcp-transcoding], [AS_HELP_STRING([--enable-mgcp-transcoding], [Build the MGCP gateway with internal transcoding enabled.])],
@ -93,52 +59,6 @@ fi
AM_CONDITIONAL(BUILD_MGCP_TRANSCODING, test "x$osmo_ac_mgcp_transcoding" = "xyes")
AC_SUBST(osmo_ac_mgcp_transcoding)
# Enable/disable 3G aka IuPS + IuCS support?
AC_ARG_ENABLE([iu], [AS_HELP_STRING([--enable-iu], [Build 3G support, aka IuPS and IuCS interfaces])],
[osmo_ac_iu="$enableval"],[osmo_ac_iu="no"])
if test "x$osmo_ac_iu" = "xyes" ; then
PKG_CHECK_MODULES(LIBASN1C, libasn1c) # TODO version?
PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap) # TODO version?
AC_DEFINE(BUILD_IU, 1, [Define if we want to build IuPS and IuCS interfaces support])
fi
AM_CONDITIONAL(BUILD_IU, test "x$osmo_ac_iu" = "xyes")
AC_SUBST(osmo_ac_iu)
found_libgtp=yes
PKG_CHECK_MODULES(LIBGTP, libgtp >= 0.92, , found_libgtp=no)
AM_CONDITIONAL(HAVE_LIBGTP, test "$found_libgtp" = yes)
AC_SUBST(found_libgtp)
found_libcares=yes
PKG_CHECK_MODULES([LIBCARES], [libcares], [], [found_libcares=no])
AM_CONDITIONAL(HAVE_LIBCARES, test "$found_libcares" = yes)
AC_SUBST(found_libcares)
found_libgtp_and_libcares=no
if test "$found_libgtp" = "yes" -a "$found_libcares" = "yes"; then
found_libgtp_and_libcares=yes
fi
AC_SUBST(found_libgtp_and_libcares)
dnl checks for header files
AC_HEADER_STDC
AC_CHECK_HEADERS(dbi/dbd.h,,AC_MSG_ERROR(DBI library is not installed))
found_pcap=yes
AC_CHECK_HEADERS(pcap/pcap.h,,found_pcap=no)
AM_CONDITIONAL(HAVE_PCAP, test "$found_pcap" = yes)
found_cdk=yes
AC_CHECK_HEADERS(cdk/cdk.h,,found_cdk=no)
AM_CONDITIONAL(HAVE_LIBCDK, test "$found_cdk" = yes)
found_sqlite3=yes
PKG_CHECK_MODULES(SQLITE3, sqlite3, ,found_sqlite3=no)
AM_CONDITIONAL(HAVE_SQLITE3, test "$found_sqlite3" = yes)
AC_SUBST(found_sqlite3)
dnl Checks for typedefs, structures and compiler characteristics
# The following test is taken from WebKit's webkit.m4
@ -173,31 +93,6 @@ if test "$enable_coverage" = "yes"; then
AC_SUBST([COVERAGE_LDFLAGS])
fi
AC_DEFUN([CHECK_TM_INCLUDES_TM_GMTOFF], [
AC_CACHE_CHECK(
[whether struct tm has tm_gmtoff member],
osmo_cv_tm_includes_tm_gmtoff,
[AC_LINK_IFELSE([
AC_LANG_PROGRAM([
#include <time.h>
], [
time_t t = time(NULL);
struct tm* lt = localtime(&t);
int off = lt->tm_gmtoff;
])
],
osmo_cv_tm_includes_tm_gmtoff=yes,
osmo_cv_tm_includes_tm_gmtoff=no
)]
)
if test "x$osmo_cv_tm_includes_tm_gmtoff" = xyes; then
AC_DEFINE(HAVE_TM_GMTOFF_IN_TM, 1,
[Define if struct tm has tm_gmtoff member.])
fi
])
CHECK_TM_INCLUDES_TM_GMTOFF
AC_ARG_ENABLE([vty_tests],
AC_HELP_STRING([--enable-vty-tests],
[Include the VTY/CTRL tests in make check (deprecated)
@ -222,49 +117,16 @@ dnl Generate the output
AM_CONFIG_HEADER(bscconfig.h)
AC_OUTPUT(
openbsc.pc
include/openbsc/Makefile
libosmo-legacy-mgcp.pc
include/Makefile
include/osmocom/Makefile
include/osmocom/legacy_mgcp/Makefile
src/Makefile
src/libtrau/Makefile
src/libbsc/Makefile
src/libmsc/Makefile
src/libvlr/Makefile
src/libmgcp/Makefile
src/libcommon/Makefile
src/libfilter/Makefile
src/libcommon-cs/Makefile
src/osmo-msc/Makefile
src/osmo-bsc/Makefile
src/osmo-bsc_nat/Makefile
src/libosmo-legacy-mgcp/Makefile
src/osmo-bsc_mgcp/Makefile
src/ipaccess/Makefile
src/utils/Makefile
src/gprs/Makefile
tests/Makefile
tests/atlocal
tests/gsm0408/Makefile
tests/channel/Makefile
tests/bsc/Makefile
tests/bsc-nat/Makefile
tests/bsc-nat-trie/Makefile
tests/mgcp/Makefile
tests/gprs/Makefile
tests/gbproxy/Makefile
tests/abis/Makefile
tests/smpp/Makefile
tests/trau/Makefile
tests/sgsn/Makefile
tests/subscr/Makefile
tests/oap/Makefile
tests/gtphub/Makefile
tests/xid/Makefile
tests/sndcp_xid/Makefile
tests/slhc/Makefile
tests/v42bis/Makefile
tests/nanobts_omlattr/Makefile
tests/sms_queue/Makefile
tests/msc_vlr/Makefile
tests/legacy_mgcp/Makefile
doc/Makefile
doc/examples/Makefile
contrib/Makefile

View File

@ -1,170 +0,0 @@
-- Split trace based on SCCP Source
-- There are still bugs to find... bugs bugs bugs... hmm
do
local function init_listener()
print("CREATED LISTENER")
local tap = Listener.new("ip", "sccp && (ip.src == 172.16.1.81 || ip.dst == 172.16.1.81)")
local sccp_type_field = Field.new("sccp.message_type")
local sccp_src_field = Field.new("sccp.slr")
local sccp_dst_field = Field.new("sccp.dlr")
local msg_type_field = Field.new("gsm_a.dtap_msg_mm_type")
local lu_rej_field = Field.new("gsm_a.dtap.rej_cause")
local ip_src_field = Field.new("ip.src")
local ip_dst_field = Field.new("ip.dst")
--
local bssmap_msgtype_field = Field.new("gsm_a.bssmap_msgtype")
-- assignment failure 0x03
--
--
local dtap_cause_field = Field.new("gsm_a_dtap.cause")
local dtap_cc_field = Field.new("gsm_a.dtap_msg_cc_type")
local connections = {}
function check_failure(con)
check_lu_reject(con)
check_disconnect(con)
check_failures(con)
end
-- cipher mode reject
function check_failures(con)
local msgtype = bssmap_msgtype_field()
if not msgtype then
return
end
msgtype = tonumber(msgtype)
if msgtype == 89 then
print("Cipher mode reject")
con[4] = true
elseif msgtype == 0x03 then
print("Assignment failure")
con[4] = true
elseif msgtype == 0x22 then
print("Clear Request... RF failure?")
con[4] = true
end
end
-- check if a DISCONNECT is normal
function check_disconnect(con)
local msg_type = dtap_cc_field()
if not msg_type then
return
end
if tonumber(msg_type) ~= 0x25 then
return
end
local cause = dtap_cause_field()
if not cause then
return
end
cause = tonumber(cause)
if cause ~= 0x10 then
print("DISCONNECT != Normal")
con[4] = true
end
end
-- check if we have a LU Reject
function check_lu_reject(con)
local msg_type = msg_type_field()
if not msg_type then
return
end
msg_type = tonumber(tostring(msg_type))
if msg_type == 0x04 then
print("LU REJECT with " .. tostring(lu_rej_field()))
con[4] = true
end
end
function tap.packet(pinfo,tvb,ip)
local ip_src = tostring(ip_src_field())
local ip_dst = tostring(ip_dst_field())
local sccp_type = tonumber(tostring(sccp_type_field()))
local sccp_src = sccp_src_field()
local sccp_dst = sccp_dst_field()
local con
if sccp_type == 0x01 then
elseif sccp_type == 0x2 then
local src = string.format("%s-%s", ip_src, tostring(sccp_src))
local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
local datestring = os.date("%Y%m%d%H%M%S")
local pcap_name = string.format("alink_trace_%s-%s_%s.pcap", src, dst, datestring)
local dumper = Dumper.new_for_current(pcap_name)
local con = { ip_src, tostring(sccp_src), tostring(sccp_dst), false, dumper, pcap_name }
dumper:dump_current()
connections[src] = con
connections[dst] = con
elseif sccp_type == 0x4 then
-- close a connection... remove it from the list
local src = string.format("%s-%s", ip_src, tostring(sccp_src))
local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
local con = connections[src]
if not con then
return
end
con[5]:dump_current()
con[5]:flush()
-- this causes a crash on unpacted wireshark
con[5]:close()
-- the connection had a failure
if con[4] == true then
local datestring = os.date("%Y%m%d%H%M%S")
local new_name = string.format("alink_failure_%s_%s-%s.pcap", datestring, con[2], con[3])
os.rename(con[6], new_name)
else
os.remove(con[6])
end
-- clear the old connection
connections[src] = nil
connections[dst] = nil
elseif sccp_type == 0x5 then
-- not handled yet... we should verify stuff here...
local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
local con = connections[dst]
if not con then
return
end
con[5]:dump_current()
elseif sccp_type == 0x6 then
local dst = string.format("%s-%s", ip_dst, tostring(sccp_dst))
local con = connections[dst]
if not con then
print("DON'T KNOW THIS CONNECTION for " .. ip_dst)
return
end
con[5]:dump_current()
check_failure(con)
end
end
function tap.draw()
print("DRAW")
end
function tap.reset()
print("RESET")
end
end
init_listener()
end

View File

@ -1 +0,0 @@
Some crazy scripts call testing... and MSC link failure simulation

View File

@ -1,8 +0,0 @@
ABORT BUSY
ABORT 'NO CARRIER'
ABORT 'OK'
'' AT
SAY "Dialing a number\n"
'OK' ATD05660066;

View File

@ -1,11 +0,0 @@
#!/bin/sh
# Evil dial script..
while true;
do
chat -v -f all_dial < /dev/ttyACM0 > /dev/ttyACM0
sleep 5s
chat -v -f hangup < /dev/ttyACM0 > /dev/ttyACM0
sleep 2s
done

View File

@ -1,6 +0,0 @@
#!/bin/sh
sleep 3
echo "enable"
sleep 1
echo "drop bts connection 0 oml"
sleep 1

View File

@ -1,8 +0,0 @@
#!/bin/sh
while true;
do
echo "Going to drop the OML connection"
./drop-oml.sh | telnet 127.0.0.1 4242
sleep 58m
done

View File

@ -1,4 +0,0 @@
TIMEOUT 10
'' ^Z
SAY "Waiting for hangup confirm\n"
'' ATH;

View File

@ -1,8 +0,0 @@
#!/bin/sh
while true;
do
echo "Kill the osmo-bsc"
/usr/bin/kill -s SIGUSR2 `pidof osmo-bsc`
sleep 58s
done

View File

@ -1,120 +0,0 @@
#!/usr/bin/python
# -*- mode: python-mode; py-indent-tabs-mode: nil -*-
"""
/*
* Copyright (C) 2016 sysmocom s.f.m.c. GmbH
*
* 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 3 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* 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.
*/
"""
from optparse import OptionParser
from ipa import Ctrl
import socket
verbose = False
def connect(host, port):
if verbose:
print "Connecting to host %s:%i" % (host, port)
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.setblocking(1)
sck.connect((host, port))
return sck
def do_set_get(sck, var, value = None):
(r, c) = Ctrl().cmd(var, value)
sck.send(c)
answer = Ctrl().rem_header(sck.recv(4096))
return (answer,) + Ctrl().verify(answer, r, var, value)
def set_var(sck, var, val):
(a, _, _) = do_set_get(sck, var, val)
return a
def get_var(sck, var):
(_, _, v) = do_set_get(sck, var)
return v
def _leftovers(sck, fl):
"""
Read outstanding data if any according to flags
"""
try:
data = sck.recv(1024, fl)
except socket.error as (s_errno, strerror):
return False
if len(data) != 0:
tail = data
while True:
(head, tail) = Ctrl().split_combined(tail)
print "Got message:", Ctrl().rem_header(head)
if len(tail) == 0:
break
return True
return False
if __name__ == '__main__':
parser = OptionParser("Usage: %prog [options] var [value]")
parser.add_option("-d", "--host", dest="host",
help="connect to HOST", metavar="HOST")
parser.add_option("-p", "--port", dest="port", type="int",
help="use PORT", metavar="PORT", default=4249)
parser.add_option("-g", "--get", action="store_true",
dest="cmd_get", help="perform GET operation")
parser.add_option("-s", "--set", action="store_true",
dest="cmd_set", help="perform SET operation")
parser.add_option("-v", "--verbose", action="store_true",
dest="verbose", help="be verbose", default=False)
parser.add_option("-m", "--monitor", action="store_true",
dest="monitor", help="monitor the connection for traps", default=False)
(options, args) = parser.parse_args()
verbose = options.verbose
if options.cmd_set and options.cmd_get:
parser.error("Get and set options are mutually exclusive!")
if not (options.cmd_get or options.cmd_set or options.monitor):
parser.error("One of -m, -g, or -s must be set")
if not (options.host):
parser.error("Destination host and port required!")
sock = connect(options.host, options.port)
if options.cmd_set:
if len(args) < 2:
parser.error("Set requires var and value arguments")
_leftovers(sock, socket.MSG_DONTWAIT)
print "Got message:", set_var(sock, args[0], ' '.join(args[1:]))
if options.cmd_get:
if len(args) != 1:
parser.error("Get requires the var argument")
_leftovers(sock, socket.MSG_DONTWAIT)
(a, _, _) = do_set_get(sock, args[0])
print "Got message:", a
if options.monitor:
while True:
if not _leftovers(sock, 0):
print "Connection is gone."
break
sock.close()

View File

@ -1,33 +0,0 @@
#!/usr/bin/env python
import os
f = open("unbalanced")
lines = []
for line in f:
lines.append(line)
filenames = {}
output = []
for line in lines:
if "[0x" in line:
start = line.find("[")
end = line.find("]")
addr = line[start+1:end]
try:
file = filenames[addr]
except KeyError:
r = os.popen("addr2line -fs -e ./bsc_hack %s" % addr)
all = r.read().replace("\n", ",")
file = all
filenames[addr] = file
line = line.replace(addr, file)
output.append(line)
g = open("unbalanced.2", "w")
g.write("".join(output))

View File

@ -1,37 +0,0 @@
#!/usr/bin/env python
#
# Convert ETSI documents to an enum
#
import re, sys
def convert(string):
string = string.strip().replace(" ", "").rjust(8, "0")
var = 0
offset = 7
for char in string:
assert offset >= 0
var = var | (int(char) << offset)
offset = offset - 1
return var
def string(name):
name = name.replace(" ", "_")
name = name.replace('"', "")
name = name.replace('/', '_')
name = name.replace('(', '_')
name = name.replace(')', '_')
return "%s_%s" % (sys.argv[2], name.upper())
file = open(sys.argv[1])
for line in file:
m = re.match(r"[ \t]*(?P<value>[01 ]+)[ ]+(?P<name>[a-zA-Z /0-9()]+)", line[:-1])
if m:
print "\t%s\t\t= %d," % (string(m.groupdict()["name"]), convert(m.groupdict()["value"]))
else:
print line[:-1]

View File

@ -1,147 +0,0 @@
#!/usr/bin/python2
mod_license = '''
/*
* Copyright (C) 2016 sysmocom s.f.m.c. GmbH
*
* 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 3 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* 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.
*/
'''
import sys, argparse, random, logging, tornado.ioloop, tornado.web, tornado.tcpclient, tornado.httpclient, eventsource, bsc_control
from eventsource import listener, request
'''
N. B: this is not an example of building proper REST API or building secure web application.
It's only purpose is to illustrate conversion of Osmocom's Control Interface to web-friendly API.
Exposing this to Internet while connected to production network might lead to all sorts of mischief and mayhem
from NSA' TAO breaking into your network to zombie apocalypse. Do NOT do that.
'''
token = None
stream = None
url = None
'''
Returns json according to following schema - see http://json-schema.org/documentation.html for details:
{
"title": "Ctrl Schema",
"type": "object",
"properties": {
"variable": {
"type": "string"
},
"varlue": {
"type": "string"
}
},
"required": ["interface", "variable", "value"]
}
Example validation from command-line:
json validate --schema-file=schema.json --document-file=data.json
The interface is represented as string because it might look different for IPv4 vs v6.
'''
def read_header(data):
t_length = bsc_control.ipa_ctrl_header(data)
if (t_length):
stream.read_bytes(t_length - 1, callback = read_trap)
else:
print >> sys.stderr, "protocol error: length missing in %s!" % data
@tornado.gen.coroutine
def read_trap(data):
(t, z, v, p) = data.split()
if (t != 'TRAP' or int(z) != 0):
print >> sys.stderr, "protocol error: TRAP != %s or 0! = %d" % (t, int(z))
else:
yield tornado.httpclient.AsyncHTTPClient().fetch(tornado.httpclient.HTTPRequest(url = "%s/%s/%s" % (url, "ping", token),
method = 'POST',
headers = {'Content-Type': 'application/json'},
body = tornado.escape.json_encode({ 'variable' : v, 'value' : p })))
stream.read_bytes(4, callback = read_header)
@tornado.gen.coroutine
def trap_setup(host, port, target_host, target_port, tk):
global stream
global url
global token
token = tk
url = "http://%s:%s/sse" % (host, port)
stream = yield tornado.tcpclient.TCPClient().connect(target_host, target_port)
stream.read_bytes(4, callback = read_header)
def get_v(s, v):
return { 'variable' : v, 'value' : bsc_control.get_var(s, tornado.escape.native_str(v)) }
class CtrlHandler(tornado.web.RequestHandler):
def initialize(self):
self.skt = bsc_control.connect(self.settings['ctrl_host'], self.settings['ctrl_port'])
def get(self, v):
self.write(get_v(self.skt, v))
def post(self):
self.write(get_v(self.skt, self.get_argument("variable")))
class SetCtrl(CtrlHandler):
def get(self, var, val):
bsc_control.set_var(self.skt, tornado.escape.native_str(var), tornado.escape.native_str(val))
super(SetCtrl, self).get(tornado.escape.native_str(var))
def post(self):
bsc_control.set_var(self.skt, tornado.escape.native_str(self.get_argument("variable")), tornado.escape.native_str(self.get_argument("value")))
super(SetCtrl, self).post()
class Slash(tornado.web.RequestHandler):
def get(self):
self.write('<html><head><title>%s</title></head><body>Using Tornado framework v%s'
'<form action="/get" method="POST">'
'<input type="text" name="variable">'
'<input type="submit" value="GET">'
'</form>'
'<form action="/set" method="POST">'
'<input type="text" name="variable">'
'<input type="text" name="value">'
'<input type="submit" value="SET">'
'</form>'
'</body></html>' % ("Osmocom Control Interface Proxy", tornado.version))
if __name__ == '__main__':
p = argparse.ArgumentParser(description='Osmocom Control Interface proxy.')
p.add_argument('-c', '--control-port', type = int, default = 4252, help = "Target Control Interface port")
p.add_argument('-a', '--control-host', default = 'localhost', help = "Target Control Interface adress")
p.add_argument('-b', '--host', default = 'localhost', help = "Adress to bind proxy's web interface")
p.add_argument('-p', '--port', type = int, default = 6969, help = "Port to bind proxy's web interface")
p.add_argument('-d', '--debug', action='store_true', help = "Activate debugging (default off)")
p.add_argument('-t', '--token', default = 'osmocom', help = "Token to be used by SSE client in URL e. g. http://127.0.0.1:8888/poll/osmocom where 'osmocom' is default token value")
p.add_argument('-k', '--keepalive', type = int, default = 5000, help = "Timeout betwwen keepalive messages, in milliseconds, defaults to 5000")
args = p.parse_args()
random.seed()
tornado.netutil.Resolver.configure('tornado.netutil.ThreadedResolver') # Use non-blocking resolver
logging.basicConfig()
application = tornado.web.Application([
(r"/", Slash),
(r"/get", CtrlHandler),
(r"/get/(.*)", CtrlHandler),
(r"/set", SetCtrl),
(r"/set/(.*)/(.*)", SetCtrl),
(r"/sse/(.*)/(.*)", listener.EventSourceHandler, dict(event_class = listener.JSONIdEvent, keepalive = args.keepalive)),
], debug = args.debug, ctrl_host = args.control_host, ctrl_port = args.control_port)
application.listen(address = args.host, port = args.port)
trap_setup(args.host, args.port, application.settings['ctrl_host'], application.settings['ctrl_port'], args.token)
tornado.ioloop.IOLoop.instance().start()

View File

@ -1,58 +0,0 @@
#!/usr/bin/env python
"""
demonstrate a unblock bug on the GB Proxy..
"""
bts_ns_reset = "\x02\x00\x81\x01\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
ns_reset_ack = "\x03\x01\x82\x1f\xe7\x04\x82\x1f\xe7"
bts_ns_unblock = "\x06"
ns_unblock_ack = "\x07"
bts_bvc_reset_0 = "\x00\x00\x00\x00\x22\x04\x82\x00\x00\x07\x81\x03\x3b\x81\x02"
ns_bvc_reset_0_ack = "\x00\x00\x00\x00\x23\x04\x82\x00\x00"
bts_bvc_reset_8167 = "\x00\x00\x00\x00\x22\x04\x82\x1f\xe7\x07\x81\x08\x08\x88\x72\xf4\x80\x10\x1c\x00\x9c\x40"
import socket
socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socket.bind(("0.0.0.0", 0))
socket.setblocking(1)
import sys
port = int(sys.argv[1])
print "Sending data to port: %d" % port
def send_and_receive(packet):
socket.sendto(packet, ("127.0.0.1", port))
try:
data, addr = socket.recvfrom(4096)
except socket.error, e:
print "ERROR", e
import sys
sys.exit(0)
return data
#send stuff once
to_send = [
(bts_ns_reset, ns_reset_ack, "reset ack"),
(bts_ns_unblock, ns_unblock_ack, "unblock ack"),
(bts_bvc_reset_0, ns_bvc_reset_0_ack, "BVCI=0 reset ack"),
]
for (out, inp, type) in to_send:
res = send_and_receive(out)
if res != inp:
print "Failed to get the %s" % type
sys.exit(-1)
import time
time.sleep(3)
res = send_and_receive(bts_bvc_reset_8167)
print "Sent all messages... check wireshark for the last response"

View File

@ -1,78 +0,0 @@
-- Simple LUA script to print the size of BSSGP messages over their type...
do
local ip_bucket = {}
local pdu_types = {}
pdu_types[ 6] = "PAGING"
pdu_types[11] = "SUSPEND"
pdu_types[12] = "SUSPEND-ACK"
pdu_types[32] = "BVC-BLOCK"
pdu_types[33] = "BVC-BLOCK-ACK"
pdu_types[34] = "BVC-RESET"
pdu_types[35] = "BVC-RESET-ACK"
pdu_types[36] = "UNBLOCK"
pdu_types[37] = "UNBLOCK-ACK"
pdu_types[38] = "FLOW-CONTROL-BVC"
pdu_types[39] = "FLOW-CONTROL-BVC-ACK"
pdu_types[40] = "FLOW-CONTROL-MS"
pdu_types[41] = "FLOW-CONTROL-MS-ACK"
pdu_types[44] = "LLC-DISCARDED"
local function init_listener()
-- handle the port as NS over IP
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
-- bssgp filters
local bssgp_pdu_get = Field.new("bssgp.pdu_type")
local udp_length_get = Field.new("udp.length")
local tap = Listener.new("ip", "udp.port == 23000")
function tap.packet(pinfo,tvb,ip)
local pdu = bssgp_pdu_get()
local len = udp_length_get()
-- only handle bssgp, but we also want the IP frame
if not pdu then
return
end
pdu = tostring(pdu)
if tonumber(pdu) == 0 or tonumber(pdu) == 1 then
return
end
local ip_src = tostring(ip.ip_src)
local bssgp_histo = ip_bucket[ip_src]
if not bssgp_histo then
bssgp_histo = {}
ip_bucket[ip_src] = bssgp_histo
end
local key = pdu
local bucket = bssgp_histo[key]
if not bucket then
bucket = {}
bssgp_histo[key] = bucket
end
table.insert(bucket, tostring(len))
print("IP: " .. ip_src .. " PDU: " .. pdu_types[tonumber(pdu)] .. " Length: " .. tostring(len))
end
function tap.draw()
-- well... this will not be called...
-- for ip,bssgp_histo in pairs(dumpers) do
-- print("IP " .. ip)
-- end
end
function tap.reset()
-- well... this will not be called...
end
end
init_listener()
end

View File

@ -1,80 +0,0 @@
-- I count the buffer space needed for LLC PDUs in the worse case and print it
do
local function init_listener()
-- handle the port as NS over IP
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
-- bssgp filters
local bssgp_pdu_get = Field.new("bssgp.pdu_type")
local bssgp_delay_get = Field.new("bssgp.delay_val")
local llcgprs_get = Field.new("llcgprs")
local pdus = nil
print("START...")
local tap = Listener.new("ip", "udp.port == 23000 && bssgp.pdu_type == 0")
function tap.packet(pinfo,tvb,ip)
local pdu = bssgp_pdu_get()
local len = llcgprs_get().len
local delay = bssgp_delay_get()
-- only handle bssgp, but we also want the IP frame
if not pdu then
return
end
if tonumber(tostring(delay)) == 65535 then
pdus = { next = pdus,
len = len,
expires = -1 }
else
local off = tonumber(tostring(delay)) / 100.0
pdus = { next = pdus,
len = len,
expires = pinfo.rel_ts + off }
end
local now_time = tonumber(tostring(pinfo.rel_ts))
local now_size = 0
local l = pdus
local prev = nil
local count = 0
while l do
if now_time < l.expires or l.expires == -1 then
now_size = now_size + l.len
prev = l
l = l.next
count = count + 1
else
-- delete things
if prev == nil then
pdus = nil
l = nil
else
prev.next = l.next
l = l.next
end
end
end
-- print("TOTAL: " .. now_time .. " PDU_SIZE: " .. now_size)
print(now_time .. " " .. now_size / 1024.0 .. " " .. count)
-- print("NOW: " .. tostring(pinfo.rel_ts) .. " Delay: " .. tostring(delay) .. " Length: " .. tostring(len))
end
function tap.draw()
-- well... this will not be called...
-- for ip,bssgp_histo in pairs(dumpers) do
-- print("IP " .. ip)
-- end
print("END")
end
function tap.reset()
-- well... this will not be called...
end
end
init_listener()
end

View File

@ -1,46 +0,0 @@
-- Create a file named by_ip/''ip_addess''.cap with all ip traffic of each ip host. (works for tshark only)
-- Dump files are created for both source and destination hosts
do
local dir = "by_tlli"
local dumpers = {}
local function init_listener()
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
local field_tlli = Field.new("bssgp.tlli")
local tap = Listener.new("ip", "udp.port == 23000")
-- we will be called once for every IP Header.
-- If there's more than one IP header in a given packet we'll dump the packet once per every header
function tap.packet(pinfo,tvb,ip)
local tlli = field_tlli()
if not tlli then
return
end
local tlli_str = tostring(tlli)
tlli_dmp = dumpers[tlli_str]
if not tlli_dmp then
local tlli_hex = string.format("0x%x", tonumber(tlli_str))
print("Creating dump for TLLI " .. tlli_hex)
tlli_dmp = Dumper.new_for_current(dir .. "/" .. tlli_hex .. ".pcap")
dumpers[tlli_str] = tlli_dmp
end
tlli_dmp:dump_current()
tlli_dmp:flush()
end
function tap.draw()
for tlli,dumper in pairs(dumpers) do
dumper:flush()
end
end
function tap.reset()
for tlli,dumper in pairs(dumpers) do
dumper:close()
end
dumpers = {}
end
end
init_listener()
end

View File

@ -1,59 +0,0 @@
-- This script verifies that the N(U) is increasing...
--
do
local nu_state_src = {}
local function init_listener()
-- handle the port as NS over IP
local udp_port_table = DissectorTable.get("udp.port")
local gprs_ns_dis = Dissector.get("gprs_ns")
udp_port_table:add(23000,gprs_ns_dis)
-- we want to look here...
local llc_sapi_get = Field.new("llcgprs.sapib")
local llc_nu_get = Field.new("llcgprs.nu")
local bssgp_tlli_get = Field.new("bssgp.tlli")
local tap = Listener.new("ip", "udp.port == 23000")
function tap.packet(pinfo,tvb,ip)
local llc_sapi = llc_sapi_get()
local llc_nu = llc_nu_get()
local bssgp_tlli = bssgp_tlli_get()
if not llc_sapi or not llc_nu or not bssgp_tlli then
return
end
local ip_src = tostring(ip.ip_src)
local bssgp_tlli = tostring(bssgp_tlli)
local llc_nu = tostring(llc_nu)
local llc_sapi = tostring(llc_sapi)
local src_key = ip_src .. "-" .. bssgp_tlli .. "-" .. llc_sapi
local last_nu = nu_state_src[src_key]
if not last_nu then
-- print("Establishing mapping for " .. src_key)
nu_state_src[src_key] = llc_nu
return
end
local function tohex(number)
return string.format("0x%x", tonumber(number))
end
nu_state_src[src_key] = llc_nu
if tonumber(last_nu) + 1 ~= tonumber(llc_nu) then
print("JUMP in N(U) on TLLI " .. tohex(bssgp_tlli) .. " and SAPI: " .. llc_sapi .. " src: " .. ip_src)
print("\t last: " .. last_nu .. " now: " .. llc_nu)
end
end
function tap.draw()
end
function tap.reset()
end
end
init_listener()
end

View File

@ -1,18 +0,0 @@
-- Remove old data from the database
DELETE FROM Subscriber
WHERE id != 1 AND datetime('now', '-10 days') > updated AND authorized != 1;
DELETE FROM Equipment
WHERE datetime('now', '-10 days') > updated;
DELETE FROM EquipmentWatch
WHERE datetime('now', '-10 days') > updated;
DELETE FROM SMS
WHERE datetime('now', '-10 days') > created;
DELETE FROM VLR
WHERE datetime('now', '-10 days') > updated;
DELETE FROM ApduBlobs
WHERE datetime('now', '-10 days') > created;
DELETE FROM Counters
WHERE datetime('now', '-10 days') > timestamp;
DELETE FROM RateCounters
WHERE datetime('now', '-10 days') > timestamp;
VACUUM;

View File

@ -1,125 +0,0 @@
#!/usr/bin/python2.5
from __future__ import with_statement
from pysqlite2 import dbapi2 as sqlite3
import sys
hlr = sqlite3.connect(sys.argv[1])
web = sqlite3.connect(sys.argv[2])
# switch to autocommit
hlr.isolation_level = None
web.isolation_level = None
hlr.row_factory = sqlite3.Row
web.row_factory = sqlite3.Row
with hlr:
hlr_subscrs = hlr.execute("""
SELECT * FROM Subscriber
""").fetchall()
hlr_tokens = hlr.execute("""
SELECT * FROM AuthToken
""").fetchall()
with web:
web_tokens = web.execute("""
SELECT * FROM reg_tokens
""").fetchall()
web_sms = web.execute("""
SELECT * FROM sms_queue
""").fetchall()
# index by subscr id
hlr_subscrs_by_id = {}
hlr_subscrs_by_ext = {}
hlr_tokens_by_subscr_id = {}
for x in hlr_subscrs:
hlr_subscrs_by_id[x['id']] = x
hlr_subscrs_by_ext[x['extension']] = x
del hlr_subscrs
for x in hlr_tokens:
hlr_tokens_by_subscr_id[x['subscriber_id']] = x
del hlr_tokens
web_tokens_by_subscr_id = {}
for x in web_tokens:
web_tokens_by_subscr_id[x['subscriber_id']] = x
del web_tokens
# remove leftover web_tokens and correct inconsistent fields
with web:
for x in web_tokens_by_subscr_id.values():
subscr = hlr_subscrs_by_id.get(x['subscriber_id'], None)
if subscr is None:
web.execute("""
DELETE FROM reg_tokens WHERE subscriber_id = ?
""", (x['subscriber_id'],))
del web_tokens_by_subscr_id[x['subscriber_id']]
continue
if str(x['imsi']) != str(subscr['imsi']) or \
x['extension'] != subscr['extension'] or \
x['tmsi'] != subscr['tmsi'] or \
x['lac'] != subscr['lac']:
web.execute("""
UPDATE reg_tokens
SET imsi = ?, extension = ?, tmsi = ?, lac = ?
WHERE subscriber_id = ?
""", (str(subscr['imsi']), subscr['extension'],
subscr['tmsi'], subscr['lac'], x['subscriber_id']))
# add missing web_tokens
with web:
for x in hlr_tokens_by_subscr_id.values():
subscr = hlr_subscrs_by_id.get(x['subscriber_id'], None)
if subscr is None:
hlr.execute("""
DELETE FROM AuthToken WHERE subscriber_id = ?
""", (x['subscriber_id'],))
del hlr_tokens_by_subscr_id[x['subscriber_id']]
continue
webtoken = web_tokens_by_subscr_id.get(x['subscriber_id'], None)
if webtoken is None:
web.execute("""
INSERT INTO reg_tokens
(subscriber_id, extension, reg_completed, name, email, lac, imsi, token, tmsi)
VALUES
(?, ?, 0, ?, '', ?, ?, ?, ?)
""", (x['subscriber_id'], subscr['extension'], subscr['name'],
subscr['lac'], str(subscr['imsi']), x['token'], subscr['tmsi']))
# authorize subscribers
with hlr:
for x in web_tokens_by_subscr_id.values():
subscr = hlr_subscrs_by_id.get(x['subscriber_id'], None)
if x['reg_completed'] and not subscr['authorized']:
hlr.execute("""
UPDATE Subscriber
SET authorized = 1
WHERE id = ?
""", (x['subscriber_id'],))
# Sync SMS from web to hlr
with hlr:
for sms in web_sms:
subscr = hlr_subscrs_by_ext.get(sms['receiver_ext'])
if subscr is None:
print '%s not found' % sms['receiver_ext']
continue
hlr.execute("""
INSERT INTO SMS
(created, sender_id, receiver_id, reply_path_req, status_rep_req, protocol_id, data_coding_scheme, ud_hdr_ind, text)
VALUES
(?, 1, ?, 0, 0, 0, 0, 0, ?)
""", (sms['created'], subscr['id'], sms['text']))
with web:
for sms in web_sms:
web.execute("""
DELETE FROM sms_queue WHERE id = ?
""", (sms['id'],))
hlr.close()
web.close()

View File

@ -26,31 +26,22 @@ export LD_LIBRARY_PATH="$inst/lib"
osmo-build-dep.sh libosmo-abis
osmo-build-dep.sh libosmo-netif
osmo-build-dep.sh libosmo-sccp
PARALLEL_MAKE="" osmo-build-dep.sh libsmpp34
osmo-build-dep.sh openggsn
if [ "x$IU" = "x--enable-iu" ]; then
osmo-build-dep.sh libasn1c
#osmo-build-dep.sh asn1c aper-prefix # only needed for make regen in osmo-iuh
osmo-build-dep.sh osmo-iuh
fi
set +x
echo
echo
echo
echo " =============================== osmo-msc ==============================="
echo " =============================== osmo-mgw ==============================="
echo
set -x
cd "$base"
autoreconf --install --force
./configure --enable-osmo-bsc --enable-nat $SMPP $MGCP $IU --enable-vty-tests --enable-external-tests
./configure $MGCP --enable-vty-tests --enable-external-tests
$MAKE $PARALLEL_MAKE
LD_LIBRARY_PATH="$inst/lib" $MAKE check \
|| cat-testlogs.sh
LD_LIBRARY_PATH="$inst/lib" \
DISTCHECK_CONFIGURE_FLAGS="--enable-osmo-bsc --enable-nat $SMPP $MGCP $IU --enable-vty-tests --enable-external-tests" \
DISTCHECK_CONFIGURE_FLAGS="$MGCP --enable-vty-tests --enable-external-tests" \
$MAKE distcheck \
|| cat-testlogs.sh

View File

@ -1,30 +0,0 @@
/* make test_regexp */
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
int main(int argc, char **argv)
{
regex_t reg;
regmatch_t matches[2];
if (argc != 4) {
printf("Invoke with: test_regexp REGEXP REPLACE NR\n");
return -1;
}
if (regcomp(&reg, argv[1], REG_EXTENDED) != 0) {
fprintf(stderr, "Regexp '%s' is not valid.\n", argv[1]);
return -1;
}
if (regexec(&reg, argv[3], 2, matches, 0) == 0 && matches[1].rm_eo != -1)
printf("New Number: %s%s\n", argv[2], &argv[3][matches[1].rm_so]);
else
printf("No match.\n");
regfree(&reg);
return 0;
}

View File

@ -1,65 +0,0 @@
#!/usr/bin/env python2.7
"""
AGPLv3+ 2016 Copyright Holger Hans Peter Freyther
Example of how to connect to the USSD side-channel and how to respond
with a fixed message.
"""
import socket
import struct
ussdSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ussdSocket.connect(('127.0.0.1', 5001))
def send_dt1(dstref, data):
dlen = struct.pack('B', len(data)).encode('hex')
hex = '06' + dstref.encode('hex') + '00' + '01' + dlen + data.encode('hex')
pdata = hex.decode('hex')
out = struct.pack('>HB', len(pdata), 0xfd) + pdata
ussdSocket.send(out)
def send_rel(srcref, dstref):
hex = '04' + dstref.encode('hex') + srcref.encode('hex') + '000100'
pdata = hex.decode('hex')
out = struct.pack('>HB', len(pdata), 0xfd) + pdata
ussdSocket.send(out)
def recv_one():
plen = ussdSocket.recv(3)
(plen,ptype) = struct.unpack(">HB", plen)
data = ussdSocket.recv(plen)
return ptype, data
# Assume this is the ID request
data = ussdSocket.recv(4)
ussdSocket.send("\x00\x08\xfe\x05\x00" + "\x05\x01" + "ussd")
# ^len ^len of tag ... and ignore
# Expect a fake message. see struct ipac_msgt_sccp_state
ptype, data = recv_one()
print("%d %s" % (ptype, data.encode('hex')))
(srcref, dstref, transid, invokeid) = struct.unpack("<3s3sBB", data[1:9])
print("New transID %d invoke %d" % (transid, invokeid))
# Expect a the invocation.. todo.. extract invoke id
ptype, data = recv_one()
print("%d %s" % (ptype, data.encode('hex')))
# Reply with BSSAP + GSM 04.08 + MAP portion
# 00 == invoke id 0f == DCS
res = "01002a9b2a0802e1901c22a220020100301b02013b301604010f041155e7d2f9bc3a41412894991c06a9c9a713"
send_dt1(dstref, res.decode('hex'))
clear = "000420040109"
send_dt1(dstref, clear.decode('hex'))
# should be the clear complete
send_rel(srcref, dstref)
# Give it some time to handle connection shutdown properly
print("Gracefully sleeping")
import time
time.sleep(3)

View File

@ -1,420 +0,0 @@
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -smp disable
-module(gen_rtp_header).
% -mode(compile).
-define(VERSION, "0.1").
-export([main/1]).
-record(rtp_packet,
{
version = 2,
padding = 0,