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:
parent
b6f6c23fa1
commit
e9920f24b1
|
@ -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
|
||||
|
|
150
configure.ac
150
configure.ac
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -1 +0,0 @@
|
|||
Some crazy scripts call testing... and MSC link failure simulation
|
|
@ -1,8 +0,0 @@
|
|||
ABORT BUSY
|
||||
ABORT 'NO CARRIER'
|
||||
ABORT 'OK'
|
||||
|
||||
'' AT
|
||||
SAY "Dialing a number\n"
|
||||
'OK' ATD05660066;
|
||||
|
|
@ -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
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/sh
|
||||
sleep 3
|
||||
echo "enable"
|
||||
sleep 1
|
||||
echo "drop bts connection 0 oml"
|
||||
sleep 1
|
|
@ -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
|
|
@ -1,4 +0,0 @@
|
|||
TIMEOUT 10
|
||||
'' ^Z
|
||||
SAY "Waiting for hangup confirm\n"
|
||||
'' ATH;
|
|
@ -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
|
|
@ -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()
|
|
@ -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))
|
||||
|
||||
|
||||
|
|
@ -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]
|
|
@ -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()
|
|
@ -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"
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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;
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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(®, argv[1], REG_EXTENDED) != 0) {
|
||||
fprintf(stderr, "Regexp '%s' is not valid.\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (regexec(®, 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(®);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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)
|
|
@ -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,
|
||||
marker = 0,
|
||||
payload_type = 0,
|
||||
seqno = 0,
|
||||
timestamp = 0,
|
||||
ssrc = 0,
|
||||
csrcs = [],
|
||||
extension = <<>>,
|
||||
payload = <<>>,
|
||||
realtime
|
||||
}).
|
||||
|
||||
|
||||
main(Args) ->
|
||||
DefaultOpts = [{format, state},
|
||||
{ssrc, 16#11223344},
|
||||
{rate, 8000},
|
||||
{pt, 98}],
|
||||
{PosArgs, Opts} = getopts_checked(Args, DefaultOpts),
|
||||
log(debug, fun (Dev) ->
|
||||
io:format(Dev, "Initial options:~n", []),
|
||||
dump_opts(Dev, Opts),
|
||||
io:format(Dev, "~s: ~p~n", ["Args", PosArgs])
|
||||
end, [], Opts),
|
||||
main(PosArgs, Opts).
|
||||
|
||||
main([First | RemArgs], Opts) ->
|
||||
try
|
||||
F = list_to_integer(First),
|
||||
Format = proplists:get_value(format, Opts, state),
|
||||
PayloadData = proplists:get_value(payload, Opts, undef),
|
||||
InFile = proplists:get_value(file, Opts, undef),
|
||||
|
||||
Payload = case {PayloadData, InFile} of
|
||||
{undef, undef} ->
|
||||
% use default value
|
||||
#rtp_packet{}#rtp_packet.payload;
|
||||
{P, undef} -> P;
|
||||
{_, File} ->
|
||||
log(info, "Loading file '~s'~n", [File], Opts),
|
||||
{ok, InDev} = file:open(File, [read]),
|
||||
DS = [ Pl#rtp_packet.payload || {_T, Pl} <- read_packets(InDev, Opts)],
|
||||
file:close(InDev),
|
||||
log(debug, "File '~s' closed, ~w packets read.~n", [File, length(DS)], Opts),
|
||||
DS
|
||||
end,
|
||||
Dev = standard_io,
|
||||
write_packet_pre(Dev, Format),
|
||||
do_groups(Dev, Payload, F, RemArgs, Opts),
|
||||
write_packet_post(Dev, Format),
|
||||
0
|
||||
catch
|
||||
_:_ ->
|
||||
log(debug, "~p~n", [hd(erlang:get_stacktrace())], Opts),
|
||||
usage(),
|
||||
halt(1)
|
||||
end
|
||||
;
|
||||
|
||||
main(_, _Opts) ->
|
||||
usage(),
|
||||
halt(1).
|
||||
|
||||
%%% group (count + offset) handling %%%
|
||||
|
||||
do_groups(_Dev, _Pl, _F, [], _Opts) ->
|
||||
ok;
|
||||
|
||||
do_groups(Dev, Pl, F, [L], Opts) ->
|
||||
do_groups(Dev, Pl, F, [L, 0], Opts);
|
||||
|
||||
do_groups(Dev, Pl, First, [L, O | Args], Opts) ->
|
||||
Ssrc = proplists:get_value(ssrc, Opts, #rtp_packet.ssrc),
|
||||
PT = proplists:get_value(pt, Opts, #rtp_packet.payload_type),
|
||||
Len = list_to_num(L),
|
||||
Offs = list_to_num(O),
|
||||
log(info, "Starting group: Ssrc=~.16B, PT=~B, First=~B, Len=~B, Offs=~B~n",
|
||||
[Ssrc, PT, First, Len, Offs], Opts),
|
||||
Pkg = #rtp_packet{ssrc = Ssrc, payload_type = PT},
|
||||
Pl2 = write_packets(Dev, Pl, Pkg, First, Len, Offs, Opts),
|
||||
{Args2, Opts2} = getopts_checked(Args, Opts),
|
||||
log(debug, fun (Io) ->
|
||||
io:format(Io, "Changed options:~n", []),
|
||||
dump_opts(Io, Opts2 -- Opts)
|
||||
end, [], Opts),
|
||||
do_groups(Dev, Pl2, First+Len, Args2, Opts2).
|
||||
|
||||
%%% error handling helpers %%%
|
||||
|
||||
getopts_checked(Args, Opts) ->
|
||||
try
|
||||
getopts(Args, Opts)
|
||||
catch
|
||||
C:R ->
|
||||
log(error, "~s~n",
|
||||
[explain_error(C, R, erlang:get_stacktrace(), Opts)], Opts),
|
||||
usage(),
|
||||
halt(1)
|
||||
end.
|
||||
|
||||
explain_error(error, badarg, [{erlang,list_to_integer,[S,B]} | _ ], _Opts) ->
|
||||
io_lib:format("Invalid number '~s' (base ~B)", [S, B]);
|
||||
explain_error(error, badarg, [{erlang,list_to_integer,[S]} | _ ], _Opts) ->
|
||||
io_lib:format("Invalid decimal number '~s'", [S]);
|
||||
explain_error(C, R, [Hd | _ ], _Opts) ->
|
||||
io_lib:format("~p, ~p:~p", [Hd, C, R]);
|
||||
explain_error(_, _, [], _Opts) ->
|
||||
"".
|
||||
|
||||
%%% usage and options %%%
|
||||
|
||||
myname() ->
|
||||
filename:basename(escript:script_name()).
|
||||
|
||||
usage(Text) ->
|
||||
io:format(standard_error, "~s: ~s~n", [myname(), Text]),
|
||||
usage().
|
||||
|
||||
usage() ->
|
||||
io:format(standard_error,
|
||||
"Usage: ~s [Options] Start Count1 Offs1 [[Options] Count2 Offs2 ...]~n",
|
||||
[myname()]).
|
||||
|
||||
show_version() ->
|
||||
io:format(standard_io,
|
||||
"~s ~s~n", [myname(), ?VERSION]).
|
||||
|
||||
show_help() ->
|
||||
io:format(standard_io,
|
||||
"Usage: ~s [Options] Start Count1 Offs1 [[Options] Count2 Offs2 ...]~n~n" ++
|
||||
"Options:~n" ++
|
||||
" -h, --help this text~n" ++
|
||||
" --version show version info~n" ++
|
||||
" -i, --file=FILE reads payload from file (state format by default)~n" ++
|
||||
" -f, --frame-size=N read payload as binary frames of size N instead~n" ++
|
||||
" -p, --payload=HEX set constant payload~n" ++
|
||||
" --verbose=N set verbosity~n" ++
|
||||
" -v increase verbosity~n" ++
|
||||
" --format=state use state format for output (default)~n" ++
|
||||
" -C, --format=c use simple C lines for output~n" ++
|
||||
" --format=carray use a C array for output~n" ++
|
||||
" -s, --ssrc=SSRC set the SSRC~n" ++
|
||||
" -t, --type=N set the payload type~n" ++
|
||||
" -r, --rate=N set the RTP rate [8000]~n" ++
|
||||
" -D, --duration=N set the packet duration in RTP time units [160]~n" ++
|
||||
" -d, --delay=FLOAT add offset to playout timestamp~n" ++
|
||||
"~n" ++
|
||||
"Arguments:~n" ++
|
||||
" Start initial packet (sequence) number~n" ++
|
||||
" Count number of packets~n" ++
|
||||
" Offs timestamp offset (in RTP units)~n" ++
|
||||
"", [myname()]).
|
||||
|
||||
getopts([ "--file=" ++ File | R], Opts) ->
|
||||
getopts(R, [{file, File} | Opts]);
|
||||
getopts([ "-i" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--file", T, R, Opts);
|
||||
getopts([ "--frame-size=" ++ N | R], Opts) ->
|
||||
Size = list_to_integer(N),
|
||||
getopts(R, [{frame_size, Size}, {in_format, bin} | Opts]);
|
||||
getopts([ "-f" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--frame-size", T, R, Opts);
|
||||
getopts([ "--duration=" ++ N | R], Opts) ->
|
||||
Duration = list_to_integer(N),
|
||||
getopts(R, [{duration, Duration} | Opts]);
|
||||
getopts([ "-D" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--duration", T, R, Opts);
|
||||
getopts([ "--rate=" ++ N | R], Opts) ->
|
||||
Rate = list_to_integer(N),
|
||||
getopts(R, [{rate, Rate} | Opts]);
|
||||
getopts([ "-r" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--rate", T, R, Opts);
|
||||
getopts([ "--version" | _], _Opts) ->
|
||||
show_version(),
|
||||
halt(0);
|
||||
getopts([ "--help" | _], _Opts) ->
|
||||
show_help(),
|
||||
halt(0);
|
||||
getopts([ "-h" ++ T | R], Opts) ->
|
||||
getopts_alias_no_arg("--help", T, R, Opts);
|
||||
getopts([ "--verbose=" ++ V | R], Opts) ->
|
||||
Verbose = list_to_integer(V),
|
||||
getopts(R, [{verbose, Verbose} | Opts]);
|
||||
getopts([ "-v" ++ T | R], Opts) ->
|
||||
Verbose = proplists:get_value(verbose, Opts, 0),
|
||||
getopts_short_no_arg(T, R, [ {verbose, Verbose+1} | Opts]);
|
||||
getopts([ "--format=state" | R], Opts) ->
|
||||
getopts(R, [{format, state} | Opts]);
|
||||
getopts([ "--format=c" | R], Opts) ->
|
||||
getopts(R, [{format, c} | Opts]);
|
||||
getopts([ "-C" ++ T | R], Opts) ->
|
||||
getopts_alias_no_arg("--format=c", T, R, Opts);
|
||||
getopts([ "--format=carray" | R], Opts) ->
|
||||
getopts(R, [{format, carray} | Opts]);
|
||||
getopts([ "--payload=" ++ Hex | R], Opts) ->
|
||||
getopts(R, [{payload, hex_to_bin(Hex)} | Opts]);
|
||||
getopts([ "--ssrc=" ++ Num | R], Opts) ->
|
||||
getopts(R, [{ssrc, list_to_num(Num)} | Opts]);
|
||||
getopts([ "-s" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--ssrc", T, R, Opts);
|
||||
getopts([ "--type=" ++ Num | R], Opts) ->
|
||||
getopts(R, [{pt, list_to_num(Num)} | Opts]);
|
||||
getopts([ "-t" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--type", T, R, Opts);
|
||||
getopts([ "--delay=" ++ Num | R], Opts) ->
|
||||
getopts(R, [{delay, list_to_float(Num)} | Opts]);
|
||||
getopts([ "-d" ++ T | R], Opts) ->
|
||||
getopts_alias_arg("--delay", T, R, Opts);
|
||||
|
||||
% parsing helpers
|
||||
getopts([ "--" | R], Opts) ->
|
||||
{R, normalize_opts(Opts)};
|
||||
getopts([ O = "--" ++ _ | _], _Opts) ->
|
||||
usage("Invalid option: " ++ O),
|
||||
halt(1);
|
||||
getopts([ [ $-, C | _] | _], _Opts) when C < $0; C > $9 ->
|
||||
usage("Invalid option: -" ++ [C]),
|
||||
halt(1);
|
||||
|
||||
getopts(R, Opts) ->
|
||||
{R, normalize_opts(Opts)}.
|
||||
|
||||
getopts_short_no_arg([], R, Opts) -> getopts(R, Opts);
|
||||
getopts_short_no_arg(T, R, Opts) -> getopts([ "-" ++ T | R], Opts).
|
||||
|
||||
getopts_alias_no_arg(A, [], R, Opts) -> getopts([A | R], Opts);
|
||||
getopts_alias_no_arg(A, T, R, Opts) -> getopts([A, "-" ++ T | R], Opts).
|
||||
|
||||
getopts_alias_arg(A, [], [T | R], Opts) -> getopts([A ++ "=" ++ T | R], Opts);
|
||||
getopts_alias_arg(A, T, R, Opts) -> getopts([A ++ "=" ++ T | R], Opts).
|
||||
|
||||
normalize_opts(Opts) ->
|
||||
[ proplists:lookup(E, Opts) || E <- proplists:get_keys(Opts) ].
|
||||
|
||||
%%% conversions %%%
|
||||
|
||||
bin_to_hex(Bin) -> [hd(integer_to_list(N,16)) || <<N:4>> <= Bin].
|
||||
hex_to_bin(Hex) -> << <<(list_to_integer([Nib],16)):4>> || Nib <- Hex>>.
|
||||
|
||||
list_to_num("-" ++ Str) -> -list_to_num(Str);
|
||||
list_to_num("0x" ++ Str) -> list_to_integer(Str, 16);
|
||||
list_to_num("0b" ++ Str) -> list_to_integer(Str, 2);
|
||||
list_to_num(Str = [ $0 | _ ]) -> list_to_integer(Str, 8);
|
||||
list_to_num(Str) -> list_to_integer(Str, 10).
|
||||
|
||||
%%% dumping data %%%
|
||||
|
||||
dump_opts(Dev, Opts) ->
|
||||
dump_opts2(Dev, Opts, proplists:get_keys(Opts)).
|
||||
|
||||
dump_opts2(Dev, Opts, [OptName | R]) ->
|
||||
io:format(Dev, " ~-10s: ~p~n",
|
||||
[OptName, proplists:get_value(OptName, Opts)]),
|
||||
dump_opts2(Dev, Opts, R);
|
||||
dump_opts2(_Dev, _Opts, []) -> ok.
|
||||
|
||||
%%% logging %%%
|
||||
|
||||
log(L, Fmt, Args, Opts) when is_list(Opts) ->
|
||||
log(L, Fmt, Args, proplists:get_value(verbose, Opts, 0), Opts).
|
||||
|
||||
log(debug, Fmt, Args, V, Opts) when V > 2 -> log2("DEBUG", Fmt, Args, Opts);
|
||||
log(info, Fmt, Args, V, Opts) when V > 1 -> log2("INFO", Fmt, Args, Opts);
|
||||
log(notice, Fmt, Args, V, Opts) when V > 0 -> log2("NOTICE", Fmt, Args, Opts);
|
||||
log(warn, Fmt, Args, _V, Opts) -> log2("WARNING", Fmt, Args, Opts);
|
||||
log(error, Fmt, Args, _V, Opts) -> log2("ERROR", Fmt, Args, Opts);
|
||||
|
||||
log(Lvl, Fmt, Args, V, Opts) when V >= Lvl -> log2("", Fmt, Args, Opts);
|
||||
|
||||
log(_, _, _, _i, _) -> ok.
|
||||
|
||||
log2(Type, Fmt, Args, _Opts) when is_list(Fmt) ->
|
||||
io:format(standard_error, "~s: " ++ Fmt, [Type | Args]);
|
||||
log2("", Fmt, Args, _Opts) when is_list(Fmt) ->
|
||||
io:format(standard_error, Fmt, Args);
|
||||
log2(_Type, Fun, _Args, _Opts) when is_function(Fun, 1) ->
|
||||
Fun(standard_error).
|
||||
|
||||
%%% RTP packets %%%
|
||||
|
||||
make_rtp_packet(P = #rtp_packet{version = 2}) ->
|
||||
<< (P#rtp_packet.version):2,
|
||||
0:1, % P
|
||||
0:1, % X
|
||||
0:4, % CC
|
||||
(P#rtp_packet.marker):1,
|
||||
(P#rtp_packet.payload_type):7,
|
||||
(P#rtp_packet.seqno):16,
|
||||
(P#rtp_packet.timestamp):32,
|
||||
(P#rtp_packet.ssrc):32,
|
||||
(P#rtp_packet.payload)/bytes
|
||||
>>.
|
||||
|
||||
parse_rtp_packet(
|
||||
<< 2:2, % Version 2
|
||||
0:1, % P (not supported yet)
|
||||
0:1, % X (not supported yet)
|
||||
0:4, % CC (not supported yet)
|
||||
M:1,
|
||||
PT:7,
|
||||
SeqNo: 16,
|
||||
TS:32,
|
||||
Ssrc:32,
|
||||
Payload/bytes >>) ->
|
||||
#rtp_packet{
|
||||
version = 0,
|
||||
marker = M,
|
||||
payload_type = PT,
|
||||
seqno = SeqNo,
|
||||
timestamp = TS,
|
||||
ssrc = Ssrc,
|
||||
payload = Payload}.
|
||||
|
||||
%%% payload generation %%%
|
||||
|
||||
next_payload(F) when is_function(F) ->
|
||||
{F(), F};
|
||||
next_payload({F, D}) when is_function(F) ->
|
||||
{P, D2} = F(D),
|
||||
{P, {F, D2}};
|
||||
next_payload([P | R]) ->
|
||||
{P, R};
|
||||
next_payload([]) ->
|
||||
undef;
|
||||
next_payload(Bin = <<_/bytes>>) ->
|
||||
{Bin, Bin}.
|
||||
|
||||
%%% real writing work %%%
|
||||
|
||||
write_packets(_Dev, DS, _P, _F, 0, _O, _Opts) ->
|
||||
DS;
|
||||
write_packets(Dev, DataSource, P = #rtp_packet{}, F, L, O, Opts) ->
|
||||
Format = proplists:get_value(format, Opts, state),
|
||||
Ptime = proplists:get_value(duration, Opts, 160),
|
||||
Delay = proplists:get_value(delay, Opts, 0),
|
||||
Rate = proplists:get_value(rate, Opts, 8000),
|
||||
case next_payload(DataSource) of
|
||||
{Payload, DataSource2} ->
|
||||
write_packet(Dev, Ptime * F / Rate + Delay,
|
||||
P#rtp_packet{seqno = F, timestamp = F*Ptime+O,
|
||||
payload = Payload},
|
||||
Format),
|
||||
write_packets(Dev, DataSource2, P, F+1, L-1, O, Opts);
|
||||
Other -> Other
|
||||
end.
|
||||
|
||||
write_packet(Dev, Time, P = #rtp_packet{}, Format) ->
|
||||
Bin = make_rtp_packet(P),
|
||||
|
||||
write_packet_line(Dev, Time, P, Bin, Format).
|
||||
|
||||
write_packet_pre(Dev, carray) ->
|
||||
io:format(Dev,
|
||||
"struct {float t; int len; char *data;} packets[] = {~n", []);
|
||||
|
||||
write_packet_pre(_Dev, _) -> ok.
|
||||
|
||||
write_packet_post(Dev, carray) ->
|
||||
io:format(Dev, "};~n", []);
|
||||
|
||||
write_packet_post(_Dev, _) -> ok.
|
||||
|
||||
write_packet_line(Dev, Time, _P, Bin, state) ->
|
||||
io:format(Dev, "~f ~s~n", [Time, bin_to_hex(Bin)]);
|
||||
|
||||
write_packet_line(Dev, Time, #rtp_packet{seqno = N, timestamp = TS}, Bin, c) ->
|
||||
ByteList = [ [ $0, $x | integer_to_list(Byte, 16) ] || <<Byte:8>> <= Bin ],
|
||||
ByteStr = string:join(ByteList, ", "),
|
||||
io:format(Dev, "/* time=~f, SeqNo=~B, TS=~B */ {~s}~n", [Time, N, TS, ByteStr]);
|
||||
|
||||
write_packet_line(Dev, Time, #rtp_packet{seqno = N, timestamp = TS}, Bin, carray) ->
|
||||
io:format(Dev, " /* RTP: SeqNo=~B, TS=~B */~n", [N, TS]),
|
||||
io:format(Dev, " {~f, ~B, \"", [Time, size(Bin)]),
|
||||
[ io:format(Dev, "\\x~2.16.0B", [Byte]) || <<Byte:8>> <= Bin ],
|
||||
io:format(Dev, "\"},~n", []).
|
||||
|
||||
%%% real reading work %%%
|
||||
|
||||
read_packets(Dev, Opts) ->
|
||||
Format = proplists:get_value(in_format, Opts, state),
|
||||
|
||||
read_packets(Dev, Opts, Format).
|
||||
|
||||
read_packets(Dev, Opts, Format) ->
|
||||
case read_packet(Dev, Opts, Format) of
|
||||
eof -> [];
|
||||
Tuple -> [Tuple | read_packets(Dev, Opts, Format)]
|
||||
end.
|
||||
|
||||
read_packet(Dev, Opts, bin) ->
|
||||
Size = proplists:get_value(frame_size, Opts),
|
||||
case file:read(Dev, Size) of
|
||||
{ok, Data} -> {0, #rtp_packet{payload = iolist_to_binary(Data)}};
|
||||
eof -> eof
|
||||
end;
|
||||
read_packet(Dev, _Opts, Format) ->
|
||||
case read_packet_line(Dev, Format) of
|
||||
{Time, Bin} -> {Time, parse_rtp_packet(Bin)};
|
||||
eof -> eof
|
||||
end.
|
||||
|
||||
read_packet_line(Dev, state) ->
|
||||
case io:fread(Dev, "", "~f ~s") of
|
||||
{ok, [Time, Hex]} -> {Time, hex_to_bin(Hex)};
|
||||
eof -> eof
|
||||
end.
|
|
@ -1,21 +0,0 @@
|
|||
"
|
||||
Simple UDP replay from the state files
|
||||
"
|
||||
|
||||
PackageLoader fileInPackage: #Sockets.
|
||||
FileStream fileIn: 'rtp_replay_shared.st'.
|
||||
|
||||
|
||||
Eval [
|
||||
| replay file host dport |
|
||||
|
||||
file := Smalltalk arguments at: 1 ifAbsent: [ 'rtpstream.state' ].
|
||||
host := Smalltalk arguments at: 2 ifAbsent: [ '127.0.0.1' ].
|
||||
dport := (Smalltalk arguments at: 3 ifAbsent: [ '4000' ]) asInteger.
|
||||
sport := (Smalltalk arguments at: 4 ifAbsent: [ '0' ]) asInteger.
|
||||
|
||||
replay := RTPReplay on: file fromPort: sport.
|
||||
|
||||
Transcript nextPutAll: 'Going to stream now'; nl.
|
||||
replay streamAudio: host port: dport.
|
||||
]
|
|
@ -1,118 +0,0 @@
|
|||
"
|
||||
Simple UDP replay from the state files
|
||||
"
|
||||
|
||||
PackageLoader fileInPackage: #Sockets.
|
||||
|
||||
Object subclass: SDPUtils [
|
||||
"Look into using PetitParser."
|
||||
SDPUtils class >> findPort: aSDP [
|
||||
aSDP linesDo: [:line |
|
||||
(line startsWith: 'm=audio ') ifTrue: [
|
||||
| stream |
|
||||
stream := line readStream
|
||||
skip: 'm=audio ' size;
|
||||
yourself.
|
||||
^ Number readFrom: stream.
|
||||
]
|
||||
].
|
||||
|
||||
^ self error: 'Not found'.
|
||||
]
|
||||
|
||||
SDPUtils class >> findHost: aSDP [
|
||||
aSDP linesDo: [:line |
|
||||
(line startsWith: 'c=IN IP4 ') ifTrue: [
|
||||
| stream |
|
||||
^ stream := line readStream
|
||||
skip: 'c=IN IP4 ' size;
|
||||
upToEnd.
|
||||
]
|
||||
].
|
||||
|
||||
^ self error: 'Not found'.
|
||||
]
|
||||
]
|
||||
|
||||
Object subclass: RTPReplay [
|
||||
| filename socket |
|
||||
RTPReplay class >> on: aFile [
|
||||
^ self new
|
||||
initialize;
|
||||
file: aFile; yourself
|
||||
]
|
||||
|
||||
RTPReplay class >> on: aFile fromPort: aPort [
|
||||
^ self new
|
||||
initialize: aPort;
|
||||
file: aFile; yourself
|
||||
]
|
||||
|
||||
initialize [
|
||||
self initialize: 0.
|
||||
]
|
||||
|
||||
initialize: aPort [
|
||||
socket := Sockets.DatagramSocket local: '0.0.0.0' port: aPort.
|
||||
]
|
||||
|
||||
file: aFile [
|
||||
filename := aFile
|
||||
]
|
||||
|
||||
localPort [
|
||||
^ socket port
|
||||
]
|
||||
|
||||
streamAudio: aHost port: aPort [
|
||||
| file last_time last_image udp_send dest |
|
||||
|
||||
last_time := nil.
|
||||
last_image := nil.
|
||||
file := FileStream open: filename mode: #read.
|
||||
|
||||
"Send the payload"
|
||||
dest := Sockets.SocketAddress byName: aHost.
|
||||
udp_send := [:payload | | datagram |
|
||||
datagram := Sockets.Datagram data: payload contents address: dest port: aPort.
|
||||
socket nextPut: datagram
|
||||
].
|
||||
|
||||
[file atEnd] whileFalse: [
|
||||
| lineStream time data now_image |
|
||||
lineStream := file nextLine readStream.
|
||||
|
||||
"Read the time, skip the blank, parse the data"
|
||||
time := Number readFrom: lineStream.
|
||||
lineStream skip: 1.
|
||||
|
||||
data := WriteStream on: (ByteArray new: 30).
|
||||
[lineStream atEnd] whileFalse: [
|
||||
| hex |
|
||||
hex := lineStream next: 2.
|
||||
data nextPut: (Number readFrom: hex readStream radix: 16).
|
||||
].
|
||||
|
||||
last_time isNil
|
||||
ifTrue: [
|
||||
"First time, send it right now"
|
||||
last_time := time.
|
||||
last_image := Time millisecondClockValue.
|
||||
udp_send value: data.
|
||||
]
|
||||
ifFalse: [
|
||||
| wait_image new_image_time |
|
||||
|
||||
"How long to wait?"
|
||||
wait_image := last_image + ((time - last_time) * 1000).
|
||||
[ wait_image > Time millisecondClockValue ]
|
||||
whileTrue: [Processor yield].
|
||||
|
||||
udp_send value: data.
|
||||
last_time := time.
|
||||
last_image := wait_image.
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
"""
|
||||
Create a SIP connection and then stream...
|
||||
"""
|
||||
|
||||
PackageLoader
|
||||
fileInPackage: #OsmoSIP.
|
||||
|
||||
"Load for the replay code"
|
||||
FileStream fileIn: 'rtp_replay_shared.st'.
|
||||
|
||||
|
||||
Osmo.SIPCall subclass: StreamCall [
|
||||
| sem stream |
|
||||
|
||||
createCall: aSDP [
|
||||
| sdp |
|
||||
stream := RTPReplay on: 'rtp_ssrc6976010.240.240.1_to_10.240.240.50.state'.
|
||||
sdp := aSDP % {stream localPort}.
|
||||
^ super createCall: sdp.
|
||||
]
|
||||
|
||||
sem: aSemaphore [
|
||||
sem := aSemaphore
|
||||
]
|
||||
|
||||
sessionNew [
|
||||
| host port |
|
||||
Transcript nextPutAll: 'The call has started'; nl.
|
||||
Transcript nextPutAll: sdp_result; nl.
|
||||
|
||||
host := SDPUtils findHost: sdp_result.
|
||||
port := SDPUtils findPort: sdp_result.
|
||||
|
||||
[
|
||||
stream streamAudio: host port: port.
|
||||
Transcript nextPutAll: 'Streaming has finished.'; nl.
|
||||
] fork.
|
||||
]
|
||||
|
||||
sessionFailed [
|
||||
sem signal
|
||||
]
|
||||
|
||||
sessionEnd [
|
||||
sem signal
|
||||
]
|
||||
]
|
||||
|
||||
Eval [
|
||||
| transport agent call sem sdp_fr sdp_amr |
|
||||
|
||||
|
||||
sdp_fr := (WriteStream on: String new)
|
||||
nextPutAll: 'v=0'; cr; nl;
|
||||
nextPutAll: 'o=twinkle 1739517580 1043400482 IN IP4 127.0.0.1'; cr; nl;
|
||||
nextPutAll: 's=-'; cr; nl;
|
||||
nextPutAll: 'c=IN IP4 127.0.0.1'; cr; nl;
|
||||
nextPutAll: 't=0 0'; cr; nl;
|
||||
nextPutAll: 'm=audio %1 RTP/AVP 0 101'; cr; nl;
|
||||
nextPutAll: 'a=rtpmap:0 PCMU/8000'; cr; nl;
|
||||
nextPutAll: 'a=rtpmap:101 telephone-event/8000'; cr; nl;
|
||||
nextPutAll: 'a=fmtp:101 0-15'; cr; nl;
|
||||
nextPutAll: 'a=ptime:20'; cr; nl;
|
||||
contents.
|
||||
|
||||
sem := Semaphore new.
|
||||
transport := Osmo.SIPUdpTransport
|
||||
startOn: '0.0.0.0' port: 5066.
|
||||
agent := Osmo.SIPUserAgent createOn: transport.
|
||||
transport start.
|
||||
|
||||
call := (StreamCall
|
||||
fromUser: 'sip:1000@sip.zecke.osmocom.org'
|
||||
host: '127.0.0.1'
|
||||
port: 5060
|
||||
to: 'sip:123456@127.0.0.1'
|
||||
on: agent)
|
||||
sem: sem; yourself.
|
||||
|
||||
call createCall: sdp_fr.
|
||||
|
||||
|
||||
"Wait for the stream to have ended"
|
||||
sem wait.
|
||||
|
||||
(Delay forSeconds: 4) wait.
|
||||
]
|
|
@ -1,28 +0,0 @@
|
|||
print("Ni hao")
|
||||
|
||||
|
||||
do
|
||||
local tap = Listener.new("ip", "rtp")
|
||||
local rtp_ssrc = Field.new("rtp.ssrc")
|
||||
local frame_time = Field.new("frame.time_relative")
|
||||
local rtp = Field.new("rtp")
|
||||
|
||||
function tap.packet(pinfo, tvb, ip)
|
||||
local ip_src, ip_dst = tostring(ip.ip_src), tostring(ip.ip_dst)
|
||||
local rtp_data = rtp()
|
||||
local filename = "rtp_ssrc" .. rtp_ssrc() "_src_" .. ip_src .. "_to_" .. ip_dst .. ".state"
|
||||
local f = io.open(filename, "a")
|
||||
|
||||
f:write(tostring(frame_time()) .. " ")
|
||||
f:write(tostring(rtp_data.value))
|
||||
f:write("\n")
|
||||
f:close()
|
||||
end
|
||||
|
||||
function tap.draw()
|
||||
print("DRAW")
|
||||
end
|
||||
function tap.reset()
|
||||
print("RESET")
|
||||
end
|
||||
end
|
|
@ -1,66 +0,0 @@
|
|||
"I create output for some simple SQL statements for the HLR db"
|
||||
|
||||
|
||||
Eval [
|
||||
|
||||
"Create tables if they don't exist"
|
||||
Transcript show: 'CREATE TABLE SMS (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created TIMESTAMP NOT NULL,
|
||||
sent TIMESTAMP,
|
||||
sender_id INTEGER NOT NULL,
|
||||
receiver_id INTEGER NOT NULL,
|
||||
deliver_attempts INTEGER NOT NULL DEFAULT 0,
|
||||
valid_until TIMESTAMP,
|
||||
reply_path_req INTEGER NOT NULL,
|
||||
status_rep_req INTEGER NOT NULL,
|
||||
protocol_id INTEGER NOT NULL,
|
||||
data_coding_scheme INTEGER NOT NULL,
|
||||
ud_hdr_ind INTEGER NOT NULL,
|
||||
dest_addr TEXT,
|
||||
user_data BLOB,
|
||||
header BLOB,
|
||||
text TEXT);'; nl;
|
||||
show: 'CREATE TABLE Subscriber (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created TIMESTAMP NOT NULL,
|
||||
updated TIMESTAMP NOT NULL,
|
||||
imsi NUMERIC UNIQUE NOT NULL,
|
||||
name TEXT,
|
||||
extension TEXT UNIQUE,
|
||||
authorized INTEGER NOT NULL DEFAULT 0,
|
||||
tmsi TEXT UNIQUE,
|
||||
lac INTEGER NOT NULL DEFAULT 0);'; nl.
|
||||
|
||||
"Create some dummy subscribers"
|
||||
num_sub := 1000.
|
||||
num_sms := 30.
|
||||
lac := 1.
|
||||
|
||||
Transcript show: 'BEGIN;'; nl.
|
||||
|
||||
1 to: num_sub do: [:each |
|
||||
Transcript show: 'INSERT INTO Subscriber
|
||||
(imsi, created, updated, authorized, lac, extension)
|
||||
VALUES
|
||||
(%1, datetime(''now''), datetime(''now''), 1, %2, %3);' %
|
||||
{(274090000000000 + each). lac. each}; nl.
|
||||
].
|
||||
|
||||
1 to: num_sms do: [:sms |
|
||||
1 to: num_sub do: [:sub |
|
||||
Transcript show: 'INSERT INTO SMS
|
||||
(created, sender_id, receiver_id, valid_until,
|
||||
reply_path_req, status_rep_req, protocol_id,
|
||||
data_coding_scheme, ud_hdr_ind, dest_addr,
|
||||
text) VALUES
|
||||
(datetime(''now''), 1, %1, ''2222-2-2'',
|
||||
0, 0, 0,
|
||||
0, 0, ''123456'',
|
||||
''abc'');' % {sub}; nl.
|
||||
]
|
||||
].
|
||||
|
||||
Transcript show: 'COMMIT;'; nl.
|
||||
|
||||
]
|
|
@ -1,10 +0,0 @@
|
|||
"Query for one SMS"
|
||||
|
||||
Eval [
|
||||
1 to: 100 do: [:each |
|
||||
Transcript show: 'SELECT SMS.* FROM SMS
|
||||
JOIN Subscriber ON SMS.receiver_id = Subscriber.id
|
||||
WHERE SMS.id >= 1 AND SMS.sent IS NULL AND Subscriber.lac > 0
|
||||
ORDER BY SMS.id LIMIT 1;'; nl.
|
||||
].
|
||||
]
|
|
@ -1,5 +0,0 @@
|
|||
probe process("/usr/lib/libsqlite3.so.0.8.6").function("sqlite3_get_table")
|
||||
{
|
||||
a = user_string($zSql);
|
||||
printf("sqlite3_get_table called '%s'\n", a);
|
||||
}
|
188
contrib/soap.py
188
contrib/soap.py
|
@ -1,188 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- 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.
|
||||
*/
|
||||
"""
|
||||
|
||||
__version__ = "v0.7" # bump this on every non-trivial change
|
||||
|
||||
from twisted.internet import defer, reactor
|
||||
from twisted_ipa import CTRL, IPAFactory, __version__ as twisted_ipa_version
|
||||
from ipa import Ctrl
|
||||
from treq import post, collect
|
||||
from suds.client import Client
|
||||
from functools import partial
|
||||
from distutils.version import StrictVersion as V # FIXME: use NormalizedVersion from PEP-386 when available
|
||||
import argparse, datetime, signal, sys, os, logging, logging.handlers
|
||||
|
||||
# we don't support older versions of TwistedIPA module
|
||||
assert V(twisted_ipa_version) > V('0.4')
|
||||
|
||||
# keys from OpenBSC openbsc/src/libbsc/bsc_rf_ctrl.c, values SOAP-specific
|
||||
oper = { 'inoperational' : 0, 'operational' : 1 }
|
||||
admin = { 'locked' : 0, 'unlocked' : 1 }
|
||||
policy = { 'off' : 0, 'on' : 1, 'grace' : 2, 'unknown' : 3 }
|
||||
|
||||
# keys from OpenBSC openbsc/src/libbsc/bsc_vty.c
|
||||
fix = { 'invalid' : 0, 'fix2d' : 1, 'fix3d' : 1 } # SOAP server treats it as boolean but expects int
|
||||
|
||||
|
||||
def handle_reply(p, f, log, r):
|
||||
"""
|
||||
Reply handler: takes function p to process raw SOAP server reply r, function f to run for each command and verbosity flag v
|
||||
"""
|
||||
repl = p(r) # result is expected to have both commands[] array and error string (could be None)
|
||||
bsc_id = repl.commands[0].split()[0].split('.')[3] # we expect 1st command to have net.0.bsc.666.bts.2.trx.1 location prefix format
|
||||
log.info("Received SOAP response for BSC %s with %d commands, error status: %s" % (bsc_id, len(repl.commands), repl.error))
|
||||
log.debug("BSC %s commands: %s" % (bsc_id, repl.commands))
|
||||
for t in repl.commands: # Process OpenBscCommands format from .wsdl
|
||||
(_, m) = Ctrl().cmd(*t.split())
|
||||
f(m)
|
||||
|
||||
|
||||
class Trap(CTRL):
|
||||
"""
|
||||
TRAP handler (agnostic to factory's client object)
|
||||
"""
|
||||
def ctrl_TRAP(self, data, op_id, v):
|
||||
"""
|
||||
Parse CTRL TRAP and dispatch to appropriate handler after normalization
|
||||
"""
|
||||
(l, r) = v.split()
|
||||
loc = l.split('.')
|
||||
t_type = loc[-1]
|
||||
p = partial(lambda a, i: a[i] if len(a) > i else None, loc) # parse helper
|
||||
method = getattr(self, 'handle_' + t_type.replace('-', ''), lambda: "Unhandled %s trap" % t_type)
|
||||
method(p(1), p(3), p(5), p(7), r) # we expect net.0.bsc.666.bts.2.trx.1 format for trap prefix
|
||||
|
||||
def ctrl_SET_REPLY(self, data, _, v):
|
||||
"""
|
||||
Debug log for replies to our commands
|
||||
"""
|
||||
self.factory.log.debug('SET REPLY %s' % v)
|
||||
|
||||
def ctrl_ERROR(self, data, op_id, v):
|
||||
"""
|
||||
We want to know if smth went wrong
|
||||
"""
|
||||
self.factory.log.debug('CTRL ERROR [%s] %s' % (op_id, v))
|
||||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
Logging wrapper, calling super() is necessary not to break reconnection logic
|
||||
"""
|
||||
self.factory.log.info("Connected to CTRL@%s:%d" % (self.factory.host, self.factory.port))
|
||||
super(CTRL, self).connectionMade()
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def handle_locationstate(self, net, bsc, bts, trx, data):
|
||||
"""
|
||||
Handle location-state TRAP: parse trap content, build SOAP context and use treq's routines to post it while setting up async handlers
|
||||
"""
|
||||
(ts, fx, lat, lon, height, opr, adm, pol, mcc, mnc) = data.split(',')
|
||||
tstamp = datetime.datetime.fromtimestamp(float(ts)).isoformat()
|
||||
self.factory.log.debug('location-state@%s.%s.%s.%s (%s) [%s/%s] => %s' % (net, bsc, bts, trx, tstamp, mcc, mnc, data))
|
||||
ctx = self.factory.client.registerSiteLocation(bsc, float(lon), float(lat), fix.get(fx, 0), tstamp, oper.get(opr, 2), admin.get(adm, 2), policy.get(pol, 3))
|
||||
d = post(self.factory.location, ctx.envelope)
|
||||
d.addCallback(collect, partial(handle_reply, ctx.process_reply, self.transport.write, self.factory.log)) # treq's collect helper is handy to get all reply content at once using closure on ctx
|
||||
d.addErrback(lambda e, bsc: self.factory.log.critical("HTTP POST error %s while trying to register BSC %s" % (e, bsc)), bsc) # handle HTTP errors
|
||||
# Ensure that we run only limited number of requests in parallel:
|
||||
yield self.factory.semaphore.acquire()
|
||||
yield d # we end up here only if semaphore is available which means it's ok to fire the request without exceeding the limit
|
||||
self.factory.semaphore.release()
|
||||
|
||||
def handle_notificationrejectionv1(self, net, bsc, bts, trx, data):
|
||||
"""
|
||||
Handle notification-rejection-v1 TRAP: just an example to show how more message types can be handled
|
||||
"""
|
||||
self.factory.log.debug('notification-rejection-v1@bsc-id %s => %s' % (bsc, data))
|
||||
|
||||
|
||||
class TrapFactory(IPAFactory):
|
||||
"""
|
||||
Store SOAP client object so TRAP handler can use it for requests
|
||||
"""
|
||||
location = None
|
||||
log = None
|
||||
semaphore = None
|
||||
client = None
|
||||
host = None
|
||||
port = None
|
||||
def __init__(self, host, port, proto, semaphore, log, wsdl=None, location=None):
|
||||
self.host = host # for logging only,
|
||||
self.port = port # seems to be no way to get it from ReconnectingClientFactory
|
||||
self.log = log
|
||||
self.semaphore = semaphore
|
||||
soap = Client(wsdl, location=location, nosend=True) # make async SOAP client
|
||||
self.location = location.encode() if location else soap.wsdl.services[0].ports[0].location # necessary for dispatching HTTP POST via treq
|
||||
self.client = soap.service
|
||||
level = self.log.getEffectiveLevel()
|
||||
self.log.setLevel(logging.WARNING) # we do not need excessive debug from lower levels
|
||||
super(TrapFactory, self).__init__(proto, self.log)
|
||||
self.log.setLevel(level)
|
||||
self.log.debug("Using IPA %s, SUDS client: %s" % (Ctrl.version, soap))
|
||||
|
||||
|
||||
def reloader(path, script, log, dbg1, dbg2, signum, _):
|
||||
"""
|
||||
Signal handler: we have to use execl() because twisted's reactor is not restartable due to some bug in twisted implementation
|
||||
"""
|
||||
log.info("Received Signal %d - restarting..." % signum)
|
||||
if signum == signal.SIGUSR1 and dbg1 not in sys.argv and dbg2 not in sys.argv:
|
||||
sys.argv.append(dbg1) # enforce debug
|
||||
if signum == signal.SIGUSR2 and (dbg1 in sys.argv or dbg2 in sys.argv): # disable debug
|
||||
if dbg1 in sys.argv:
|
||||
sys.argv.remove(dbg1)
|
||||
if dbg2 in sys.argv:
|
||||
sys.argv.remove(dbg2)
|
||||
os.execl(path, script, *sys.argv[1:])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
p = argparse.ArgumentParser(description='Proxy between given SOAP service and Osmocom CTRL protocol.')
|
||||
p.add_argument('-v', '--version', action='version', version=("%(prog)s " + __version__))
|
||||
p.add_argument('-p', '--port', type=int, default=4250, help="Port to use for CTRL interface, defaults to 4250")
|
||||
p.add_argument('-c', '--ctrl', default='localhost', help="Adress to use for CTRL interface, defaults to localhost")
|
||||
p.add_argument('-w', '--wsdl', required=True, help="WSDL URL for SOAP")
|
||||
p.add_argument('-n', '--num', type=int, default=5, help="Max number of concurrent HTTP requests to SOAP server")
|
||||
p.add_argument('-d', '--debug', action='store_true', help="Enable debug log")
|
||||
p.add_argument('-o', '--output', action='store_true', help="Log to STDOUT in addition to SYSLOG")
|
||||
p.add_argument('-l', '--location', help="Override location found in WSDL file (don't use unless you know what you're doing)")
|
||||
args = p.parse_args()
|
||||
|
||||
log = logging.getLogger('CTRL2SOAP')
|
||||
if args.debug:
|
||||
log.setLevel(logging.DEBUG)
|
||||
else:
|
||||
log.setLevel(logging.INFO)
|
||||
log.addHandler(logging.handlers.SysLogHandler('/dev/log'))
|
||||
if args.output:
|
||||
log.addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
reboot = partial(reloader, os.path.abspath(__file__), os.path.basename(__file__), log, '-d', '--debug') # keep in sync with add_argument() call above
|
||||
signal.signal(signal.SIGHUP, reboot)
|
||||
signal.signal(signal.SIGQUIT, reboot)
|
||||
signal.signal(signal.SIGUSR1, reboot) # restart and enabled debug output
|
||||
signal.signal(signal.SIGUSR2, reboot) # restart and disable debug output
|
||||
|
||||
log.info("SOAP proxy %s starting with PID %d ..." % (__version__, os.getpid()))
|
||||
reactor.connectTCP(args.ctrl, args.port, TrapFactory(args.ctrl, args.port, Trap, defer.DeferredSemaphore(args.num), log, args.wsdl, args.location))
|
||||
reactor.run()
|
|
@ -1,12 +0,0 @@
|
|||
[Unit]
|
||||
Description=OpenBSC BSC
|
||||
Wants=osmo-bsc-mgcp.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-bsc -c /etc/osmocom/osmo-bsc.cfg -s
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,12 +0,0 @@
|
|||
[Unit]
|
||||
Description=Osmocom Gb proxy
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/osmo-gbproxy -c /etc/osmocom/osmo-gbproxy.cfg
|
||||
Restart=always
|
||||
RestartSec=2
|
||||
RestartPreventExitStatus=1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,14 +0,0 @@
|
|||
[Unit]
|
||||
Description=Osmocom Mobile Switching Center (MSC)
|
||||
Wants=osmo-hlr.service
|
||||
After=osmo-hlr.service
|
||||
After=osmo-hnbgw.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-msc -c /etc/osmocom/osmo-msc.cfg
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,11 +0,0 @@
|
|||
[Unit]
|
||||
Description=OpenBSC Network In the Box (NITB)
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-nitb -s -C -c /etc/osmocom/osmo-nitb.cfg -l /var/lib/osmocom/hlr.sqlite3
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,14 +0,0 @@
|
|||
[Unit]
|
||||
Description=OpenBSC SGSN
|
||||
Wants=osmo-hlr.service
|
||||
After=osmo-hlr.service
|
||||
After=osmo-hnbgw.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
Restart=always
|
||||
ExecStart=/usr/bin/osmo-sgsn -c /etc/osmocom/osmo-sgsn.cfg
|
||||
RestartSec=2
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
OBJS = testconv_main.o
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -O0 -ggdb -Wall
|
||||
LDFLAGS =
|
||||
CPPFLAGS = -I../.. -I../../include $(shell pkg-config --cflags libosmocore) $(shell pkg-config --cflags libbcg729)
|
||||
LIBS = ../../src/libmgcp/libmgcp.a ../../src/libcommon/libcommon.a $(shell pkg-config --libs libosmocore) $(shell pkg-config --libs libbcg729) -lgsm -lrt
|
||||
|
||||
testconv: $(OBJS)
|
||||
$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
|
||||
|
||||
testconv_main.o: testconv_main.c
|
||||
|
||||
$(OBJS):
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
|
|
@ -1,133 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/core/application.h>
|
||||
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/mgcp.h>
|
||||
#include <openbsc/mgcp_internal.h>
|
||||
|
||||
#include "bscconfig.h"
|
||||
#ifndef BUILD_MGCP_TRANSCODING
|
||||
#error "Requires MGCP transcoding enabled (see --enable-mgcp-transcoding)"
|
||||
#endif
|
||||
|
||||
#include "openbsc/mgcp_transcode.h"
|
||||
|
||||
static int audio_name_to_type(const char *name)
|
||||
{
|
||||
if (!strcasecmp(name, "gsm"))
|
||||
return 3;
|
||||
#ifdef HAVE_BCG729
|
||||
else if (!strcasecmp(name, "g729"))
|
||||
return 18;
|
||||
#endif
|
||||
else if (!strcasecmp(name, "pcma"))
|
||||
return 8;
|
||||
else if (!strcasecmp(name, "l16"))
|
||||
return 11;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mgcp_get_trans_frame_size(void *state_, int nsamples, int dst);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char buf[4096] = {0x80, 0};
|
||||
int cc, rc;
|
||||
struct mgcp_rtp_end *dst_end;
|
||||
struct mgcp_rtp_end *src_end;
|
||||
struct mgcp_trunk_config tcfg = {{0}};
|
||||
struct mgcp_endpoint endp = {0};
|
||||
struct mgcp_process_rtp_state *state;
|
||||
int in_size;
|
||||
int in_samples = 160;
|
||||
int out_samples = 0;
|
||||
uint32_t ts = 0;
|
||||
uint16_t seq = 0;
|
||||
|
||||
osmo_init_logging(&log_info);
|
||||
|
||||
tcfg.endpoints = &endp;
|
||||
tcfg.number_endpoints = 1;
|
||||
endp.tcfg = &tcfg;
|
||||
mgcp_initialize_endp(&endp);
|
||||
|
||||
dst_end = &endp.bts_end;
|
||||
src_end = &endp.net_end;
|
||||
|
||||
if (argc <= 2)
|
||||
errx(1, "Usage: {gsm|g729|pcma|l16} {gsm|g729|pcma|l16} [SPP]");
|
||||
|
||||
if ((src_end->codec.payload_type = audio_name_to_type(argv[1])) == -1)
|
||||
errx(1, "invalid input format '%s'", argv[1]);
|
||||
if ((dst_end->codec.payload_type = audio_name_to_type(argv[2])) == -1)
|
||||
errx(1, "invalid output format '%s'", argv[2]);
|
||||
if (argc > 3)
|
||||
out_samples = atoi(argv[3]);
|
||||
|
||||
if (out_samples) {
|
||||
dst_end->codec.frame_duration_den = dst_end->codec.rate;
|
||||
dst_end->codec.frame_duration_num = out_samples;
|
||||
dst_end->frames_per_packet = 1;
|
||||
}
|
||||
|
||||
rc = mgcp_transcoding_setup(&endp, dst_end, src_end);
|
||||
if (rc < 0)
|
||||
errx(1, "setup failed: %s", strerror(-rc));
|
||||
|
||||
state = dst_end->rtp_process_data;
|
||||
OSMO_ASSERT(state != NULL);
|
||||
|
||||
in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0);
|
||||
OSMO_ASSERT(sizeof(buf) >= in_size + 12);
|
||||
|
||||
buf[1] = src_end->codec.payload_type;
|
||||
*(uint16_t*)(buf+2) = htons(1);
|
||||
*(uint32_t*)(buf+4) = htonl(0);
|
||||
*(uint32_t*)(buf+8) = htonl(0xaabbccdd);
|
||||
|
||||
while ((cc = read(0, buf + 12, in_size))) {
|
||||
int cont;
|
||||
int len;
|
||||
|
||||
if (cc != in_size)
|
||||
err(1, "read");
|
||||
|
||||
*(uint16_t*)(buf+2) = htonl(seq);
|
||||
*(uint32_t*)(buf+4) = htonl(ts);
|
||||
|
||||
seq += 1;
|
||||
ts += in_samples;
|
||||
|
||||
cc += 12; /* include RTP header */
|
||||
|
||||
len = cc;
|
||||
|
||||
do {
|
||||
cont = mgcp_transcoding_process_rtp(&endp, dst_end,
|
||||
buf, &len, sizeof(buf));
|
||||
if (cont == -EAGAIN) {
|
||||
fprintf(stderr, "Got EAGAIN\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (cont < 0)
|
||||
errx(1, "processing failed: %s", strerror(-cont));
|
||||
|
||||
len -= 12; /* ignore RTP header */
|
||||
|
||||
if (write(1, buf + 12, len) != len)
|
||||
err(1, "write");
|
||||
|
||||
len = cont;
|
||||
} while (len > 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,384 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- 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.
|
||||
*/
|
||||
"""
|
||||
|
||||
__version__ = "0.6" # bump this on every non-trivial change
|
||||
|
||||
from ipa import Ctrl, IPA
|
||||
from twisted.internet.protocol import ReconnectingClientFactory
|
||||
from twisted.internet import reactor
|
||||
from twisted.protocols import basic
|
||||
import argparse, logging
|
||||
|
||||
class IPACommon(basic.Int16StringReceiver):
|
||||
"""
|
||||
Generic IPA protocol handler: include some routines for simpler subprotocols.
|
||||
It's not intended as full implementation of all subprotocols, rather common ground and example code.
|
||||
"""
|
||||
def dbg(self, line):
|
||||
"""
|
||||
Debug print helper
|
||||
"""
|
||||
self.factory.log.debug(line)
|
||||
|
||||
def osmo_CTRL(self, data):
|
||||
"""
|
||||
OSMO CTRL protocol
|
||||
Placeholder, see corresponding derived class
|
||||
"""
|
||||
pass
|
||||
|
||||
def osmo_MGCP(self, data):
|
||||
"""
|
||||
OSMO MGCP extension
|
||||
"""
|
||||
self.dbg('OSMO MGCP received %s' % data)
|
||||
|
||||
def osmo_LAC(self, data):
|
||||
"""
|
||||
OSMO LAC extension
|
||||
"""
|
||||
self.dbg('OSMO LAC received %s' % data)
|
||||
|
||||
def osmo_SMSC(self, data):
|
||||
"""
|
||||
OSMO SMSC extension
|
||||
"""
|
||||
self.dbg('OSMO SMSC received %s' % data)
|
||||
|
||||
def osmo_ORC(self, data):
|
||||
"""
|
||||
OSMO ORC extension
|
||||
"""
|
||||
self.dbg('OSMO ORC received %s' % data)
|
||||
|
||||
def osmo_GSUP(self, data):
|
||||
"""
|
||||
OSMO GSUP extension
|
||||
"""
|
||||
self.dbg('OSMO GSUP received %s' % data)
|
||||
|
||||
def osmo_OAP(self, data):
|
||||
"""
|
||||
OSMO OAP extension
|
||||
"""
|
||||
self.dbg('OSMO OAP received %s' % data)
|
||||
|
||||
def osmo_UNKNOWN(self, data):
|
||||
"""
|
||||
OSMO defaul extension handler
|
||||
"""
|
||||
self.dbg('OSMO unknown extension received %s' % data)
|
||||
|
||||
def handle_RSL(self, data, proto, extension):
|
||||
"""
|
||||
RSL protocol handler
|
||||
"""
|
||||
self.dbg('IPA RSL received message with extension %s' % extension)
|
||||
|
||||
def handle_CCM(self, data, proto, msgt):
|
||||
"""
|
||||
CCM (IPA Connection Management)
|
||||
Placeholder, see corresponding derived class
|
||||
"""
|
||||
pass
|
||||
|
||||
def handle_SCCP(self, data, proto, extension):
|
||||
"""
|
||||
SCCP protocol handler
|
||||
"""
|
||||
self.dbg('IPA SCCP received message with extension %s' % extension)
|
||||
|
||||
def handle_OML(self, data, proto, extension):
|
||||
"""
|
||||
OML protocol handler
|
||||
"""
|
||||
self.dbg('IPA OML received message with extension %s' % extension)
|
||||
|
||||
def handle_OSMO(self, data, proto, extension):
|
||||
"""
|
||||
Dispatcher point for OSMO subprotocols based on extension name, lambda default should never happen
|
||||
"""
|
||||
method = getattr(self, 'osmo_' + IPA().ext(extension), lambda: "extension dispatch failure")
|
||||
method(data)
|
||||
|
||||
def handle_MGCP(self, data, proto, extension):
|
||||
"""
|
||||
MGCP protocol handler
|
||||
"""
|
||||
self.dbg('IPA MGCP received message with attribute %s' % extension)
|
||||
|
||||
def handle_UNKNOWN(self, data, proto, extension):
|
||||
"""
|
||||
Default protocol handler
|
||||
"""
|
||||
self.dbg('IPA received message for %s (%s) protocol with attribute %s' % (IPA().proto(proto), proto, extension))
|
||||
|
||||
def process_chunk(self, data):
|
||||
"""
|
||||
Generic message dispatcher for IPA (sub)protocols based on protocol name, lambda default should never happen
|
||||
"""
|
||||
(_, proto, extension, content) = IPA().del_header(data)
|
||||
if content is not None:
|
||||
self.dbg('IPA received %s::%s [%d/%d] %s' % (IPA().proto(proto), IPA().ext_name(proto, extension), len(data), len(content), content))
|
||||
method = getattr(self, 'handle_' + IPA().proto(proto), lambda: "protocol dispatch failure")
|
||||
method(content, proto, extension)
|
||||
|
||||
def dataReceived(self, data):
|
||||
"""
|
||||
Override for dataReceived from Int16StringReceiver because of inherently incompatible interpretation of length
|
||||
If default handler is used than we would always get off-by-1 error (Int16StringReceiver use equivalent of l + 2)
|
||||
"""
|
||||
if len(data):
|
||||
(head, tail) = IPA().split_combined(data)
|
||||
self.process_chunk(head)
|
||||
self.dataReceived(tail)
|
||||
|
||||
def connectionMade(self):
|
||||
"""
|
||||
We have to resetDelay() here to drop internal state to default values to make reconnection logic work
|
||||
Make sure to call this via super() if overriding to keep reconnection logic intact
|
||||
"""
|
||||
addr = self.transport.getPeer()
|
||||
self.dbg('IPA connected to %s:%d peer' % (addr.host, addr.port))
|
||||
self.factory.resetDelay()
|
||||
|
||||
|
||||
class CCM(IPACommon):
|
||||
"""
|
||||
Implementation of CCM protocol for IPA multiplex
|
||||
"""
|
||||
def ack(self):
|
||||
self.transport.write(IPA().id_ack())
|
||||
|
||||
def ping(self):
|
||||
self.transport.write(IPA().ping())
|
||||
|
||||
def pong(self):
|
||||
self.transport.write(IPA().pong())
|
||||
|
||||
def handle_CCM(self, data, proto, msgt):
|
||||
"""
|
||||
CCM (IPA Connection Management)
|
||||
Only basic logic necessary for tests is implemented (ping-pong, id ack etc)
|
||||
"""
|
||||
if msgt == IPA.MSGT['ID_GET']:
|
||||
self.transport.getHandle().sendall(IPA().id_resp(self.factory.ccm_id))
|
||||
# if we call
|
||||
# self.transport.write(IPA().id_resp(self.factory.test_id))
|
||||
# instead, than we would have to also call
|
||||
# reactor.callLater(1, self.ack)
|
||||
# instead of self.ack()
|
||||
# otherwise the writes will be glued together - hence the necessity for ugly hack with 1s timeout
|
||||
# Note: this still might work depending on the IPA implementation details on the other side
|
||||
self.ack()
|
||||
# schedule PING in 4s
|
||||
reactor.callLater(4, self.ping)
|
||||
if msgt == IPA.MSGT['PING']:
|
||||
self.pong()
|
||||
|
||||
|
||||
class CTRL(IPACommon):
|
||||
"""
|
||||
Implementation of Osmocom control protocol for IPA multiplex
|
||||
"""
|
||||
def ctrl_SET(self, data, op_id, v):
|
||||
"""
|
||||
Handle CTRL SET command
|
||||
"""
|
||||
self.dbg('CTRL SET [%s] %s' % (op_id, v))
|
||||
|
||||
def ctrl_SET_REPLY(self, data, op_id, v):
|
||||
"""
|
||||
Handle CTRL SET reply
|
||||
"""
|
||||
self.dbg('CTRL SET REPLY [%s] %s' % (op_id, v))
|
||||
|
||||
def ctrl_GET(self, data, op_id, v):
|
||||
"""
|
||||
Handle CTRL GET command
|
||||
"""
|
||||
self.dbg('CTRL GET [%s] %s' % (op_id, v))
|
||||
|
||||
def ctrl_GET_REPLY(self, data, op_id, v):
|
||||
"""
|
||||
Handle CTRL GET reply
|
||||
"""
|
||||
self.dbg('CTRL GET REPLY [%s] %s' % (op_id, v))
|
||||
|
||||
def ctrl_TRAP(self, data, op_id, v):
|
||||
"""
|
||||
Handle CTRL TRAP command
|
||||
"""
|
||||
self.dbg('CTRL TRAP [%s] %s' % (op_id, v))
|
||||
|
||||
def ctrl_ERROR(self, data, op_id, v):
|
||||
"""
|
||||
Handle CTRL ERROR reply
|
||||
"""
|
||||
self.dbg('CTRL ERROR [%s] %s' % (op_id, v))
|
||||
|
||||
def osmo_CTRL(self, data):
|
||||
"""
|
||||
OSMO CTRL message dispatcher, lambda default should never happen
|
||||
For basic tests only, appropriate handling routines should be replaced: see CtrlServer for example
|
||||
"""
|
||||
self.dbg('OSMO CTRL received %s::%s' % Ctrl().parse(data.decode('utf-8')))
|
||||
(cmd, op_id, v) = data.decode('utf-8').split(' ', 2)
|
||||
method = getattr(self, 'ctrl_' + cmd, lambda: "CTRL unknown command")
|
||||
method(data, op_id, v)
|
||||
|
||||
|
||||
class IPAServer(CCM):
|
||||
"""
|
||||
Test implementation of IPA server
|
||||
Demonstrate CCM opearation by overriding necessary bits from CCM
|
||||
"""
|
||||
def connectionMade(self):
|
||||
"""
|
||||
Keep reconnection logic working by calling routine from CCM
|
||||
Initiate CCM upon connection
|
||||
"""
|
||||
addr = self.transport.getPeer()
|
||||
self.factory.log.info('IPA server: connection from %s:%d client' % (addr.host, addr.port))
|
||||
super(IPAServer, self).connectionMade()
|
||||
self.transport.write(IPA().id_get())
|
||||
|
||||
|
||||
class CtrlServer(CTRL):
|
||||
"""
|
||||
Test implementation of CTRL server
|
||||
Demonstarte CTRL handling by overriding simpler routines from CTRL
|
||||
"""
|
||||
def connectionMade(self):
|
||||
"""
|
||||
Keep reconnection logic working by calling routine from CTRL
|
||||
Send TRAP upon connection
|
||||
Note: we can't use sendString() because of it's incompatibility with IPA interpretation of length prefix
|
||||
"""
|
||||
addr = self.transport.getPeer()
|
||||
self.factory.log.info('CTRL server: connection from %s:%d client' % (addr.host, addr.port))
|
||||
super(CtrlServer, self).connectionMade()
|
||||
self.transport.write(Ctrl().trap('LOL', 'what'))
|
||||
self.transport.write(Ctrl().trap('rulez', 'XXX'))
|
||||
|
||||
def reply(self, r):
|
||||
self.transport.write(Ctrl().add_header(r))
|
||||
|
||||
def ctrl_SET(self, data, op_id, v):
|
||||
"""
|
||||
CTRL SET command: always succeed
|
||||
"""
|
||||
self.dbg('SET [%s] %s' % (op_id, v))
|
||||
self.reply('SET_REPLY %s %s' % (op_id, v))
|
||||
|
||||
def ctrl_GET(self, data, op_id, v):
|
||||
"""
|
||||
CTRL GET command: always fail
|
||||
"""
|
||||
self.dbg('GET [%s] %s' % (op_id, v))
|
||||
self.reply('ERROR %s No variable found' % op_id)
|
||||
|
||||
|
||||
class IPAFactory(ReconnectingClientFactory):
|
||||
"""
|
||||
Generic IPA Client Factory which can be used to store state for various subprotocols and manage connections
|
||||
Note: so far we do not really need separate Factory for acting as a server due to protocol simplicity
|
||||
"""
|
||||
protocol = IPACommon
|
||||
log = None
|
||||
ccm_id = IPA().identity(unit=b'1515/0/1', mac=b'b0:0b:fa:ce:de:ad:be:ef', utype=b'sysmoBTS', name=b'StingRay', location=b'hell', sw=IPA.version.encode('utf-8'))
|
||||
|
||||
def __init__(self, proto=None, log=None, ccm_id=None):
|
||||
if proto:
|
||||
self.protocol = proto
|
||||
if ccm_id:
|
||||
self.ccm_id = ccm_id
|
||||
if log:
|
||||
self.log = log
|
||||
else:
|
||||
self.log = logging.getLogger('IPAFactory')
|
||||
self.log.setLevel(logging.CRITICAL)
|
||||
self.log.addHandler(logging.NullHandler)
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
"""
|
||||
Only necessary for as debugging aid - if we can somehow set parent's class noisy attribute then we can omit this method
|
||||
"""
|
||||
self.log.warning('IPAFactory connection failed: %s' % reason.getErrorMessage())
|
||||
ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
"""
|
||||
Only necessary for as debugging aid - if we can somehow set parent's class noisy attribute then we can omit this method
|
||||
"""
|
||||
self.log.warning('IPAFactory connection lost: %s' % reason.getErrorMessage())
|
||||
ReconnectingClientFactory.clientConnectionLost(self, connector, reason)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
p = argparse.ArgumentParser("Twisted IPA (module v%s) app" % IPA.version)
|
||||
p.add_argument('-v', '--version', action='version', version="%(prog)s v" + __version__)
|
||||
p.add_argument('-p', '--port', type=int, default=4250, help="Port to use for CTRL interface")
|
||||
p.add_argument('-d', '--host', default='localhost', help="Adress to use for CTRL interface")
|
||||
cs = p.add_mutually_exclusive_group()
|
||||
cs.add_argument("-c", "--client", action='store_true', help="asume client role")
|
||||
cs.add_argument("-s", "--server", action='store_true', help="asume server role")
|
||||
ic = p.add_mutually_exclusive_group()
|
||||
ic.add_argument("--ipa", action='store_true', help="use IPA protocol")
|
||||
ic.add_argument("--ctrl", action='store_true', help="use CTRL protocol")
|
||||
args = p.parse_args()
|
||||
test = False
|
||||
|
||||
log = logging.getLogger('TwistedIPA')
|
||||
log.setLevel(logging.DEBUG)
|
||||
log.addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
if args.ctrl:
|
||||
if args.client:
|
||||
# Start osmo-bsc to receive TRAP messages when osmo-bts-* connects to it
|
||||
print('CTRL client, connecting to %s:%d' % (args.host, args.port))
|
||||
reactor.connectTCP(args.host, args.port, IPAFactory(CTRL, log))
|
||||
test = True
|
||||
if args.server:
|
||||
# Use bsc_control.py to issue set/get commands
|
||||
print('CTRL server, listening on port %d' % args.port)
|
||||
reactor.listenTCP(args.port, IPAFactory(CtrlServer, log))
|
||||
test = True
|
||||
if args.ipa:
|
||||
if args.client:
|
||||
# Start osmo-nitb which would initiate A-bis/IP session
|
||||
print('IPA client, connecting to %s ports %d and %d' % (args.host, IPA.TCP_PORT_OML, IPA.TCP_PORT_RSL))
|
||||
reactor.connectTCP(args.host, IPA.TCP_PORT_OML, IPAFactory(CCM, log))
|
||||
reactor.connectTCP(args.host, IPA.TCP_PORT_RSL, IPAFactory(CCM, log))
|
||||
test = True
|
||||
if args.server:
|
||||
# Start osmo-bts-* which would attempt to connect to us
|
||||
print('IPA server, listening on ports %d and %d' % (IPA.TCP_PORT_OML, IPA.TCP_PORT_RSL))
|
||||
reactor.listenTCP(IPA.TCP_PORT_RSL, IPAFactory(IPAServer, log))
|
||||
reactor.listenTCP(IPA.TCP_PORT_OML, IPAFactory(IPAServer, log))
|
||||
test = True
|
||||
if test:
|
||||
reactor.run()
|
||||
else:
|
||||
print("Please specify which protocol in which role you'd like to test.")
|
|
@ -1,8 +1,10 @@
|
|||
SUBDIRS = \
|
||||
openbsc \
|
||||
osmocom \
|
||||
$(NULL)
|
||||
|
||||
noinst_HEADERS = \
|
||||
mISDNif.h \
|
||||
compat_af_isdn.h \
|
||||
nobase_include_HEADERS = \
|
||||
osmocom/legacy_mgcp/mgcp.h \
|
||||
osmocom/legacy_mgcp/mgcp_internal.h \
|
||||
osmocom/legacy_mgcp/mgcpgw_client.h \
|
||||
osmocom/legacy_mgcp/osmux.h \
|
||||
$(NULL)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
#ifdef MISDN_OLD_AF_COMPATIBILITY
|
||||
#undef AF_ISDN
|
||||
#undef PF_ISDN
|
||||
|
||||
extern int AF_ISDN;
|
||||
#define PF_ISDN AF_ISDN
|
||||
|
||||
int AF_ISDN;
|
||||
|
||||
#endif
|
||||
|
||||
extern void init_af_isdn(void);
|
||||
|
||||
#ifdef AF_COMPATIBILITY_FUNC
|
||||
#ifdef MISDN_OLD_AF_COMPATIBILITY
|
||||
void init_af_isdn(void)
|
||||
{
|
||||
int s;
|
||||
|
||||
/* test for new value */
|
||||
AF_ISDN = 34;
|
||||
s = socket(AF_ISDN, SOCK_RAW, ISDN_P_BASE);
|
||||
if (s >= 0) {
|
||||
close(s);
|
||||
return;
|
||||
}
|
||||
AF_ISDN = 27;
|
||||
s = socket(AF_ISDN, SOCK_RAW, ISDN_P_BASE);
|
||||
if (s >= 0) {
|
||||
close(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void init_af_isdn(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -1,387 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Author Karsten Keil <kkeil@novell.com>
|
||||
*
|
||||
* Copyright 2008 by Karsten Keil <kkeil@novell.com>
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
|
||||
* version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 LESSER GENERAL PUBLIC LICENSE for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef mISDNIF_H
|
||||
#define mISDNIF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifdef linux
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/socket.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ABI Version 32 bit
|
||||
*
|
||||
* <8 bit> Major version
|
||||
* - changed if any interface become backwards incompatible
|
||||
*
|
||||
* <8 bit> Minor version
|
||||
* - changed if any interface is extended but backwards compatible
|
||||
*
|
||||
* <16 bit> Release number
|
||||
* - should be incremented on every checkin
|
||||
*/
|
||||
#define MISDN_MAJOR_VERSION 1
|
||||
#define MISDN_MINOR_VERSION 1
|
||||
#define MISDN_RELEASE 20
|
||||
|
||||
/* primitives for information exchange
|
||||
* generell format
|
||||
* <16 bit 0 >
|
||||
* <8 bit command>
|
||||
* BIT 8 = 1 LAYER private
|
||||
* BIT 7 = 1 answer
|
||||
* BIT 6 = 1 DATA
|
||||
* <8 bit target layer mask>
|
||||
*
|
||||
* Layer = 00 is reserved for general commands
|
||||
Layer = 01 L2 -> HW
|
||||
Layer = 02 HW -> L2
|
||||
Layer = 04 L3 -> L2
|
||||
Layer = 08 L2 -> L3
|
||||
* Layer = FF is reserved for broadcast commands
|
||||
*/
|
||||
|
||||
#define MISDN_CMDMASK 0xff00
|
||||
#define MISDN_LAYERMASK 0x00ff
|
||||
|
||||
/* generell commands */
|
||||
#define OPEN_CHANNEL 0x0100
|
||||
#define CLOSE_CHANNEL 0x0200
|
||||
#define CONTROL_CHANNEL 0x0300
|
||||
#define CHECK_DATA 0x0400
|
||||
|
||||
/* layer 2 -> layer 1 */
|
||||
#define PH_ACTIVATE_REQ 0x0101
|
||||
#define PH_DEACTIVATE_REQ 0x0201
|
||||
#define PH_DATA_REQ 0x2001
|
||||
#define MPH_ACTIVATE_REQ 0x0501
|
||||
#define MPH_DEACTIVATE_REQ 0x0601
|
||||
#define MPH_INFORMATION_REQ 0x0701
|
||||
#define PH_CONTROL_REQ 0x0801
|
||||
|
||||
/* layer 1 -> layer 2 */
|
||||
#define PH_ACTIVATE_IND 0x0102
|
||||
#define PH_ACTIVATE_CNF 0x4102
|
||||
#define PH_DEACTIVATE_IND 0x0202
|
||||
#define PH_DEACTIVATE_CNF 0x4202
|
||||
#define PH_DATA_IND 0x2002
|
||||
#define PH_DATA_E_IND 0x3002
|
||||
#define MPH_ACTIVATE_IND 0x0502
|
||||
#define MPH_DEACTIVATE_IND 0x0602
|
||||
#define MPH_INFORMATION_IND 0x0702
|
||||
#define PH_DATA_CNF 0x6002
|
||||
#define PH_CONTROL_IND 0x0802
|
||||
#define PH_CONTROL_CNF 0x4802
|
||||
|
||||
/* layer 3 -> layer 2 */
|
||||
#define DL_ESTABLISH_REQ 0x1004
|
||||
#define DL_RELEASE_REQ 0x1104
|
||||
#define DL_DATA_REQ 0x3004
|
||||
#define DL_UNITDATA_REQ 0x3104
|
||||
#define DL_INFORMATION_REQ 0x0004
|
||||
|
||||
/* layer 2 -> layer 3 */
|
||||
#define DL_ESTABLISH_IND 0x1008
|
||||
#define DL_ESTABLISH_CNF 0x5008
|
||||
#define DL_RELEASE_IND 0x1108
|
||||
#define DL_RELEASE_CNF 0x5108
|
||||
#define DL_DATA_IND 0x3008
|
||||
#define DL_UNITDATA_IND 0x3108
|
||||
#define DL_INFORMATION_IND 0x0008
|
||||
|
||||
/* intern layer 2 managment */
|
||||
#define MDL_ASSIGN_REQ 0x1804
|
||||
#define MDL_ASSIGN_IND 0x1904
|
||||
#define MDL_REMOVE_REQ 0x1A04
|
||||
#define MDL_REMOVE_IND 0x1B04
|
||||
#define MDL_STATUS_UP_IND 0x1C04
|
||||
#define MDL_STATUS_DOWN_IND 0x1D04
|
||||
#define MDL_STATUS_UI_IND 0x1E04
|
||||
#define MDL_ERROR_IND 0x1F04
|
||||
#define MDL_ERROR_RSP 0x5F04
|
||||
|
||||
/* DL_INFORMATION_IND types */
|
||||
#define DL_INFO_L2_CONNECT 0x0001
|
||||
#define DL_INFO_L2_REMOVED 0x0002
|
||||
|
||||
/* PH_CONTROL types */
|
||||
/* TOUCH TONE IS 0x20XX XX "0"..."9", "A","B","C","D","*","#" */
|
||||
#define DTMF_TONE_VAL 0x2000
|
||||
#define DTMF_TONE_MASK 0x007F
|
||||
#define DTMF_TONE_START 0x2100
|
||||
#define DTMF_TONE_STOP 0x2200
|
||||
#define DTMF_HFC_COEF 0x4000
|
||||
#define DSP_CONF_JOIN 0x2403
|
||||
#define DSP_CONF_SPLIT 0x2404
|
||||
#define DSP_RECEIVE_OFF 0x2405
|
||||
#define DSP_RECEIVE_ON 0x2406
|
||||
#define DSP_ECHO_ON 0x2407
|
||||
#define DSP_ECHO_OFF 0x2408
|
||||
#define DSP_MIX_ON 0x2409
|
||||
#define DSP_MIX_OFF 0x240a
|
||||
#define DSP_DELAY 0x240b
|
||||
#define DSP_JITTER 0x240c
|
||||
#define DSP_TXDATA_ON 0x240d
|
||||
#define DSP_TXDATA_OFF 0x240e
|
||||
#define DSP_TX_DEJITTER 0x240f
|
||||
#define DSP_TX_DEJ_OFF 0x2410
|
||||
#define DSP_TONE_PATT_ON 0x2411
|
||||
#define DSP_TONE_PATT_OFF 0x2412
|
||||
#define DSP_VOL_CHANGE_TX 0x2413
|
||||
#define DSP_VOL_CHANGE_RX 0x2414
|
||||
#define DSP_BF_ENABLE_KEY 0x2415
|
||||
#define DSP_BF_DISABLE 0x2416
|
||||
#define DSP_BF_ACCEPT 0x2416
|
||||
#define DSP_BF_REJECT 0x2417
|
||||
#define DSP_PIPELINE_CFG 0x2418
|
||||
#define HFC_VOL_CHANGE_TX 0x2601
|
||||
#define HFC_VOL_CHANGE_RX 0x2602
|
||||
#define HFC_SPL_LOOP_ON 0x2603
|
||||
#define HFC_SPL_LOOP_OFF 0x2604
|
||||
|
||||
/* DSP_TONE_PATT_ON parameter */
|
||||
#define TONE_OFF 0x0000
|
||||
#define TONE_GERMAN_DIALTONE 0x0001
|
||||
#define TONE_GERMAN_OLDDIALTONE 0x0002
|
||||
#define TONE_AMERICAN_DIALTONE 0x0003
|
||||
#define TONE_GERMAN_DIALPBX 0x0004
|
||||
#define TONE_GERMAN_OLDDIALPBX 0x0005
|
||||
#define TONE_AMERICAN_DIALPBX 0x0006
|
||||
#define TONE_GERMAN_RINGING 0x0007
|
||||
#define TONE_GERMAN_OLDRINGING 0x0008
|
||||
#define TONE_AMERICAN_RINGPBX 0x000b
|
||||
#define TONE_GERMAN_RINGPBX 0x000c
|
||||
#define TONE_GERMAN_OLDRINGPBX 0x000d
|
||||
#define TONE_AMERICAN_RINGING 0x000e
|
||||
#define TONE_GERMAN_BUSY 0x000f
|
||||
#define TONE_GERMAN_OLDBUSY 0x0010
|
||||
#define TONE_AMERICAN_BUSY 0x0011
|
||||
#define TONE_GERMAN_HANGUP 0x0012
|
||||
#define TONE_GERMAN_OLDHANGUP 0x0013
|
||||
#define TONE_AMERICAN_HANGUP 0x0014
|
||||
#define TONE_SPECIAL_INFO 0x0015
|
||||
#define TONE_GERMAN_GASSENBESETZT 0x0016
|
||||
#define TONE_GERMAN_AUFSCHALTTON 0x0016
|
||||
|
||||
/* MPH_INFORMATION_IND */
|
||||
#define L1_SIGNAL_LOS_OFF 0x0010
|
||||
#define L1_SIGNAL_LOS_ON 0x0011
|
||||
#define L1_SIGNAL_AIS_OFF 0x0012
|
||||
#define L1_SIGNAL_AIS_ON 0x0013
|
||||
#define L1_SIGNAL_RDI_OFF 0x0014
|
||||
#define L1_SIGNAL_RDI_ON 0x0015
|
||||
#define L1_SIGNAL_SLIP_RX 0x0020
|
||||
#define L1_SIGNAL_SLIP_TX 0x0021
|
||||
|
||||
/*
|
||||
* protocol ids
|
||||
* D channel 1-31
|
||||
* B channel 33 - 63
|
||||
*/
|
||||
|
||||
#define ISDN_P_NONE 0
|
||||
#define ISDN_P_BASE 0
|
||||
#define ISDN_P_TE_S0 0x01
|
||||
#define ISDN_P_NT_S0 0x02
|
||||
#define ISDN_P_TE_E1 0x03
|
||||
#define ISDN_P_NT_E1 0x04
|
||||
#define ISDN_P_TE_UP0 0x05
|
||||
#define ISDN_P_NT_UP0 0x06
|
||||
|
||||
#define IS_ISDN_P_TE(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_TE_E1) || \
|
||||
(p == ISDN_P_TE_UP0) || (p == ISDN_P_LAPD_TE))
|
||||
#define IS_ISDN_P_NT(p) ((p == ISDN_P_NT_S0) || (p == ISDN_P_NT_E1) || \
|
||||
(p == ISDN_P_NT_UP0) || (p == ISDN_P_LAPD_NT))
|
||||
#define IS_ISDN_P_S0(p) ((p == ISDN_P_TE_S0) || (p == ISDN_P_NT_S0))
|
||||
#define IS_ISDN_P_E1(p) ((p == ISDN_P_TE_E1) || (p == ISDN_P_NT_E1))
|
||||
#define IS_ISDN_P_UP0(p) ((p == ISDN_P_TE_UP0) || (p == ISDN_P_NT_UP0))
|
||||
|
||||
|
||||
#define ISDN_P_LAPD_TE 0x10
|
||||
#define ISDN_P_LAPD_NT 0x11
|
||||
|
||||
#define ISDN_P_B_MASK 0x1f
|
||||
#define ISDN_P_B_START 0x20
|
||||
|
||||
#define ISDN_P_B_RAW 0x21
|
||||
#define ISDN_P_B_HDLC 0x22
|
||||
#define ISDN_P_B_X75SLP 0x23
|
||||
#define ISDN_P_B_L2DTMF 0x24
|
||||
#define ISDN_P_B_L2DSP 0x25
|
||||
#define ISDN_P_B_L2DSPHDLC 0x26
|
||||
|
||||
#define OPTION_L2_PMX 1
|
||||
#define OPTION_L2_PTP 2
|
||||
#define OPTION_L2_FIXEDTEI 3
|
||||
#define OPTION_L2_CLEANUP 4
|
||||
|
||||
/* should be in sync with linux/kobject.h:KOBJ_NAME_LEN */
|
||||
#define MISDN_MAX_IDLEN 20
|
||||
|
||||
struct mISDNhead {
|
||||
unsigned int prim;
|
||||
unsigned int id;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define MISDN_HEADER_LEN sizeof(struct mISDNhead)
|
||||
#define MAX_DATA_SIZE 2048
|
||||
#define MAX_DATA_MEM (MAX_DATA_SIZE + MISDN_HEADER_LEN)
|
||||
#define MAX_DFRAME_LEN 260
|
||||
|
||||
#define MISDN_ID_ADDR_MASK 0xFFFF
|
||||
#define MISDN_ID_TEI_MASK 0xFF00
|
||||
#define MISDN_ID_SAPI_MASK 0x00FF
|
||||
#define MISDN_ID_TEI_ANY 0x7F00
|
||||
|
||||
#define MISDN_ID_ANY 0xFFFF
|
||||
#define MISDN_ID_NONE 0xFFFE
|
||||
|
||||
#define GROUP_TEI 127
|
||||
#define TEI_SAPI 63
|
||||
#define CTRL_SAPI 0
|
||||
|
||||
#define MISDN_MAX_CHANNEL 127
|
||||
#define MISDN_CHMAP_SIZE ((MISDN_MAX_CHANNEL + 1) >> 3)
|
||||
|
||||
#define SOL_MISDN 0
|
||||
|
||||
struct sockaddr_mISDN {
|
||||
sa_family_t family;
|
||||
unsigned char dev;
|
||||
unsigned char channel;
|
||||
unsigned char sapi;
|
||||
unsigned char tei;
|
||||
};
|
||||
|
||||
struct mISDNversion {
|
||||
unsigned char major;
|
||||
unsigned char minor;
|
||||
unsigned short release;
|
||||
};
|
||||
|
||||
#define MAX_DEVICE_ID 63
|
||||
|
||||
struct mISDN_devinfo {
|
||||
u_int id;
|
||||
u_int Dprotocols;
|
||||
u_int Bprotocols;
|
||||
u_int protocol;
|
||||
u_char channelmap[MISDN_CHMAP_SIZE];
|
||||
u_int nrbchan;
|
||||
char name[MISDN_MAX_IDLEN];
|
||||
};
|
||||
|
||||
struct mISDN_devrename {
|
||||
u_int id;
|
||||
char name[MISDN_MAX_IDLEN];
|
||||
};
|
||||
|
||||
struct ph_info_ch {
|
||||
int32_t protocol;
|
||||
int64_t Flags;
|
||||
};
|
||||
|
||||
struct ph_info_dch {
|
||||
struct ph_info_ch ch;
|
||||
int16_t state;
|
||||
int16_t num_bch;
|
||||
};
|
||||
|
||||
struct ph_info {
|
||||
struct ph_info_dch dch;
|
||||
struct ph_info_ch bch[];
|
||||
};
|
||||
|
||||
/* timer device ioctl */
|
||||
#define IMADDTIMER _IOR('I', 64, int)
|
||||
#define IMDELTIMER _IOR('I', 65, int)
|
||||
/* socket ioctls */
|
||||
#define IMGETVERSION _IOR('I', 66, int)
|
||||
#define IMGETCOUNT _IOR('I', 67, int)
|
||||
#define IMGETDEVINFO _IOR('I', 68, int)
|
||||
#define IMCTRLREQ _IOR('I', 69, int)
|
||||
#define IMCLEAR_L2 _IOR('I', 70, int)
|
||||
#define IMSETDEVNAME _IOR('I', 71, struct mISDN_devrename)
|
||||
|
||||
static inline int
|
||||
test_channelmap(u_int nr, u_char *map)
|
||||
{
|
||||
if (nr <= MISDN_MAX_CHANNEL)
|
||||
return map[nr >> 3] & (1 << (nr & 7));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_channelmap(u_int nr, u_char *map)
|
||||
{
|
||||
map[nr >> 3] |= (1 << (nr & 7));
|
||||
}
|
||||
|
||||
static inline void
|
||||
clear_channelmap(u_int nr, u_char *map)
|
||||
{
|
||||
map[nr >> 3] &= ~(1 << (nr & 7));
|
||||
}
|
||||
|
||||
/* CONTROL_CHANNEL parameters */
|
||||
#define MISDN_CTRL_GETOP 0x0000
|
||||
#define MISDN_CTRL_LOOP 0x0001
|
||||
#define MISDN_CTRL_CONNECT 0x0002
|
||||
#define MISDN_CTRL_DISCONNECT 0x0004
|
||||
#define MISDN_CTRL_PCMCONNECT 0x0010
|
||||
#define MISDN_CTRL_PCMDISCONNECT 0x0020
|
||||
#define MISDN_CTRL_SETPEER 0x0040
|
||||
#define MISDN_CTRL_UNSETPEER 0x0080
|
||||
#define MISDN_CTRL_RX_OFF 0x0100
|
||||
#define MISDN_CTRL_FILL_EMPTY 0x0200
|
||||
#define MISDN_CTRL_GETPEER 0x0400
|
||||
#define MISDN_CTRL_HW_FEATURES_OP 0x2000
|
||||
#define MISDN_CTRL_HW_FEATURES 0x2001
|
||||
#define MISDN_CTRL_HFC_OP 0x4000
|
||||
#define MISDN_CTRL_HFC_PCM_CONN 0x4001
|
||||
#define MISDN_CTRL_HFC_PCM_DISC 0x4002
|
||||
#define MISDN_CTRL_HFC_CONF_JOIN 0x4003
|
||||
#define MISDN_CTRL_HFC_CONF_SPLIT 0x4004
|
||||
#define MISDN_CTRL_HFC_RECEIVE_OFF 0x4005
|
||||
#define MISDN_CTRL_HFC_RECEIVE_ON 0x4006
|
||||
#define MISDN_CTRL_HFC_ECHOCAN_ON 0x4007
|
||||
#define MISDN_CTRL_HFC_ECHOCAN_OFF 0x4008
|
||||
|
||||
|
||||
/* socket options */
|
||||
#define MISDN_TIME_STAMP 0x0001
|
||||
|
||||
struct mISDN_ctrl_req {
|
||||
int op;
|
||||
int channel;
|
||||
int p1;
|
||||
int p2;
|
||||
};
|
||||
|
||||
/* muxer options */
|
||||
#define MISDN_OPT_ALL 1
|
||||
#define MISDN_OPT_TEIMGR 2
|
||||
|
||||
#endif /* mISDNIF_H */
|
|
@ -1,110 +0,0 @@
|
|||
noinst_HEADERS = \
|
||||
abis_nm.h \
|
||||
abis_om2000.h \
|
||||
abis_rsl.h \
|
||||
a_iface.h \
|
||||
a_iface_bssap.h \
|
||||
arfcn_range_encode.h \
|
||||
auth.h \
|
||||
bsc_msc.h \
|
||||
bsc_msg_filter.h \
|
||||
bsc_nat.h \
|
||||
bsc_nat_callstats.h \
|
||||
bsc_nat_sccp.h \
|
||||
bsc_rll.h \
|
||||
bsc_subscriber.h \
|
||||
bss.h \
|
||||
bts_ipaccess_nanobts_omlattr.h \
|
||||
chan_alloc.h \
|
||||
common.h \
|
||||
common_bsc.h \
|
||||
common_cs.h \
|
||||
crc24.h \
|
||||
ctrl.h \
|
||||
db.h \
|
||||
debug.h \
|
||||
e1_config.h \
|
||||
gb_proxy.h \
|
||||
gprs_gb_parse.h \
|
||||
gprs_gmm.h \
|
||||
gprs_llc.h \
|
||||
gprs_llc_xid.h \
|
||||
gprs_sgsn.h \
|
||||
gprs_sndcp.h \
|
||||
gprs_sndcp_comp.h \
|
||||
gprs_sndcp_dcomp.h \
|
||||
gprs_sndcp_pcomp.h \
|
||||
gprs_sndcp_xid.h \
|
||||
gprs_subscriber.h \
|
||||
gprs_utils.h \
|
||||
gsm_04_08.h \
|
||||
gsm_04_11.h \
|
||||
gsm_04_14.h \
|
||||
gsm_04_80.h \
|
||||
gsm_data.h \
|
||||
gsm_data_shared.h \
|
||||
gsm_subscriber.h \
|
||||
gsup_client.h \
|
||||
gtphub.h \
|
||||
handover.h \
|
||||
handover_decision.h \
|
||||
ipaccess.h \
|
||||
iucs.h \
|
||||
iucs_ranap.h \
|
||||
iu_dummy.h \
|
||||
meas_feed.h \
|
||||
meas_rep.h \
|
||||
mgcp.h \
|
||||
mgcp_internal.h \
|
||||
mgcp_transcode.h \
|
||||
mgcpgw_client.h \
|
||||
misdn.h \
|
||||
mncc.h \
|
||||
mncc_int.h \
|
||||
msc_ifaces.h \
|
||||
nat_rewrite_trie.h \
|
||||
network_listen.h \
|
||||
oap_client.h \
|
||||
openbscdefines.h \
|
||||
osmo_bsc.h \
|
||||
osmo_bsc_grace.h \
|
||||
a_reset.h \
|
||||
osmo_bsc_rf.h \
|
||||
osmo_msc.h \
|
||||
osmo_bsc_sigtran.h \
|
||||
bsc_msc_data.h \
|
||||
osmux.h \
|
||||
paging.h \
|
||||
pcu_if.h \
|
||||
pcuif_proto.h \
|
||||
rest_octets.h \
|
||||
rrlp.h \
|
||||
rs232.h \
|
||||
rtp_proxy.h \
|
||||
sgsn.h \
|
||||
signal.h \
|
||||
silent_call.h \
|
||||
slhc.h \
|
||||
smpp.h \
|
||||
sms_queue.h \
|
||||
socket.h \
|
||||
system_information.h \
|
||||
transaction.h \
|
||||
trau_mux.h \
|
||||
trau_upqueue.h \
|
||||
ussd.h \
|
||||
vlr.h \
|
||||
vty.h \
|
||||
v42bis.h \
|
||||
v42bis_private.h \
|
||||
$(NULL)
|
||||
|
||||
openbsc_HEADERS = \
|
||||
bsc_api.h \
|
||||
gsm_04_08.h \
|
||||
meas_rep.h \
|
||||
$(NULL)
|
||||
|
||||
# DO NOT add a newline and '$(NULL)' to this line. That would add a trailing
|
||||
# space to the directory installed: $prefix/include/'openbsc '
|
||||
openbscdir = $(includedir)/openbsc
|
|
@ -1,76 +0,0 @@
|
|||
/* (C) 2017 by Sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <openbsc/a_reset.h>
|
||||
|
||||
/* A struct to keep a context information about the BSCs we are associated with */
|
||||
struct bsc_context {
|
||||
struct llist_head list;
|
||||
|
||||
/* Holds a copy of the sccp address of the BSC,
|
||||
* this address will become known as soon as
|
||||
* a remote BSC tries to make a connection or
|
||||
* sends a RESET request via UNIDATA */
|
||||
struct osmo_sccp_addr bsc_addr;
|
||||
|
||||
/* Holds a copy of the our local MSC address,
|
||||
* this will be the sccp-address that is associated
|
||||
* with the A interface */
|
||||
struct osmo_sccp_addr msc_addr;
|
||||
|
||||
/* A pointer to the reset handler FSM, the
|
||||
* state machine is allocated when the BSC
|
||||
* is registerd. */
|
||||
struct a_reset_ctx *reset;
|
||||
|
||||
/* A pointer to the sccp_user that is associated
|
||||
* with the A interface. We need this information
|
||||
* to send the resets and to send paging requests */
|
||||
struct osmo_sccp_user *sccp_user;
|
||||
};
|
||||
|
||||
/* Initalize A interface connection between to MSC and BSC */
|
||||
int a_init(struct osmo_sccp_instance *sccp, struct gsm_network *network);
|
||||
|
||||
/* Send DTAP message via A-interface */
|
||||
int a_iface_tx_dtap(struct msgb *msg);
|
||||
|
||||
/* Send Cipher mode command via A-interface */
|
||||
int a_iface_tx_cipher_mode(const struct gsm_subscriber_connection *conn,
|
||||
int cipher, const const uint8_t *key, int len, int include_imeisv);
|
||||
|
||||
/* Page a subscriber via A-interface */
|
||||
int a_iface_tx_paging(const char *imsi, uint32_t tmsi, uint16_t lac);
|
||||
|
||||
/* Send assignment request via A-interface */
|
||||
int a_iface_tx_assignment(const struct gsm_trans *trans);
|
||||
|
||||
/* Send clear command via A-interface */
|
||||
int a_iface_tx_clear_cmd(struct gsm_subscriber_connection *conn);
|
||||
|
||||
/* Clear all subscriber connections on a specified BSC
|
||||
* (Helper function for a_iface_bssap.c) */
|
||||
void a_clear_all(struct osmo_sccp_user *scu, const struct osmo_sccp_addr *bsc_addr);
|
||||
|
||||
/* Delete info of a closed connection from the active connection list
|
||||
* (Helper function for a_iface_bssap.c) */
|
||||
void a_delete_bsc_con(uint32_t conn_id);
|
|
@ -1,41 +0,0 @@
|
|||
/* (C) 2017 by sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Note: The structs and functions presented in this header file are intended
|
||||
* to be used only by a_iface.c. */
|
||||
|
||||
/* A structure to hold tha most basic information about a sigtran connection
|
||||
* we use this struct internally here to pass connection data around */
|
||||
struct a_conn_info {
|
||||
struct osmo_sccp_addr *msc_addr;
|
||||
struct osmo_sccp_addr *bsc_addr;
|
||||
uint32_t conn_id;
|
||||
struct gsm_network *network;
|
||||
struct a_reset_ctx *reset;
|
||||
};
|
||||
|
||||
/* Receive incoming connection less data messages via sccp */
|
||||
void sccp_rx_udt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg);
|
||||
|
||||
/* Receive incoming connection oriented data messages via sccp */
|
||||
int sccp_rx_dt(struct osmo_sccp_user *scu, const struct a_conn_info *a_conn_info, struct msgb *msg);
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
/* (C) 2017 by sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
/* Reset context data (callbacks, state machine etc...) */
|
||||
struct a_reset_ctx {
|
||||
|
||||
/* FSM instance, which handles the reset procedure */
|
||||
struct osmo_fsm_inst *fsm;
|
||||
|
||||
/* Connection failure counter. When this counter
|
||||
* reaches a certain threshold, the reset procedure
|
||||
* will be triggered */
|
||||
int conn_loss_counter;
|
||||
|
||||
/* A human readable name to display in the logs */
|
||||
char name[256];
|
||||
|
||||
/* Callback function to be called when a connection
|
||||
* failure is detected and a rest must occur */
|
||||
void (*cb)(void *priv);
|
||||
|
||||
/* Privated data for the callback function */
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/* Create and start state machine which handles the reset/reset-ack procedure */
|
||||
struct a_reset_ctx *a_reset_alloc(const void *ctx, const char *name, void *cb, void *priv);
|
||||
|
||||
/* Tear down state machine */
|
||||
void a_reset_free(struct a_reset_ctx *reset);
|
||||
|
||||
/* Confirm that we sucessfully received a reset acknowlege message */
|
||||
void a_reset_ack_confirm(struct a_reset_ctx *reset);
|
||||
|
||||
/* Report a failed connection */
|
||||
void a_reset_conn_fail(struct a_reset_ctx *reset);
|
||||
|
||||
/* Report a successful connection */
|
||||
void a_reset_conn_success(struct a_reset_ctx *reset);
|
||||
|
||||
/* Check if we have a connection to a specified msc */
|
||||
bool a_reset_conn_ready(struct a_reset_ctx *reset);
|
|
@ -1,180 +0,0 @@
|
|||
/* GSM Network Management messages on the A-bis interface
|
||||
* 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
|
||||
|
||||
/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NM_H
|
||||
#define _NM_H
|
||||
|
||||
#include <osmocom/gsm/tlv.h>
|
||||
#include <osmocom/gsm/abis_nm.h>
|
||||
#include <osmocom/gsm/protocol/gsm_12_21.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
/* max number of attributes represented as 3GPP TS 52.021 §9.4.62 SW Description array */
|
||||
#define MAX_BTS_ATTR 5
|
||||
|
||||
struct cell_global_id {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint16_t lac;
|
||||
uint16_t ci;
|
||||
};
|
||||
|
||||
/* The BCCH info from an ip.access test, in host byte order
|
||||
* and already parsed... */
|
||||
struct ipac_bcch_info {
|
||||
struct llist_head list;
|
||||
|
||||
uint16_t info_type;
|
||||
uint8_t freq_qual;
|
||||
uint16_t arfcn;
|
||||
uint8_t rx_lev;
|
||||
uint8_t rx_qual;
|
||||
int16_t freq_err;
|
||||
uint16_t frame_offset;
|
||||
uint32_t frame_nr_offset;
|
||||
uint8_t bsic;
|
||||
struct cell_global_id cgi;
|
||||
uint8_t ba_list_si2[16];
|
||||
uint8_t ba_list_si2bis[16];
|
||||
uint8_t ba_list_si2ter[16];
|
||||
uint8_t ca_list_si1[16];
|
||||
};
|
||||
|
||||
/* PUBLIC */
|
||||
|
||||
struct msgb;
|
||||
|
||||
struct abis_nm_cfg {
|
||||
/* callback for unidirectional reports */
|
||||
int (*report_cb)(struct msgb *,
|
||||
struct abis_om_fom_hdr *);
|
||||
/* callback for software activate requests from BTS */
|
||||
int (*sw_act_req)(struct msgb *);
|
||||
};
|
||||
|
||||
extern int abis_nm_rcvmsg(struct msgb *msg);
|
||||
|
||||
int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const uint8_t *buf, int len);
|
||||
int abis_nm_rx(struct msgb *msg);
|
||||
int abis_nm_opstart(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0, uint8_t i1, uint8_t i2);
|
||||
int abis_nm_chg_adm_state(struct gsm_bts *bts, uint8_t obj_class, uint8_t i0,
|
||||
uint8_t i1, uint8_t i2, enum abis_nm_adm_state adm_state);
|
||||
int abis_nm_establish_tei(struct gsm_bts *bts, uint8_t trx_nr,
|
||||
uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot,
|
||||
uint8_t tei);
|
||||
int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
|
||||
uint8_t e1_port, uint8_t e1_timeslot, uint8_t e1_subslot);
|
||||
int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
|
||||
uint8_t e1_port, uint8_t e1_timeslot,
|
||||
uint8_t e1_subslot);
|
||||
int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class,
|
||||
uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
const uint8_t *attr, uint8_t attr_len);
|
||||
int abis_nm_set_bts_attr(struct gsm_bts *bts, uint8_t *attr, int attr_len);
|
||||
int abis_nm_set_radio_attr(struct gsm_bts_trx *trx, uint8_t *attr, int attr_len);
|
||||
int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, uint8_t chan_comb);
|
||||
int abis_nm_sw_act_req_ack(struct gsm_bts *bts, uint8_t obj_class, uint8_t i1,
|
||||
uint8_t i2, uint8_t i3, int nack, uint8_t *attr, int att_len);
|
||||
int abis_nm_raw_msg(struct gsm_bts *bts, int len, uint8_t *msg);
|
||||
int abis_nm_event_reports(struct gsm_bts *bts, int on);
|
||||
int abis_nm_reset_resource(struct gsm_bts *bts);
|
||||
int abis_nm_software_load(struct gsm_bts *bts, int trx_nr, const char *fname,
|
||||
uint8_t win_size, int forced,
|
||||
gsm_cbfn *cbfn, void *cb_data);
|
||||
int abis_nm_software_load_status(struct gsm_bts *bts);
|
||||
int abis_nm_software_activate(struct gsm_bts *bts, const char *fname,
|
||||
gsm_cbfn *cbfn, void *cb_data);
|
||||
|
||||
int abis_nm_conn_mdrop_link(struct gsm_bts *bts, uint8_t e1_port0, uint8_t ts0,
|
||||
uint8_t e1_port1, uint8_t ts1);
|
||||
|
||||
int abis_nm_perform_test(struct gsm_bts *bts, uint8_t obj_class,
|
||||
uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
uint8_t test_nr, uint8_t auton_report, struct msgb *msg);
|
||||
|
||||
/* Siemens / BS-11 specific */
|
||||
int abis_nm_bs11_reset_resource(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin);
|
||||
int abis_nm_bs11_create_object(struct gsm_bts *bts, enum abis_bs11_objtype type,
|
||||
uint8_t idx, uint8_t attr_len, const uint8_t *attr);
|
||||
int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, uint8_t idx);
|
||||
int abis_nm_bs11_create_bport(struct gsm_bts *bts, uint8_t idx);
|
||||
int abis_nm_bs11_delete_object(struct gsm_bts *bts,
|
||||
enum abis_bs11_objtype type, uint8_t idx);
|
||||
int abis_nm_bs11_delete_bport(struct gsm_bts *bts, uint8_t idx);
|
||||
int abis_nm_bs11_conn_oml_tei(struct gsm_bts *bts, uint8_t e1_port,
|
||||
uint8_t e1_timeslot, uint8_t e1_subslot, uint8_t tei);
|
||||
int abis_nm_bs11_get_oml_tei_ts(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_get_serno(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, uint8_t level);
|
||||
int abis_nm_bs11_get_trx_power(struct gsm_bts_trx *trx);
|
||||
int abis_nm_bs11_logon(struct gsm_bts *bts, uint8_t level, const char *name, int on);
|
||||
int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on);
|
||||
int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on);
|
||||
int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password);
|
||||
int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked);
|
||||
int abis_nm_bs11_get_pll_mode(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value);
|
||||
int abis_nm_bs11_get_cclk(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_get_state(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname,
|
||||
uint8_t win_size, int forced, gsm_cbfn *cbfn);
|
||||
int abis_nm_bs11_set_ext_time(struct gsm_bts *bts);
|
||||
int abis_nm_bs11_get_bport_line_cfg(struct gsm_bts *bts, uint8_t bport);
|
||||
int abis_nm_bs11_set_bport_line_cfg(struct gsm_bts *bts, uint8_t bport, enum abis_bs11_line_cfg line_cfg);
|
||||
int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect);
|
||||
int abis_nm_bs11_restart(struct gsm_bts *bts);
|
||||
|
||||
/* ip.access nanoBTS specific commands */
|
||||
int abis_nm_ipaccess_msg(struct gsm_bts *bts, uint8_t msg_type,
|
||||
uint8_t obj_class, uint8_t bts_nr,
|
||||
uint8_t trx_nr, uint8_t ts_nr,
|
||||
uint8_t *attr, int attr_len);
|
||||
int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
|
||||
int attr_len);
|
||||
int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx);
|
||||
int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class,
|
||||
uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
|
||||
uint8_t *attr, uint8_t attr_len);
|
||||
int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
|
||||
uint32_t ip, uint16_t port, uint8_t stream);
|
||||
void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts);
|
||||
int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf);
|
||||
const char *ipacc_testres_name(uint8_t res);
|
||||
|
||||
/* Functions calling into other code parts */
|
||||
int nm_is_running(struct gsm_nm_state *s);
|
||||
|
||||
int abis_nm_vty_init(void);
|
||||
|
||||
void abis_nm_clear_queue(struct gsm_bts *bts);
|
||||
|
||||
int _abis_nm_sendmsg(struct msgb *msg);
|
||||
|
||||
void abis_nm_queue_send_next(struct gsm_bts *bts); /* for bs11_config. */
|
||||
|
||||
int abis_nm_select_newest_sw(const struct abis_nm_sw_desc *sw, const size_t len);
|
||||
|
||||
/* Helper functions for updating attributes */
|
||||
int abis_nm_update_max_power_red(struct gsm_bts_trx *trx);
|
||||
|
||||
#endif /* _NM_H */
|
|
@ -1,129 +0,0 @@
|
|||
#ifndef OPENBSC_ABIS_OM2K_H
|
||||
#define OPENBSC_ABIS_OM2K_H
|
||||
/* Ericsson RBS 2xxx GSM O&M (OM2000) messages on the A-bis interface
|
||||
* implemented based on protocol trace analysis, no formal documentation */
|
||||
|
||||
/* (C) 2010-2011 by Harald Welte <laforge@gnumonks.org>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
enum abis_om2k_mo_cls {
|
||||
OM2K_MO_CLS_TRXC = 0x01,
|
||||
OM2K_MO_CLS_TS = 0x03,
|
||||
OM2K_MO_CLS_TF = 0x04,
|
||||
OM2K_MO_CLS_IS = 0x05,
|
||||
OM2K_MO_CLS_CON = 0x06,
|
||||
OM2K_MO_CLS_DP = 0x07,
|
||||
OM2K_MO_CLS_CF = 0x0a,
|
||||
OM2K_MO_CLS_TX = 0x0b,
|
||||
OM2K_MO_CLS_RX = 0x0c,
|
||||
};
|
||||
|
||||
enum om2k_mo_state {
|
||||
OM2K_MO_S_RESET = 0,
|
||||
OM2K_MO_S_STARTED,
|
||||
OM2K_MO_S_ENABLED,
|
||||
OM2K_MO_S_DISABLED,
|
||||
};
|
||||
|
||||
/* on-wire format for IS conn group */
|
||||
struct om2k_is_conn_grp {
|
||||
uint16_t icp1;
|
||||
uint16_t icp2;
|
||||
uint8_t cont_idx;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* internal data formant for IS conn group */
|
||||
struct is_conn_group {
|
||||
struct llist_head list;
|
||||
uint16_t icp1;
|
||||
uint16_t icp2;
|
||||
uint8_t ci;
|
||||
};
|
||||
|
||||
/* on-wire format for CON Path */
|
||||
struct om2k_con_path {
|
||||
uint16_t ccp;
|
||||
uint8_t ci;
|
||||
uint8_t tag;
|
||||
uint8_t tei;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* internal data format for CON group */
|
||||
struct con_group {
|
||||
/* links list of CON groups in BTS */
|
||||
struct llist_head list;
|
||||
struct gsm_bts *bts;
|
||||
/* CON Group ID */
|
||||
uint8_t cg;
|
||||
/* list of CON paths in this group */
|
||||
struct llist_head paths;
|
||||
};
|
||||
|
||||
/* internal data format for CON path */
|
||||
struct con_path {
|
||||
/* links with con_group.paths */
|
||||
struct llist_head list;
|
||||
/* CON Connection Point */
|
||||
uint16_t ccp;
|
||||
/* Contiguity Index */
|
||||
uint8_t ci;
|
||||
/* Tag */
|
||||
uint8_t tag;
|
||||
/* TEI */
|
||||
uint8_t tei;
|
||||
};
|
||||
|
||||
extern const struct abis_om2k_mo om2k_mo_cf;
|
||||
extern const struct abis_om2k_mo om2k_mo_is;
|
||||
extern const struct abis_om2k_mo om2k_mo_con;
|
||||
extern const struct abis_om2k_mo om2k_mo_tf;
|
||||
|
||||
extern const struct value_string om2k_mo_class_short_vals[];
|
||||
|
||||
int abis_om2k_rcvmsg(struct msgb *msg);
|
||||
|
||||
extern const struct abis_om2k_mo om2k_mo_cf;
|
||||
|
||||
int abis_om2k_tx_reset_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_start_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_status_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_connect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_disconnect_cmd(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_enable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_disable_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_test_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo,
|
||||
uint8_t operational);
|
||||
int abis_om2k_tx_cap_req(struct gsm_bts *bts, const struct abis_om2k_mo *mo);
|
||||
int abis_om2k_tx_is_conf_req(struct gsm_bts *bts);
|
||||
int abis_om2k_tx_tf_conf_req(struct gsm_bts *bts);
|
||||
int abis_om2k_tx_rx_conf_req(struct gsm_bts_trx *trx);
|
||||
int abis_om2k_tx_tx_conf_req(struct gsm_bts_trx *trx);
|
||||
int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts);
|
||||
|
||||
struct osmo_fsm_inst *om2k_bts_fsm_start(struct gsm_bts *bts);
|
||||
void abis_om2k_bts_init(struct gsm_bts *bts);
|
||||
void abis_om2k_trx_init(struct gsm_bts_trx *trx);
|
||||
|
||||
int abis_om2k_vty_init(void);
|
||||
|
||||
struct vty;
|
||||
void abis_om2k_config_write_bts(struct vty *vty, struct gsm_bts *bts);
|
||||
|
||||
#endif /* OPENBCS_ABIS_OM2K_H */
|
|
@ -1,117 +0,0 @@
|
|||
/* GSM Radio Signalling Link messages on the A-bis interface
|
||||
* 3GPP TS 08.58 version 8.6.0 Release 1999 / ETSI TS 100 596 V8.6.0 */
|
||||
|
||||
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _RSL_H
|
||||
#define _RSL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_58.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/sysinfo.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
struct gsm_bts;
|
||||
struct gsm_lchan;
|
||||
struct gsm_bts_trx_ts;
|
||||
|
||||
#define GSM48_LEN2PLEN(a) (((a) << 2) | 1)
|
||||
|
||||
int rsl_bcch_info(const struct gsm_bts_trx *trx, enum osmo_sysinfo_type si_type, const uint8_t *data, int len);
|
||||
int rsl_sacch_filling(struct gsm_bts_trx *trx, uint8_t type,
|
||||
const uint8_t *data, int len);
|
||||
int rsl_chan_activate(struct gsm_bts_trx *trx, uint8_t chan_nr,
|
||||
uint8_t act_type,
|
||||
struct rsl_ie_chan_mode *chan_mode,
|
||||
struct rsl_ie_chan_ident *chan_ident,
|
||||
uint8_t bs_power, uint8_t ms_power,
|
||||
uint8_t ta);
|
||||
int rsl_chan_activate_lchan(struct gsm_lchan *lchan, uint8_t act_type,
|
||||
uint8_t ho_ref);
|
||||
int rsl_chan_mode_modify_req(struct gsm_lchan *ts);
|
||||
int rsl_encryption_cmd(struct msgb *msg);
|
||||
int rsl_paging_cmd(struct gsm_bts *bts, uint8_t paging_group, uint8_t len,
|
||||
uint8_t *ms_ident, uint8_t chan_needed, bool is_gprs);
|
||||
int rsl_imm_assign_cmd(struct gsm_bts *bts, uint8_t len, uint8_t *val);
|
||||
|
||||
int rsl_data_request(struct msgb *msg, uint8_t link_id);
|
||||
int rsl_establish_request(struct gsm_lchan *lchan, uint8_t link_id);
|
||||
int rsl_relase_request(struct gsm_lchan *lchan, uint8_t link_id);
|
||||
|
||||
/* Ericcson vendor specific RSL extensions */
|
||||
int rsl_ericsson_imm_assign_cmd(struct gsm_bts *bts, uint32_t tlli, uint8_t len, uint8_t *val);
|
||||
|
||||
/* Siemens vendor-specific RSL extensions */
|
||||
int rsl_siemens_mrpci(struct gsm_lchan *lchan, struct rsl_mrpci *mrpci);
|
||||
|
||||
/* ip.access specfic RSL extensions */
|
||||
int rsl_ipacc_crcx(struct gsm_lchan *lchan);
|
||||
int rsl_ipacc_mdcx(struct gsm_lchan *lchan, uint32_t ip,
|
||||
uint16_t port, uint8_t rtp_payload2);
|
||||
int rsl_ipacc_mdcx_to_rtpsock(struct gsm_lchan *lchan);
|
||||
int rsl_ipacc_pdch_activate(struct gsm_bts_trx_ts *ts, int act);
|
||||
|
||||
int abis_rsl_rcvmsg(struct msgb *msg);
|
||||
|
||||
uint64_t str_to_imsi(const char *imsi_str);
|
||||
int rsl_release_request(struct gsm_lchan *lchan, uint8_t link_id,
|
||||
enum rsl_rel_mode release_mode);
|
||||
|
||||
int rsl_lchan_set_state(struct gsm_lchan *lchan, int);
|
||||
int rsl_lchan_mark_broken(struct gsm_lchan *lchan, const char *broken);
|
||||
|
||||
/* to be provided by external code */
|
||||
int rsl_deact_sacch(struct gsm_lchan *lchan);
|
||||
|
||||
/* BCCH related code */
|
||||
int rsl_ccch_conf_to_bs_cc_chans(int ccch_conf);
|
||||
int rsl_ccch_conf_to_bs_ccch_sdcch_comb(int ccch_conf);
|
||||
|
||||
int rsl_sacch_info_modify(struct gsm_lchan *lchan, uint8_t type,
|
||||
const uint8_t *data, int len);
|
||||
|
||||
int rsl_chan_bs_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int db);
|
||||
int rsl_chan_ms_power_ctrl(struct gsm_lchan *lchan, unsigned int fpc, int dbm);
|
||||
|
||||
/* SMSCB functionality */
|
||||
int rsl_sms_cb_command(struct gsm_bts *bts, uint8_t chan_number,
|
||||
struct rsl_ie_cb_cmd_type cb_command,
|
||||
const uint8_t *data, int len);
|
||||
|
||||
/* some Nokia specific stuff */
|
||||
int rsl_nokia_si_begin(struct gsm_bts_trx *trx);
|
||||
int rsl_nokia_si_end(struct gsm_bts_trx *trx);
|
||||
|
||||
/* required for Nokia BTS power control */
|
||||
int rsl_bs_power_control(struct gsm_bts_trx *trx, uint8_t channel, uint8_t reduction);
|
||||
|
||||
|
||||
int rsl_release_sapis_from(struct gsm_lchan *lchan, int start,
|
||||
enum rsl_rel_mode release_mode);
|
||||
int rsl_start_t3109(struct gsm_lchan *lchan);
|
||||
|
||||
int rsl_direct_rf_release(struct gsm_lchan *lchan);
|
||||
|
||||
void dyn_ts_init(struct gsm_bts_trx_ts *ts);
|
||||
int dyn_ts_switchover_start(struct gsm_bts_trx_ts *ts,
|
||||
enum gsm_phys_chan_config to_pchan);
|
||||
|
||||
#endif /* RSL_MT_H */
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef ARFCN_RANGE_ENCODE_H
|
||||
#define ARFCN_RANGE_ENCODE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum gsm48_range {
|
||||
ARFCN_RANGE_INVALID = -1,
|
||||
ARFCN_RANGE_128 = 127,
|
||||
ARFCN_RANGE_256 = 255,
|
||||
ARFCN_RANGE_512 = 511,
|
||||
ARFCN_RANGE_1024 = 1023,
|
||||
};
|
||||
|
||||
#define RANGE_ENC_MAX_ARFCNS 29
|
||||
|
||||
int range_enc_determine_range(const int *arfcns, int size, int *f0_out);
|
||||
int range_enc_arfcns(enum gsm48_range rng, const int *arfcns, int sze, int *out, int idx);
|
||||
int range_enc_find_index(enum gsm48_range rng, const int *arfcns, int size);
|
||||
int range_enc_filter_arfcns(int *arfcns, const int sze, const int f0, int *f0_included);
|
||||
|
||||
int range_enc_range128(uint8_t *chan_list, int f0, int *w);
|
||||
int range_enc_range256(uint8_t *chan_list, int f0, int *w);
|
||||
int range_enc_range512(uint8_t *chan_list, int f0, int *w);
|
||||
int range_enc_range1024(uint8_t *chan_list, int f0, int f0_incl, int *w);
|
||||
|
||||
#endif
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef _AUTH_H
|
||||
#define _AUTH_H
|
||||
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
struct gsm_auth_tuple;
|
||||
|
||||
enum auth_action {
|
||||
AUTH_ERROR = -1, /* Internal error */
|
||||
AUTH_NOT_AVAIL = 0, /* No auth tuple available */
|
||||
AUTH_DO_AUTH_THEN_CIPH = 1, /* Firsth authenticate, then cipher */
|
||||
AUTH_DO_CIPH = 2, /* Only ciphering */
|
||||
AUTH_DO_AUTH = 3, /* Only authentication, no ciphering */
|
||||
};
|
||||
|
||||
extern const struct value_string auth_action_names[];
|
||||
static inline const char *auth_action_str(enum auth_action a)
|
||||
{
|
||||
return get_value_string(auth_action_names, a);
|
||||
}
|
||||
|
||||
#endif /* _AUTH_H */
|
|
@ -1,58 +0,0 @@
|
|||
/* GSM 08.08 like API for OpenBSC */
|
||||
|
||||
#ifndef OPENBSC_BSC_API_H
|
||||
#define OPENBSC_BSC_API_H
|
||||
|
||||
#include "gsm_data.h"
|
||||
|
||||
#define BSC_API_CONN_POL_ACCEPT 0
|
||||
#define BSC_API_CONN_POL_REJECT 1
|
||||
|
||||
struct bsc_api {
|
||||
/*! \brief BTS->MSC: tell MSC a SAPI was not established */
|
||||
void (*sapi_n_reject)(struct gsm_subscriber_connection *conn, int dlci);
|
||||
/*! \brief MS->MSC: Tell MSC that ciphering has been enabled */
|
||||
void (*cipher_mode_compl)(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint8_t chosen_encr);
|
||||
/*! \brief MS->MSC: New MM context with L3 payload */
|
||||
int (*compl_l3)(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, uint16_t chosen_channel);
|
||||
/*! \brief MS->BSC/MSC: Um L3 message */
|
||||
void (*dtap)(struct gsm_subscriber_connection *conn, uint8_t link_id,
|
||||
struct msgb *msg);
|
||||
/*! \brief BSC->MSC: Assignment of lchan successful */
|
||||
void (*assign_compl)(struct gsm_subscriber_connection *conn,
|
||||
uint8_t rr_cause, uint8_t chosen_channel,
|
||||
uint8_t encr_alg_id, uint8_t speech_mode);
|
||||
/*! \brief BSC->MSC: Assignment of lchan failed */
|
||||
void (*assign_fail)(struct gsm_subscriber_connection *conn,
|
||||
uint8_t cause, uint8_t *rr_cause);
|
||||
/*! \brief BSC->MSC: RR conn has been cleared */
|
||||
int (*clear_request)(struct gsm_subscriber_connection *conn,
|
||||
uint32_t cause);
|
||||
/*! \brief BSC->MSC: Classmark Update */
|
||||
void (*classmark_chg)(struct gsm_subscriber_connection *conn,
|
||||
const uint8_t *cm2, uint8_t cm2_len,
|
||||
const uint8_t *cm3, uint8_t cm3_len);
|
||||
|
||||
/**
|
||||
* Configure the multirate setting on this channel. If it is
|
||||
* not implemented AMR5.9 will be used.
|
||||
*/
|
||||
void (*mr_config)(struct gsm_subscriber_connection *conn,
|
||||
struct gsm_lchan *lchan, int full_rate);
|
||||
|
||||
/** Callback for additional actions during conn cleanup */
|
||||
void (*conn_cleanup)(struct gsm_subscriber_connection *conn);
|
||||
};
|
||||
|
||||
int bsc_api_init(struct gsm_network *network, struct bsc_api *api);
|
||||
int gsm0808_submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, int link_id, int allow_sacch);
|
||||
int gsm0808_assign_req(struct gsm_subscriber_connection *conn, int chan_mode, int full_rate);
|
||||
int gsm0808_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
|
||||
const uint8_t *key, int len, int include_imeisv);
|
||||
int gsm0808_page(struct gsm_bts *bts, unsigned int page_group,
|
||||
unsigned int mi_len, uint8_t *mi, int chan_type);
|
||||
int gsm0808_clear(struct gsm_subscriber_connection *conn);
|
||||
|
||||
#endif
|
|
@ -1,77 +0,0 @@
|
|||
/* Routines to talk to the MSC using the IPA Protocol */
|
||||
/*
|
||||
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BSC_MSC_H
|
||||
#define BSC_MSC_H
|
||||
|
||||
#include <osmocom/core/write_queue.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
#include <openbsc/a_reset.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
struct bsc_msc_dest {
|
||||
struct llist_head list;
|
||||
|
||||
char *ip;
|
||||
int port;
|
||||
int dscp;
|
||||
};
|
||||
|
||||
|
||||
struct bsc_msc_connection {
|
||||
/* FIXME: Remove stuff that is no longer needed! */
|
||||
struct osmo_wqueue write_queue;
|
||||
int is_connected;
|
||||
int is_authenticated;
|
||||
int first_contact;
|
||||
|
||||
struct llist_head *dests;
|
||||
|
||||
const char *name;
|
||||
|
||||
void (*connection_loss) (struct bsc_msc_connection *);
|
||||
void (*connected) (struct bsc_msc_connection *);
|
||||
struct osmo_timer_list reconnect_timer;
|
||||
struct osmo_timer_list timeout_timer;
|
||||
|
||||
struct msgb *pending_msg;
|
||||
|
||||
/* Sigtran connection data */
|
||||
struct osmo_sccp_instance *sccp;
|
||||
struct osmo_sccp_user *sccp_user;
|
||||
struct osmo_sccp_addr g_calling_addr;
|
||||
struct osmo_sccp_addr g_called_addr;
|
||||
struct a_reset_ctx *reset;
|
||||
|
||||
int conn_id_counter;
|
||||
};
|
||||
|
||||
struct bsc_msc_connection *bsc_msc_create(void *ctx, struct llist_head *dest);
|
||||
int bsc_msc_connect(struct bsc_msc_connection *);
|
||||
void bsc_msc_schedule_connect(struct bsc_msc_connection *);
|
||||
|
||||
void bsc_msc_lost(struct bsc_msc_connection *);
|
||||
|
||||
struct msgb *bsc_msc_id_get_resp(int fixed, const char *token, const uint8_t *res, int len);
|
||||
|
||||
#endif
|
|
@ -1,174 +0,0 @@
|
|||
/*
|
||||
* Data for the true BSC
|
||||
*
|
||||
* (C) 2010-2015 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010-2015 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: This is about a *remote* MSC for OsmoBSC and is not part of libmsc.
|
||||
*/
|
||||
|
||||
#ifndef _OSMO_MSC_DATA_H
|
||||
#define _OSMO_MSC_DATA_H
|
||||
|
||||
#include "bsc_msc.h"
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
|
||||
#include <osmocom/sigtran/osmo_ss7.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
#include <osmocom/sigtran/sccp_helpers.h>
|
||||
#include <osmocom/sigtran/protocol/sua.h>
|
||||
#include <osmocom/sigtran/protocol/m3ua.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
struct osmo_bsc_rf;
|
||||
struct gsm_network;
|
||||
|
||||
struct gsm_audio_support {
|
||||
uint8_t hr : 1,
|
||||
ver : 7;
|
||||
};
|
||||
|
||||
enum {
|
||||
MSC_CON_TYPE_NORMAL,
|
||||
MSC_CON_TYPE_LOCAL,
|
||||
};
|
||||
|
||||
/*! /brief Information on a remote MSC for libbsc.
|
||||
*/
|
||||
struct bsc_msc_data {
|
||||
struct llist_head entry;
|
||||
|
||||
/* Back pointer */
|
||||
struct gsm_network *network;
|
||||
|
||||
int allow_emerg;
|
||||
int type;
|
||||
|
||||
/* local call routing */
|
||||
char *local_pref;
|
||||
regex_t local_pref_reg;
|
||||
|
||||
|
||||
/* Connection data */
|
||||
char *bsc_token;
|
||||
uint8_t bsc_key[16];
|
||||
uint8_t bsc_key_present;
|
||||
|
||||
int ping_timeout;
|
||||
int pong_timeout;
|
||||
struct osmo_timer_list ping_timer;
|
||||
struct osmo_timer_list pong_timer;
|
||||
int advanced_ping;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
int core_mnc;
|
||||
int core_mcc;
|
||||
int core_lac;
|
||||
int core_ci;
|
||||
int rtp_base;
|
||||
|
||||
/* audio codecs */
|
||||
struct gsm48_multi_rate_conf amr_conf;
|
||||
struct gsm_audio_support **audio_support;
|
||||
int audio_length;
|
||||
|
||||
/* destinations */
|
||||
struct llist_head dests;
|
||||
|
||||
/* ussd welcome text */
|
||||
char *ussd_welcome_txt;
|
||||
|
||||
/* mgcp agent */
|
||||
struct osmo_wqueue mgcp_agent;
|
||||
|
||||
int nr;
|
||||
|
||||
/* ussd msc connection lost text */
|
||||
char *ussd_msc_lost_txt;
|
||||
|
||||
/* ussd text when MSC has entered the grace period */
|
||||
char *ussd_grace_txt;
|
||||
|
||||
char *acc_lst_name;
|
||||
|
||||
/* Sigtran connection data */
|
||||
struct {
|
||||
uint32_t cs7_instance;
|
||||
bool cs7_instance_valid;
|
||||
struct osmo_sccp_instance *sccp;
|
||||
struct osmo_sccp_user *sccp_user;
|
||||
|
||||
/* Holds a copy of the our local MSC address,
|
||||
* this will be the sccp-address that is associated
|
||||
* with the A interface of this particular BSC,
|
||||
* this address is filled up by the VTY interface */
|
||||
struct osmo_sccp_addr bsc_addr;
|
||||
char *bsc_addr_name;
|
||||
|
||||
/* Holds a copy of the MSC address. This is the
|
||||
* address of the MSC that handles the calls of
|
||||
* this BSC. The address is configured via the
|
||||
* VTY interface */
|
||||
struct osmo_sccp_addr msc_addr;
|
||||
char *msc_addr_name;
|
||||
|
||||
struct a_reset_ctx *reset;
|
||||
} a;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per BSC data.
|
||||
*/
|
||||
struct osmo_bsc_data {
|
||||
struct gsm_network *network;
|
||||
|
||||
/* msc configuration */
|
||||
struct llist_head mscs;
|
||||
|
||||
/* rf ctl related bits */
|
||||
char *mid_call_txt;
|
||||
int mid_call_timeout;
|
||||
char *rf_ctrl_name;
|
||||
struct osmo_bsc_rf *rf_ctrl;
|
||||
int auto_off_timeout;
|
||||
|
||||
/* ussd text when there is no MSC available */
|
||||
char *ussd_no_msc_txt;
|
||||
|
||||
char *acc_lst_name;
|
||||
};
|
||||
|
||||
|
||||
int osmo_bsc_msc_init(struct bsc_msc_data *msc);
|
||||
int osmo_bsc_sccp_init(struct gsm_network *gsmnet);
|
||||
int msc_queue_write(struct bsc_msc_connection *conn, struct msgb *msg, int proto);
|
||||
int msc_queue_write_with_ping(struct bsc_msc_connection *, struct msgb *msg, int proto);
|
||||
|
||||
int osmo_bsc_audio_init(struct gsm_network *network);
|
||||
|
||||
struct bsc_msc_data *osmo_msc_data_find(struct gsm_network *, int);
|
||||
struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *, int);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,107 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/msgfile.h>
|
||||
#include <osmocom/core/linuxrbtree.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
struct vty;
|
||||
struct gsm48_hdr;
|
||||
|
||||
struct bsc_filter_reject_cause {
|
||||
int lu_reject_cause;
|
||||
int cm_reject_cause;
|
||||
};
|
||||
|
||||
struct bsc_filter_barr_entry {
|
||||
struct rb_node node;
|
||||
|
||||
char *imsi;
|
||||
int cm_reject_cause;
|
||||
int lu_reject_cause;
|
||||
};
|
||||
|
||||
enum bsc_filter_acc_ctr {
|
||||
ACC_LIST_LOCAL_FILTER,
|
||||
ACC_LIST_GLOBAL_FILTER,
|
||||
};
|
||||
|
||||
struct bsc_msg_acc_lst {
|
||||
struct llist_head list;
|
||||
|
||||
/* counter */
|
||||
struct rate_ctr_group *stats;
|
||||
|
||||
/* the name of the list */
|
||||
const char *name;
|
||||
struct llist_head fltr_list;
|
||||
};
|
||||
|
||||
struct bsc_msg_acc_lst_entry {
|
||||
struct llist_head list;
|
||||
|
||||
/* the filter */
|
||||
char *imsi_allow;
|
||||
regex_t imsi_allow_re;
|
||||
char *imsi_deny;
|
||||
regex_t imsi_deny_re;
|
||||
|
||||
/* reject reasons for the access lists */
|
||||
int cm_reject_cause;
|
||||
int lu_reject_cause;
|
||||
};
|
||||
|
||||
enum {
|
||||
FLT_CON_TYPE_NONE,
|
||||
FLT_CON_TYPE_LU,
|
||||
FLT_CON_TYPE_CM_SERV_REQ,
|
||||
FLT_CON_TYPE_PAG_RESP,
|
||||
FLT_CON_TYPE_SSA,
|
||||
FLT_CON_TYPE_LOCAL_REJECT,
|
||||
FLT_CON_TYPE_OTHER,
|
||||
};
|
||||
|
||||
|
||||
struct bsc_filter_state {
|
||||
char *imsi;
|
||||
int imsi_checked;
|
||||
int con_type;
|
||||
};
|
||||
|
||||
struct bsc_filter_request {
|
||||
void *ctx;
|
||||
struct rb_root *black_list;
|
||||
struct llist_head *access_lists;
|
||||
const char *local_lst_name;
|
||||
const char *global_lst_name;
|
||||
int bsc_nr;
|
||||
};
|
||||
|
||||
|
||||
int bsc_filter_barr_adapt(void *ctx, struct rb_root *rbtree, const struct osmo_config_list *);
|
||||
int bsc_filter_barr_find(struct rb_root *root, const char *imsi, int *cm, int *lu);
|
||||
|
||||
/**
|
||||
* Content filtering.
|
||||
*/
|
||||
int bsc_msg_filter_initial(struct gsm48_hdr *hdr, size_t size,
|
||||
struct bsc_filter_request *req,
|
||||
int *con_type, char **imsi,
|
||||
struct bsc_filter_reject_cause *cause);
|
||||
int bsc_msg_filter_data(struct gsm48_hdr *hdr, size_t size,
|
||||
struct bsc_filter_request *req,
|
||||
struct bsc_filter_state *state,
|
||||
struct bsc_filter_reject_cause *cause);
|
||||
|
||||
/* IMSI allow/deny handling */
|
||||
struct bsc_msg_acc_lst *bsc_msg_acc_lst_find(struct llist_head *lst, const char *name);
|
||||
struct bsc_msg_acc_lst *bsc_msg_acc_lst_get(void *ctx, struct llist_head *lst, const char *name);
|
||||
void bsc_msg_acc_lst_delete(struct bsc_msg_acc_lst *lst);
|
||||
|
||||
struct bsc_msg_acc_lst_entry *bsc_msg_acc_lst_entry_create(struct bsc_msg_acc_lst *);
|
||||
int bsc_msg_acc_lst_check_allow(struct bsc_msg_acc_lst *lst, const char *imsi);
|
||||
|
||||
void bsc_msg_lst_vty_init(void *ctx, struct llist_head *lst, int node);
|
||||
void bsc_msg_acc_lst_write(struct vty *vty, struct bsc_msg_acc_lst *lst);
|
|
@ -1,462 +0,0 @@
|
|||
/*
|
||||
* (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010-2012 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BSC_NAT_H
|
||||
#define BSC_NAT_H
|
||||
|
||||
#include "mgcp.h"
|
||||
#include "bsc_msg_filter.h"
|
||||
|
||||
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/msgfile.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/write_queue.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/statistics.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DIR_BSC 1
|
||||
#define DIR_MSC 2
|
||||
|
||||
#define PAGIN_GROUP_UNASSIGNED -1
|
||||
|
||||
struct sccp_source_reference;
|
||||
struct nat_sccp_connection;
|
||||
struct bsc_nat_parsed;
|
||||
struct bsc_nat;
|
||||
struct bsc_nat_ussd_con;
|
||||
struct nat_rewrite_rule;
|
||||
|
||||
/*
|
||||
* Is this terminated to the MSC, to the local machine (release
|
||||
* handling for IMSI filtering) or to a USSD provider?
|
||||
*/
|
||||
enum {
|
||||
NAT_CON_END_MSC,
|
||||
NAT_CON_END_LOCAL,
|
||||
NAT_CON_END_USSD,
|
||||
};
|
||||
|
||||
/*
|
||||
* Pending command entry
|
||||
*/
|
||||
struct bsc_cmd_list {
|
||||
struct llist_head list_entry;
|
||||
|
||||
struct osmo_timer_list timeout;
|
||||
|
||||
/* The NATed ID used on the bsc_con*/
|
||||
int nat_id;
|
||||
|
||||
/* The control connection from which the command originated */
|
||||
struct ctrl_connection *ccon;
|
||||
|
||||
/* The command from the control connection */
|
||||
struct ctrl_cmd *cmd;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per BSC data structure
|
||||
*/
|
||||
struct bsc_connection {
|
||||
struct llist_head list_entry;
|
||||
|
||||
/* do we know anything about this BSC? */
|
||||
int authenticated;
|
||||
uint8_t last_rand[16];
|
||||
|
||||
/* the fd we use to communicate */
|
||||
struct osmo_wqueue write_queue;
|
||||
|
||||
/* incoming message buffer */
|
||||
struct msgb *pending_msg;
|
||||
|
||||
/* the BSS associated */
|
||||
struct bsc_config *cfg;
|
||||
|
||||
/* a timeout node */
|
||||
struct osmo_timer_list id_timeout;
|
||||
|
||||
/* pong timeout */
|
||||
struct osmo_timer_list ping_timeout;
|
||||
struct osmo_timer_list pong_timeout;
|
||||
|
||||
/* mgcp related code */
|
||||
char *_endpoint_status;
|
||||
int number_multiplexes;
|
||||
int max_endpoints;
|
||||
int last_endpoint;
|
||||
int next_transaction;
|
||||
uint32_t pending_dlcx_count;
|
||||
struct llist_head pending_dlcx;
|
||||
|
||||
/* track the pending commands for this BSC */
|
||||
struct llist_head cmd_pending;
|
||||
int last_id;
|
||||
|
||||
/* a back pointer */
|
||||
struct bsc_nat *nat;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stats per BSC
|
||||
*/
|
||||
struct bsc_config_stats {
|
||||
struct rate_ctr_group *ctrg;
|
||||
};
|
||||
|
||||
enum bsc_cfg_ctr {
|
||||
BCFG_CTR_SCCP_CONN,
|
||||
BCFG_CTR_SCCP_CALLS,
|
||||
BCFG_CTR_NET_RECONN,
|
||||
BCFG_CTR_DROPPED_SCCP,
|
||||
BCFG_CTR_DROPPED_CALLS,
|
||||
BCFG_CTR_REJECTED_CR,
|
||||
BCFG_CTR_REJECTED_MSG,
|
||||
BCFG_CTR_ILL_PACKET,
|
||||
BCFG_CTR_CON_TYPE_LU,
|
||||
BCFG_CTR_CON_CMSERV_RQ,
|
||||
BCFG_CTR_CON_PAG_RESP,
|
||||
BCFG_CTR_CON_SSA,
|
||||
BCFG_CTR_CON_OTHER,
|
||||
};
|
||||
|
||||
/**
|
||||
* One BSC entry in the config
|
||||
*/
|
||||
struct bsc_config {
|
||||
struct llist_head entry;
|
||||
|
||||
uint8_t key[16];
|
||||
uint8_t key_present;
|
||||
char *token;
|
||||
int nr;
|
||||
|
||||
char *description;
|
||||
|
||||
/* imsi white and blacklist */
|
||||
char *acc_lst_name;
|
||||
|
||||
int forbid_paging;
|
||||
int paging_group;
|
||||
|
||||
/* audio handling */
|
||||
int max_endpoints;
|
||||
|
||||
/* used internally for reload handling */
|
||||
bool remove;
|
||||
bool token_updated;
|
||||
|
||||
/* backpointer */
|
||||
struct bsc_nat *nat;
|
||||
|
||||
struct bsc_config_stats stats;
|
||||
|
||||
struct llist_head lac_list;
|
||||
|
||||
/* Osmux is enabled/disabled per BSC */
|
||||
int osmux;
|
||||
};
|
||||
|
||||
struct bsc_lac_entry {
|
||||
struct llist_head entry;
|
||||
uint16_t lac;
|
||||
};
|
||||
|
||||
struct bsc_nat_paging_group {
|
||||
struct llist_head entry;
|
||||
|
||||
/* list of lac entries */
|
||||
struct llist_head lists;
|
||||
int nr;
|
||||
};
|
||||
|
||||
/**
|
||||
* BSCs point of view of endpoints
|
||||
*/
|
||||
struct bsc_endpoint {
|
||||
/* the operation that is carried out */
|
||||
int transaction_state;
|
||||
/* the pending transaction id */
|
||||
char *transaction_id;
|
||||
/* the bsc we are talking to */
|
||||
struct bsc_connection *bsc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistic for the nat.
|
||||
*/
|
||||
struct bsc_nat_statistics {
|
||||
struct {
|
||||
struct osmo_counter *conn;
|
||||
struct osmo_counter *calls;
|
||||
} sccp;
|
||||
|
||||
struct {
|
||||
struct osmo_counter *reconn;
|
||||
struct osmo_counter *auth_fail;
|
||||
} bsc;
|
||||
|
||||
struct {
|
||||
struct osmo_counter *reconn;
|
||||
} msc;
|
||||
|
||||
struct {
|
||||
struct osmo_counter *reconn;
|
||||
} ussd;
|
||||
};
|
||||
|
||||
/**
|
||||
* the structure of the "nat" network
|
||||
*/
|
||||
struct bsc_nat {
|
||||
/* active SCCP connections that need patching */
|
||||
struct llist_head sccp_connections;
|
||||
|
||||
/* active BSC connections that need patching */
|
||||
struct llist_head bsc_connections;
|
||||
|
||||
/* access lists */
|
||||
struct llist_head access_lists;
|
||||
|
||||
/* paging groups */
|
||||
struct llist_head paging_groups;
|
||||
|
||||
/* known BSC's */
|
||||
struct llist_head bsc_configs;
|
||||
int num_bsc;
|
||||
int bsc_ip_dscp;
|
||||
|
||||
/* MGCP config */
|
||||
struct mgcp_config *mgcp_cfg;
|
||||
uint8_t mgcp_msg[4096];
|
||||
int mgcp_length;
|
||||
int mgcp_ipa;
|
||||
int sdp_ensure_amr_mode_set;
|
||||
|
||||
/* msc things */
|
||||
struct llist_head dests;
|
||||
struct bsc_msc_dest *main_dest;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
char *token;
|
||||
|
||||
/* timeouts */
|
||||
int auth_timeout;
|
||||
int ping_timeout;
|
||||
int pong_timeout;
|
||||
|
||||
struct bsc_endpoint *bsc_endpoints;
|
||||
|
||||
/* path to file with BSC config */
|
||||
char *include_file;
|
||||
char *include_base;
|
||||
char *resolved_path;
|
||||
|
||||
/* filter */
|
||||
char *acc_lst_name;
|
||||
|
||||
/* Barring of subscribers with a rb tree */
|
||||
struct rb_root imsi_black_list;
|
||||
char *imsi_black_list_fn;
|
||||
|
||||
/* number rewriting */
|
||||
char *num_rewr_name;
|
||||
struct llist_head num_rewr;
|
||||
char *num_rewr_post_name;
|
||||
struct llist_head num_rewr_post;
|
||||
|
||||
char *smsc_rewr_name;
|
||||
struct llist_head smsc_rewr;
|
||||
char *tpdest_match_name;
|
||||
struct llist_head tpdest_match;
|
||||
char *sms_clear_tp_srr_name;
|
||||
struct llist_head sms_clear_tp_srr;
|
||||
char *sms_num_rewr_name;
|
||||
struct llist_head sms_num_rewr;
|
||||
|
||||
/* more rewriting */
|
||||
char *num_rewr_trie_name;
|
||||
struct nat_rewrite *num_rewr_trie;
|
||||
|
||||
/* USSD messages we want to match */
|
||||
char *ussd_lst_name;
|
||||
char *ussd_query;
|
||||
regex_t ussd_query_re;
|
||||
char *ussd_token;
|
||||
char *ussd_local;
|
||||
struct osmo_fd ussd_listen;
|
||||
struct bsc_nat_ussd_con *ussd_con;
|
||||
|
||||
/* for maintainenance */
|
||||
int blocked;
|
||||
|
||||
/* statistics */
|
||||
struct bsc_nat_statistics stats;
|
||||
|
||||
/* control interface */
|
||||
struct ctrl_handle *ctrl;
|
||||
};
|
||||
|
||||
struct bsc_nat_ussd_con {
|
||||
struct osmo_wqueue queue;
|
||||
struct bsc_nat *nat;
|
||||
int authorized;
|
||||
|
||||
struct msgb *pending_msg;
|
||||
|
||||
struct osmo_timer_list auth_timeout;
|
||||
};
|
||||
|
||||
/* create and init the structures */
|
||||
struct bsc_config *bsc_config_alloc(struct bsc_nat *nat, const char *token,
|
||||
unsigned int number);
|
||||
struct bsc_config *bsc_config_num(struct bsc_nat *nat, int num);
|
||||
struct bsc_config *bsc_config_by_token(struct bsc_nat *nat, const char *token, int len);
|
||||
void bsc_config_free(struct bsc_config *);
|
||||
void bsc_config_add_lac(struct bsc_config *cfg, int lac);
|
||||
void bsc_config_del_lac(struct bsc_config *cfg, int lac);
|
||||
int bsc_config_handles_lac(struct bsc_config *cfg, int lac);
|
||||
|
||||
struct bsc_nat *bsc_nat_alloc(void);
|
||||
struct bsc_connection *bsc_connection_alloc(struct bsc_nat *nat);
|
||||
void bsc_nat_set_msc_ip(struct bsc_nat *bsc, const char *ip);
|
||||
|
||||
void sccp_connection_destroy(struct nat_sccp_connection *);
|
||||
void bsc_close_connection(struct bsc_connection *);
|
||||
|
||||
const char *bsc_con_type_to_string(int type);
|
||||
|
||||
/**
|
||||
* parse the given message into the above structure
|
||||
*/
|
||||
struct bsc_nat_parsed *bsc_nat_parse(struct msgb *msg);
|
||||
|
||||
/**
|
||||
* filter based on IP Access header in both directions
|
||||
*/
|
||||
int bsc_nat_filter_ipa(int direction, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
||||
int bsc_nat_vty_init(struct bsc_nat *nat);
|
||||
int bsc_nat_find_paging(struct msgb *msg, const uint8_t **,int *len);
|
||||
|
||||
/**
|
||||
* SCCP patching and handling
|
||||
*/
|
||||
struct nat_sccp_connection *create_sccp_src_ref(struct bsc_connection *bsc, struct bsc_nat_parsed *parsed);
|
||||
int update_sccp_src_ref(struct nat_sccp_connection *sccp, struct bsc_nat_parsed *parsed);
|
||||
void remove_sccp_src_ref(struct bsc_connection *bsc, struct msgb *msg, struct bsc_nat_parsed *parsed);
|
||||
struct nat_sccp_connection *patch_sccp_src_ref_to_bsc(struct msgb *, struct bsc_nat_parsed *, struct bsc_nat *);
|
||||
struct nat_sccp_connection *patch_sccp_src_ref_to_msc(struct msgb *, struct bsc_nat_parsed *, struct bsc_connection *);
|
||||
struct nat_sccp_connection *bsc_nat_find_con_by_bsc(struct bsc_nat *, struct sccp_source_reference *);
|
||||
|
||||
/**
|
||||
* MGCP/Audio handling
|
||||
*/
|
||||
int bsc_mgcp_nr_multiplexes(int max_endpoints);
|
||||
int bsc_write_mgcp(struct bsc_connection *bsc, const uint8_t *data, unsigned int length);
|
||||
int bsc_mgcp_assign_patch(struct nat_sccp_connection *, struct msgb *msg);
|
||||
void bsc_mgcp_init(struct nat_sccp_connection *);
|
||||
void bsc_mgcp_dlcx(struct nat_sccp_connection *);
|
||||
void bsc_mgcp_free_endpoints(struct bsc_nat *nat);
|
||||
int bsc_mgcp_nat_init(struct bsc_nat *nat);
|
||||
|
||||
struct nat_sccp_connection *bsc_mgcp_find_con(struct bsc_nat *, int endpoint_number);
|
||||
struct msgb *bsc_mgcp_rewrite(char *input, int length, int endp, const char *ip,
|
||||
int port, int osmux, int *first_payload_type, int mode_set);
|
||||
void bsc_mgcp_forward(struct bsc_connection *bsc, struct msgb *msg);
|
||||
|
||||
void bsc_mgcp_clear_endpoints_for(struct bsc_connection *bsc);
|
||||
int bsc_mgcp_parse_response(const char *str, int *code, char transaction[60]);
|
||||
uint32_t bsc_mgcp_extract_ci(const char *resp);
|
||||
|
||||
|
||||
int bsc_write(struct bsc_connection *bsc, struct msgb *msg, int id);
|
||||
int bsc_do_write(struct osmo_wqueue *queue, struct msgb *msg, int id);
|
||||
int bsc_write_msg(struct osmo_wqueue *queue, struct msgb *msg);
|
||||
int bsc_write_cb(struct osmo_fd *bfd, struct msgb *msg);
|
||||
|
||||
int bsc_nat_msc_is_connected(struct bsc_nat *nat);
|
||||
|
||||
int bsc_conn_type_to_ctr(struct nat_sccp_connection *conn);
|
||||
|
||||
struct gsm48_hdr *bsc_unpack_dtap(struct bsc_nat_parsed *parsed, struct msgb *msg, uint32_t *len);
|
||||
|
||||
/** USSD filtering */
|
||||
int bsc_ussd_init(struct bsc_nat *nat);
|
||||
int bsc_ussd_check(struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed, struct msgb *msg);
|
||||
int bsc_ussd_close_connections(struct bsc_nat *nat);
|
||||
|
||||
struct msgb *bsc_nat_rewrite_msg(struct bsc_nat *nat, struct msgb *msg, struct bsc_nat_parsed *, const char *imsi);
|
||||
|
||||
/** paging group handling */
|
||||
struct bsc_nat_paging_group *bsc_nat_paging_group_num(struct bsc_nat *nat, int group);
|
||||
struct bsc_nat_paging_group *bsc_nat_paging_group_create(struct bsc_nat *nat, int group);
|
||||
void bsc_nat_paging_group_delete(struct bsc_nat_paging_group *);
|
||||
void bsc_nat_paging_group_add_lac(struct bsc_nat_paging_group *grp, int lac);
|
||||
void bsc_nat_paging_group_del_lac(struct bsc_nat_paging_group *grp, int lac);
|
||||
|
||||
/**
|
||||
* Number rewriting support below
|
||||
*/
|
||||
struct bsc_nat_num_rewr_entry {
|
||||
struct llist_head list;
|
||||
|
||||
regex_t msisdn_reg;
|
||||
regex_t num_reg;
|
||||
|
||||
char *replace;
|
||||
uint8_t is_prefix_lookup;
|
||||
};
|
||||
|
||||
void bsc_nat_num_rewr_entry_adapt(void *ctx, struct llist_head *head, const struct osmo_config_list *);
|
||||
|
||||
void bsc_nat_send_mgcp_to_msc(struct bsc_nat *bsc_nat, struct msgb *msg);
|
||||
void bsc_nat_handle_mgcp(struct bsc_nat *bsc, struct msgb *msg);
|
||||
|
||||
struct ctrl_handle *bsc_nat_controlif_setup(struct bsc_nat *nat,
|
||||
const char *bind_addr, int port);
|
||||
void bsc_nat_ctrl_del_pending(struct bsc_cmd_list *pending);
|
||||
int bsc_nat_handle_ctrlif_msg(struct bsc_connection *bsc, struct msgb *msg);
|
||||
|
||||
int bsc_nat_extract_lac(struct bsc_connection *bsc, struct nat_sccp_connection *con,
|
||||
struct bsc_nat_parsed *parsed, struct msgb *msg);
|
||||
|
||||
int bsc_nat_filter_sccp_cr(struct bsc_connection *bsc, struct msgb *msg,
|
||||
struct bsc_nat_parsed *, int *con_type, char **imsi,
|
||||
struct bsc_filter_reject_cause *cause);
|
||||
int bsc_nat_filter_dt(struct bsc_connection *bsc, struct msgb *msg,
|
||||
struct nat_sccp_connection *con, struct bsc_nat_parsed *parsed,
|
||||
struct bsc_filter_reject_cause *cause);
|
||||
|
||||
/**
|
||||
* CTRL interface helper
|
||||
*/
|
||||
void bsc_nat_inform_reject(struct bsc_connection *bsc, const char *imsi);
|
||||
|
||||
/*
|
||||
* Use for testing
|
||||
*/
|
||||
void bsc_nat_free(struct bsc_nat *nat);
|
||||
|
||||
#endif
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
* (C) 2010-2012 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010-2012 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BSC_NAT_CALLSTATS_H
|
||||
#define BSC_NAT_CALLSTATS_H
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#include <osmocom/sccp/sccp_types.h>
|
||||
|
||||
struct bsc_nat_call_stats {
|
||||
struct llist_head entry;
|
||||
|
||||
struct sccp_source_reference remote_ref;
|
||||
struct sccp_source_reference src_ref; /* as seen by the MSC */
|
||||
|
||||
/* mgcp options */
|
||||
uint32_t ci;
|
||||
int bts_rtp_port;
|
||||
int net_rtp_port;
|
||||
struct in_addr bts_addr;
|
||||
struct in_addr net_addr;
|
||||
|
||||
|
||||
/* as witnessed by the NAT */
|
||||
uint32_t net_ps;
|
||||
uint32_t net_os;
|
||||
uint32_t bts_pr;
|
||||
uint32_t bts_or;
|
||||
uint32_t bts_expected;
|
||||
uint32_t bts_jitter;
|
||||
int bts_loss;
|
||||
|
||||
uint32_t trans_id;
|
||||
int msc_endpoint;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,105 +0,0 @@
|
|||
/* NAT utilities using SCCP types */
|
||||
/*
|
||||
* (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2010 by On-Waves
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BSC_NAT_SCCP_H
|
||||
#define BSC_NAT_SCCP_H
|
||||
|
||||
#include "bsc_msg_filter.h"
|
||||
|
||||
#include <osmocom/sccp/sccp_types.h>
|
||||
|
||||
/*
|
||||
* For the NAT we will need to analyze and later patch
|
||||
* the received message. This would require us to parse
|
||||
* the IPA and SCCP header twice. Instead of doing this
|
||||
* we will have one analyze structure and have the patching
|
||||
* and filter operate on the same structure.
|
||||
*/
|
||||
struct bsc_nat_parsed {
|
||||
/* ip access prototype */
|
||||
int ipa_proto;
|
||||
|
||||
/* source local reference */
|
||||
struct sccp_source_reference *src_local_ref;
|
||||
|
||||
/* destination local reference */
|
||||
struct sccp_source_reference *dest_local_ref;
|
||||
|
||||
/* original value */
|
||||
struct sccp_source_reference original_dest_ref;
|
||||
|
||||
/* called ssn number */
|
||||
int called_ssn;
|
||||
|
||||
/* calling ssn number */
|
||||
int calling_ssn;
|
||||
|
||||
/* sccp message type */
|
||||
int sccp_type;
|
||||
|
||||
/* bssap type, e.g. 0 for BSS Management */
|
||||
int bssap;
|
||||
|
||||
/* the gsm0808 message type */
|
||||
int gsm_type;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per SCCP source local reference patch table. It needs to
|
||||
* be updated on new SCCP connections, connection confirm and reject,
|
||||
* and on the loss of the BSC connection.
|
||||
*/
|
||||
struct nat_sccp_connection {
|
||||
struct llist_head list_entry;
|
||||
|
||||
struct bsc_connection *bsc;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
|
||||
struct sccp_source_reference real_ref;
|
||||
struct sccp_source_reference patched_ref;
|
||||
struct sccp_source_reference remote_ref;
|
||||
int has_remote_ref;
|
||||
|
||||
/* status */
|
||||
int con_local;
|
||||
int authorized;
|
||||
|
||||
struct bsc_filter_state filter_state;
|
||||
|
||||
uint16_t lac;
|
||||
uint16_t ci;
|
||||
|
||||
/* remember which Transactions we run over the bypass */
|
||||
char ussd_ti[8];
|
||||
|
||||
/*
|
||||
* audio handling. Remember if we have ever send a CRCX,
|
||||
* remember the endpoint used by the MSC and BSC.
|
||||
*/
|
||||
int msc_endp;
|
||||
int bsc_endp;
|
||||
|
||||
/* timeout handling */
|
||||
struct timespec creation_time;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef _BSC_RLL_H
|
||||
#define _BSC_RLL_H
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
enum bsc_rllr_ind {
|
||||
BSC_RLLR_IND_EST_CONF,
|
||||
BSC_RLLR_IND_REL_IND,
|
||||
BSC_RLLR_IND_ERR_IND,
|
||||
BSC_RLLR_IND_TIMEOUT,
|
||||
};
|
||||
|
||||
int rll_establish(struct gsm_lchan *lchan, uint8_t link_id,
|
||||
void (*cb)(struct gsm_lchan *, uint8_t, void *,
|
||||
enum bsc_rllr_ind),
|
||||
void *data);
|
||||
void rll_indication(struct gsm_lchan *lchan, uint8_t link_id, uint8_t type);
|
||||
|
||||
#endif /* _BSC_RLL_H */
|
|
@ -1,43 +0,0 @@
|
|||
/* GSM subscriber details for use in BSC land */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
struct log_target;
|
||||
|
||||
struct bsc_subscr {
|
||||
struct llist_head entry;
|
||||
int use_count;
|
||||
|
||||
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
uint32_t tmsi;
|
||||
uint16_t lac;
|
||||
};
|
||||
|
||||
const char *bsc_subscr_name(struct bsc_subscr *bsub);
|
||||
|
||||
struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list,
|
||||
const char *imsi);
|
||||
struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list,
|
||||
uint32_t tmsi);
|
||||
|
||||
struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list,
|
||||
const char *imsi);
|
||||
struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list,
|
||||
uint32_t tmsi);
|
||||
|
||||
void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi);
|
||||
|
||||
struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub,
|
||||
const char *file, int line);
|
||||
struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub,
|
||||
const char *file, int line);
|
||||
#define bsc_subscr_get(bsub) _bsc_subscr_get(bsub, __BASE_FILE__, __LINE__)
|
||||
#define bsc_subscr_put(bsub) _bsc_subscr_put(bsub, __BASE_FILE__, __LINE__)
|
||||
|
||||
void log_set_filter_bsc_subscr(struct log_target *target,
|
||||
struct bsc_subscr *bsub);
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef _BSS_H_
|
||||
#define _BSS_H_
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
struct msgb;
|
||||
|
||||
/* start and stop network */
|
||||
extern int bsc_network_alloc(mncc_recv_cb_t mncc_recv);
|
||||
extern int bsc_network_configure(const char *cfg_file);
|
||||
extern int bsc_shutdown_net(struct gsm_network *net);
|
||||
|
||||
/* register all supported BTS */
|
||||
extern int bts_init(void);
|
||||
extern int bts_model_bs11_init(void);
|
||||
extern int bts_model_rbs2k_init(void);
|
||||
extern int bts_model_nanobts_init(void);
|
||||
extern int bts_model_nokia_site_init(void);
|
||||
extern int bts_model_sysmobts_init(void);
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
/* OML attribute table generator for ipaccess nanobts */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts);
|
||||
struct msgb *nanobts_attr_nse_get(struct gsm_bts *bts);
|
||||
struct msgb *nanobts_attr_cell_get(struct gsm_bts *bts);
|
||||
struct msgb *nanobts_attr_nscv_get(struct gsm_bts *bts);
|
||||
struct msgb *nanobts_attr_radio_get(struct gsm_bts *bts,
|
||||
struct gsm_bts_trx *trx);
|
|
@ -1,54 +0,0 @@
|
|||
/* Management functions to allocate/release struct gsm_lchan */
|
||||
/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef _CHAN_ALLOC_H
|
||||
#define _CHAN_ALLOC_H
|
||||
|
||||
#include "gsm_data.h"
|
||||
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
/* Find an allocated channel for a specified subscriber */
|
||||
struct gsm_subscriber_connection *connection_for_subscr(struct vlr_subscr *vsub);
|
||||
|
||||
/* Allocate a logical channel (SDCCH, TCH, ...) */
|
||||
struct gsm_lchan *lchan_alloc(struct gsm_bts *bts, enum gsm_chan_t type, int allow_bigger);
|
||||
|
||||
/* Free a logical channel (SDCCH, TCH, ...) */
|
||||
void lchan_free(struct gsm_lchan *lchan);
|
||||
void lchan_reset(struct gsm_lchan *lchan);
|
||||
|
||||
/* Release the given lchan */
|
||||
int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode release_mode);
|
||||
|
||||
struct load_counter {
|
||||
unsigned int total;
|
||||
unsigned int used;
|
||||
};
|
||||
|
||||
struct pchan_load {
|
||||
struct load_counter pchan[_GSM_PCHAN_MAX];
|
||||
};
|
||||
|
||||
void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts);
|
||||
void network_chan_load(struct pchan_load *pl, struct gsm_network *net);
|
||||
|
||||
int trx_is_usable(struct gsm_bts_trx *trx);
|
||||
|
||||
#endif /* _CHAN_ALLOC_H */
|
|
@ -1,6 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
enum nsap_addr_enc {
|
||||
NSAP_ADDR_ENC_X213,
|
||||
NSAP_ADDR_ENC_V4RAW,
|
||||
};
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <openbsc/common_cs.h>
|
||||
|
||||
struct gsm_network *bsc_network_init(void *ctx,
|
||||
uint16_t country_code,
|
||||
uint16_t network_code,
|
||||
mncc_recv_cb_t mncc_recv);
|
|
@ -1,27 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct msgb;
|
||||
struct gsm_network;
|
||||
|
||||
typedef int (*mncc_recv_cb_t)(struct gsm_network *, struct msgb *);
|
||||
|
||||
struct vty;
|
||||
|
||||
#define MAX_A5_KEY_LEN (128/8)
|
||||
|
||||
struct gsm_encr {
|
||||
uint8_t alg_id;
|
||||
uint8_t key_len;
|
||||
uint8_t key[MAX_A5_KEY_LEN];
|
||||
};
|
||||
|
||||
struct gsm_network *gsm_network_init(void *ctx,
|
||||
uint16_t country_code,
|
||||
uint16_t network_code,
|
||||
mncc_recv_cb_t mncc_recv);
|
||||
|
||||
int common_cs_vty_init(struct gsm_network *network,
|
||||
int (* config_write_net )(struct vty *));
|
||||
struct gsm_network *gsmnet_from_vty(struct vty *v);
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef _CRC24_H
|
||||
#define _CRC24_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define INIT_CRC24 0xffffff
|
||||
|
||||
uint32_t crc24_calc(uint32_t fcs, uint8_t *cp, unsigned int len);
|
||||
|
||||
#endif
|
|
@ -1,4 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
struct ctrl_handle *bsc_controlif_setup(struct gsm_network *net,
|
||||
const char *bind_addr, uint16_t port);
|
|
@ -1,59 +0,0 @@
|
|||
/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _DB_H
|
||||
#define _DB_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "gsm_subscriber.h"
|
||||
|
||||
struct gsm_equipment;
|
||||
struct gsm_network;
|
||||
struct gsm_auth_info;
|
||||
struct gsm_auth_tuple;
|
||||
struct gsm_sms;
|
||||
|
||||
/* one time initialisation */
|
||||
int db_init(const char *name);
|
||||
int db_prepare(void);
|
||||
int db_fini(void);
|
||||
|
||||
/* SMS store-and-forward */
|
||||
int db_sms_store(struct gsm_sms *sms);
|
||||
struct gsm_sms *db_sms_get(struct gsm_network *net, unsigned long long id);
|
||||
struct gsm_sms *db_sms_get_next_unsent(struct gsm_network *net,
|
||||
unsigned long long min_sms_id,
|
||||
unsigned int max_failed);
|
||||
struct gsm_sms *db_sms_get_next_unsent_rr_msisdn(struct gsm_network *net,
|
||||
const char *last_msisdn,
|
||||
unsigned int max_failed);
|
||||
struct gsm_sms *db_sms_get_unsent_for_subscr(struct vlr_subscr *vsub,
|
||||
unsigned int max_failed);
|
||||
int db_sms_mark_delivered(struct gsm_sms *sms);
|
||||
int db_sms_inc_deliver_attempts(struct gsm_sms *sms);
|
||||
int db_sms_delete_by_msisdn(const char *msisdn);
|
||||
|
||||
/* Statistics counter storage */
|
||||
struct osmo_counter;
|
||||
int db_store_counter(struct osmo_counter *ctr);
|
||||
struct rate_ctr_group;
|
||||
int db_store_rate_ctr_group(struct rate_ctr_group *ctrg);
|
||||
|
||||
#endif /* _DB_H */
|
|
@ -1,47 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#define DEBUG
|
||||
#include <osmocom/core/logging.h>
|
||||
|
||||
/* Debug Areas of the code */
|
||||
enum {
|
||||
DRLL,
|
||||
DCC,
|
||||
DMM,
|
||||
DRR,
|
||||
DRSL,
|
||||
DNM,
|
||||
DMNCC,
|
||||
DPAG,
|
||||
DMEAS,
|
||||
DSCCP,
|
||||
DMSC,
|
||||
DMGCP,
|
||||
DHO,
|
||||
DDB,
|
||||
DREF,
|
||||
DGPRS,
|
||||
DNS,
|
||||
DBSSGP,
|
||||
DLLC,
|
||||
DSNDCP,
|
||||
DSLHC,
|
||||
DNAT,
|
||||
DCTRL,
|
||||
DSMPP,
|
||||
DFILTER,
|
||||
DGTPHUB,
|
||||
DRANAP,
|
||||
DSUA,
|
||||
DV42BIS,
|
||||
DPCU,
|
||||
DVLR,
|
||||
DIUCS,
|
||||
DSIGTRAN,
|
||||
Debug_LastEntry,
|
||||
};
|
||||
|
||||
extern const struct log_info log_info;
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef _E1_CONFIG_H
|
||||
#define _E1_CONFIG_H
|
||||
|
||||
#include <openbsc/gsm_data_shared.h>
|
||||
|
||||
int e1_reconfig_ts(struct gsm_bts_trx_ts *ts);
|
||||
int e1_reconfig_trx(struct gsm_bts_trx *trx);
|
||||
int e1_reconfig_bts(struct gsm_bts *bts);
|
||||
|
||||
#endif /* _E1_CONFIG_H */
|
||||
|
|
@ -1,288 +0,0 @@
|
|||
#ifndef _GB_PROXY_H
|
||||
#define _GB_PROXY_H
|
||||
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
|
||||
#include <osmocom/gprs/gprs_ns.h>
|
||||
#include <osmocom/vty/command.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <regex.h>
|
||||
|
||||
#define GBPROXY_INIT_VU_GEN_TX 256
|
||||
|
||||
struct rate_ctr_group;
|
||||
struct gprs_gb_parse_context;
|
||||
struct tlv_parsed;
|
||||
|
||||
enum gbproxy_global_ctr {
|
||||
GBPROX_GLOB_CTR_INV_BVCI,
|
||||
GBPROX_GLOB_CTR_INV_LAI,
|
||||
GBPROX_GLOB_CTR_INV_RAI,
|
||||
GBPROX_GLOB_CTR_INV_NSEI,
|
||||
GBPROX_GLOB_CTR_PROTO_ERR_BSS,
|
||||
GBPROX_GLOB_CTR_PROTO_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_NOT_SUPPORTED_BSS,
|
||||
GBPROX_GLOB_CTR_NOT_SUPPORTED_SGSN,
|
||||
GBPROX_GLOB_CTR_RESTART_RESET_SGSN,
|
||||
GBPROX_GLOB_CTR_TX_ERR_SGSN,
|
||||
GBPROX_GLOB_CTR_OTHER_ERR,
|
||||
GBPROX_GLOB_CTR_PATCH_PEER_ERR,
|
||||
};
|
||||
|
||||
enum gbproxy_peer_ctr {
|
||||
GBPROX_PEER_CTR_BLOCKED,
|
||||
GBPROX_PEER_CTR_UNBLOCKED,
|
||||
GBPROX_PEER_CTR_DROPPED,
|
||||
GBPROX_PEER_CTR_INV_NSEI,
|
||||
GBPROX_PEER_CTR_TX_ERR,
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_RAID_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_APN_PATCHED,
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_TLLI_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_BSS,
|
||||
GBPROX_PEER_CTR_PTMSI_PATCHED_SGSN,
|
||||
GBPROX_PEER_CTR_PATCH_CRYPT_ERR,
|
||||
GBPROX_PEER_CTR_PATCH_ERR,
|
||||
GBPROX_PEER_CTR_ATTACH_REQS,
|
||||
GBPROX_PEER_CTR_ATTACH_REJS,
|
||||
GBPROX_PEER_CTR_ATTACH_ACKS,
|
||||
GBPROX_PEER_CTR_ATTACH_COMPLS,
|
||||
GBPROX_PEER_CTR_RA_UPD_REQS,
|
||||
GBPROX_PEER_CTR_RA_UPD_REJS,
|
||||
GBPROX_PEER_CTR_RA_UPD_ACKS,
|
||||
GBPROX_PEER_CTR_RA_UPD_COMPLS,
|
||||
GBPROX_PEER_CTR_GMM_STATUS_BSS,
|
||||
GBPROX_PEER_CTR_GMM_STATUS_SGSN,
|
||||
GBPROX_PEER_CTR_DETACH_REQS,
|
||||
GBPROX_PEER_CTR_DETACH_ACKS,
|
||||
GBPROX_PEER_CTR_PDP_ACT_REQS,
|
||||
GBPROX_PEER_CTR_PDP_ACT_REJS,
|
||||
GBPROX_PEER_CTR_PDP_ACT_ACKS,
|
||||
GBPROX_PEER_CTR_PDP_DEACT_REQS,
|
||||
GBPROX_PEER_CTR_PDP_DEACT_ACKS,
|
||||
GBPROX_PEER_CTR_TLLI_UNKNOWN,
|
||||
GBPROX_PEER_CTR_TLLI_CACHE_SIZE,
|
||||
GBPROX_PEER_CTR_LAST,
|
||||
};
|
||||
|
||||
enum gbproxy_keep_mode {
|
||||
GBPROX_KEEP_NEVER,
|
||||
GBPROX_KEEP_REATTACH,
|
||||
GBPROX_KEEP_IDENTIFIED,
|
||||
GBPROX_KEEP_ALWAYS,
|
||||
};
|
||||
|
||||
enum gbproxy_match_id {
|
||||
GBPROX_MATCH_PATCHING,
|
||||
GBPROX_MATCH_ROUTING,
|
||||
GBPROX_MATCH_LAST
|
||||
};
|
||||
|
||||
struct gbproxy_match {
|
||||
int enable;
|
||||
char *re_str;
|
||||
regex_t re_comp;
|
||||
};
|
||||
|
||||
struct gbproxy_config {
|
||||
/* parsed from config file */
|
||||
uint16_t nsip_sgsn_nsei;
|
||||
|
||||
/* misc */
|
||||
struct gprs_ns_inst *nsi;
|
||||
|
||||
/* Linked list of all Gb peers (except SGSN) */
|
||||
struct llist_head bts_peers;
|
||||
|
||||
/* Counter */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
/* force mcc/mnc */
|
||||
int core_mnc;
|
||||
int core_mcc;
|
||||
uint8_t* core_apn;
|
||||
size_t core_apn_size;
|
||||
int tlli_max_age;
|
||||
int tlli_max_len;
|
||||
|
||||
/* Experimental config */
|
||||
int patch_ptmsi;
|
||||
int acquire_imsi;
|
||||
int route_to_sgsn2;
|
||||
uint16_t nsip_sgsn2_nsei;
|
||||
enum gbproxy_keep_mode keep_link_infos;
|
||||
|
||||
/* IMSI checking/matching */
|
||||
struct gbproxy_match matches[GBPROX_MATCH_LAST];
|
||||
};
|
||||
|
||||
struct gbproxy_patch_state {
|
||||
int local_mnc;
|
||||
int local_mcc;
|
||||
|
||||
/* List of TLLIs for which patching is enabled */
|
||||
struct llist_head logical_links;
|
||||
int logical_link_count;
|
||||
};
|
||||
|
||||
struct gbproxy_peer {
|
||||
struct llist_head list;
|
||||
|
||||
/* point back to the config */
|
||||
struct gbproxy_config *cfg;
|
||||
|
||||
/* NSEI of the peer entity */
|
||||
uint16_t nsei;
|
||||
|
||||
/* BVCI used for Point-to-Point to this peer */
|
||||
uint16_t bvci;
|
||||
int blocked;
|
||||
|
||||
/* Routeing Area that this peer is part of (raw 04.08 encoding) */
|
||||
uint8_t ra[6];
|
||||
|
||||
/* Counter */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
struct gbproxy_patch_state patch_state;
|
||||
};
|
||||
|
||||
struct gbproxy_tlli_state {
|
||||
uint32_t current;
|
||||
uint32_t assigned;
|
||||
int bss_validated;
|
||||
int net_validated;
|
||||
|
||||
uint32_t ptmsi;
|
||||
};
|
||||
|
||||
struct gbproxy_link_info {
|
||||
struct llist_head list;
|
||||
|
||||
struct gbproxy_tlli_state tlli;
|
||||
struct gbproxy_tlli_state sgsn_tlli;
|
||||
uint32_t sgsn_nsei;
|
||||
|
||||
time_t timestamp;
|
||||
uint8_t *imsi;
|
||||
size_t imsi_len;
|
||||
|
||||
int imsi_acq_pending;
|
||||
struct llist_head stored_msgs;
|
||||
unsigned vu_gen_tx_bss;
|
||||
|
||||
int is_deregistered;
|
||||
|
||||
int is_matching[GBPROX_MATCH_LAST];
|
||||
};
|
||||
|
||||
|
||||
/* gb_proxy_vty .c */
|
||||
|
||||
int gbproxy_vty_init(void);
|
||||
int gbproxy_parse_config(const char *config_file, struct gbproxy_config *cfg);
|
||||
|
||||
|
||||
/* gb_proxy.c */
|
||||
int gbproxy_init_config(struct gbproxy_config *cfg);
|
||||
|
||||
/* Main input function for Gb proxy */
|
||||
int gbprox_rcvmsg(struct gbproxy_config *cfg, struct msgb *msg, uint16_t nsei, uint16_t ns_bvci, uint16_t nsvci);
|
||||
|
||||
int gbprox_signal(unsigned int subsys, unsigned int signal,
|
||||
void *handler_data, void *signal_data);
|
||||
|
||||
/* Reset all persistent NS-VC's */
|
||||
int gbprox_reset_persistent_nsvcs(struct gprs_ns_inst *nsi);
|
||||
|
||||
void gbprox_reset(struct gbproxy_config *cfg);
|
||||
|
||||
/* TLLI info handling */
|
||||
void gbproxy_delete_link_infos(struct gbproxy_peer *peer);
|
||||
struct gbproxy_link_info *gbproxy_update_link_state_ul(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
struct gbproxy_link_info *gbproxy_update_link_state_dl(
|
||||
struct gbproxy_peer *peer, time_t now,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
int gbproxy_update_link_state_after(
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
time_t now, struct gprs_gb_parse_context *parse_ctx);
|
||||
int gbproxy_remove_stale_link_infos(struct gbproxy_peer *peer, time_t now);
|
||||
void gbproxy_delete_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info);
|
||||
void gbproxy_link_info_discard_messages(struct gbproxy_link_info *link_info);
|
||||
|
||||
void gbproxy_attach_link_info(struct gbproxy_peer *peer, time_t now,
|
||||
struct gbproxy_link_info *link_info);
|
||||
void gbproxy_update_link_info(struct gbproxy_link_info *link_info,
|
||||
const uint8_t *imsi, size_t imsi_len);
|
||||
void gbproxy_detach_link_info(struct gbproxy_peer *peer,
|
||||
struct gbproxy_link_info *link_info);
|
||||
struct gbproxy_link_info *gbproxy_link_info_alloc( struct gbproxy_peer *peer);
|
||||
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_imsi(
|
||||
struct gbproxy_peer *peer, const uint8_t *imsi, size_t imsi_len);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_any_sgsn_tlli(
|
||||
struct gbproxy_peer *peer, uint32_t tlli);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_sgsn_tlli(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t tlli, uint32_t sgsn_nsei);
|
||||
struct gbproxy_link_info *gbproxy_link_info_by_ptmsi(
|
||||
struct gbproxy_peer *peer,
|
||||
uint32_t ptmsi);
|
||||
|
||||
int gbproxy_imsi_matches(
|
||||
struct gbproxy_config *cfg,
|
||||
enum gbproxy_match_id match_id,
|
||||
struct gbproxy_link_info *link_info);
|
||||
uint32_t gbproxy_map_tlli(
|
||||
uint32_t other_tlli, struct gbproxy_link_info *link_info, int to_bss);
|
||||
|
||||
/* needed by gb_proxy_tlli.h */
|
||||
uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_peer *peer, uint32_t sgsn_ptmsi);
|
||||
uint32_t gbproxy_make_sgsn_tlli(
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
uint32_t bss_tlli);
|
||||
void gbproxy_reset_link(struct gbproxy_link_info *link_info);
|
||||
int gbproxy_check_imsi(
|
||||
struct gbproxy_match *match, const uint8_t *imsi, size_t imsi_len);
|
||||
|
||||
/* Message patching */
|
||||
void gbproxy_patch_bssgp(
|
||||
struct msgb *msg, uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
int *len_change, struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
int gbproxy_patch_llc(
|
||||
struct msgb *msg, uint8_t *llc, size_t llc_len,
|
||||
struct gbproxy_peer *peer, struct gbproxy_link_info *link_info,
|
||||
int *len_change, struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
int gbproxy_set_patch_filter(
|
||||
struct gbproxy_match *match, const char *filter, const char **err_msg);
|
||||
void gbproxy_clear_patch_filter(struct gbproxy_match *match);
|
||||
|
||||
/* Peer handling */
|
||||
struct gbproxy_peer *gbproxy_peer_by_bvci(
|
||||
struct gbproxy_config *cfg, uint16_t bvci);
|
||||
struct gbproxy_peer *gbproxy_peer_by_nsei(
|
||||
struct gbproxy_config *cfg, uint16_t nsei);
|
||||
struct gbproxy_peer *gbproxy_peer_by_rai(
|
||||
struct gbproxy_config *cfg, const uint8_t *ra);
|
||||
struct gbproxy_peer *gbproxy_peer_by_lai(
|
||||
struct gbproxy_config *cfg, const uint8_t *la);
|
||||
struct gbproxy_peer *gbproxy_peer_by_lac(
|
||||
struct gbproxy_config *cfg, const uint8_t *la);
|
||||
struct gbproxy_peer *gbproxy_peer_by_bssgp_tlv(
|
||||
struct gbproxy_config *cfg, struct tlv_parsed *tp);
|
||||
struct gbproxy_peer *gbproxy_peer_alloc(struct gbproxy_config *cfg, uint16_t bvci);
|
||||
void gbproxy_peer_free(struct gbproxy_peer *peer);
|
||||
int gbproxy_cleanup_peers(struct gbproxy_config *cfg, uint16_t nsei, uint16_t bvci);
|
||||
|
||||
#endif
|
|
@ -1,59 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <openbsc/gprs_llc.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct gprs_gb_parse_context {
|
||||
/* Pointer to protocol specific parts */
|
||||
struct gsm48_hdr *g48_hdr;
|
||||
struct bssgp_normal_hdr *bgp_hdr;
|
||||
struct bssgp_ud_hdr *bud_hdr;
|
||||
uint8_t *bssgp_data;
|
||||
size_t bssgp_data_len;
|
||||
uint8_t *llc;
|
||||
size_t llc_len;
|
||||
|
||||
/* Extracted information */
|
||||
struct gprs_llc_hdr_parsed llc_hdr_parsed;
|
||||
struct tlv_parsed bssgp_tp;
|
||||
int to_bss;
|
||||
uint8_t *tlli_enc;
|
||||
uint8_t *old_tlli_enc;
|
||||
uint8_t *imsi;
|
||||
size_t imsi_len;
|
||||
uint8_t *apn_ie;
|
||||
size_t apn_ie_len;
|
||||
uint8_t *ptmsi_enc;
|
||||
uint8_t *new_ptmsi_enc;
|
||||
uint8_t *raid_enc;
|
||||
uint8_t *old_raid_enc;
|
||||
uint8_t *bssgp_raid_enc;
|
||||
uint8_t *bssgp_ptmsi_enc;
|
||||
|
||||
/* General info */
|
||||
const char *llc_msg_name;
|
||||
int invalidate_tlli;
|
||||
int await_reattach;
|
||||
int need_decryption;
|
||||
uint32_t tlli;
|
||||
int pdu_type;
|
||||
int old_raid_is_foreign;
|
||||
int peer_nsei;
|
||||
};
|
||||
|
||||
int gprs_gb_parse_dtap(uint8_t *data, size_t data_len,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
int gprs_gb_parse_llc(uint8_t *llc, size_t llc_len,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
int gprs_gb_parse_bssgp(uint8_t *bssgp, size_t bssgp_len,
|
||||
struct gprs_gb_parse_context *parse_ctx);
|
||||
|
||||
const char *gprs_gb_message_name(const struct gprs_gb_parse_context *parse_ctx,
|
||||
const char *default_msg_name);
|
||||
|
||||
void gprs_gb_log_parse_context(int log_level,
|
||||
struct gprs_gb_parse_context *parse_ctx,
|
||||
const char *default_msg_name);
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef _GPRS_GMM_H
|
||||
#define _GPRS_GMM_H
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <openbsc/gprs_sgsn.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
int gsm48_tx_gsm_deact_pdp_req(struct sgsn_pdp_ctx *pdp, uint8_t sm_cause);
|
||||
int gsm48_tx_gsm_act_pdp_rej(struct sgsn_mm_ctx *mm, uint8_t tid,
|
||||
uint8_t cause, uint8_t pco_len, uint8_t *pco_v);
|
||||
int gsm48_tx_gsm_act_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
int gsm48_tx_gsm_deact_pdp_acc(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
int gsm0408_gprs_rcvmsg_gb(struct msgb *msg, struct gprs_llc_llme *llme,
|
||||
bool drop_cipherable);
|
||||
int gsm0408_gprs_rcvmsg_iu(struct msgb *msg, struct gprs_ra_id *ra_id,
|
||||
uint16_t *sai);
|
||||
int gsm0408_gprs_force_reattach(struct sgsn_mm_ctx *mmctx);
|
||||
int gsm0408_gprs_force_reattach_oldmsg(struct msgb *msg,
|
||||
struct gprs_llc_llme *llme);
|
||||
void gsm0408_gprs_access_granted(struct sgsn_mm_ctx *mmctx);
|
||||
void gsm0408_gprs_access_denied(struct sgsn_mm_ctx *mmctx, int gmm_cause);
|
||||
void gsm0408_gprs_access_cancelled(struct sgsn_mm_ctx *mmctx, int gmm_cause);
|
||||
void gsm0408_gprs_authenticate(struct sgsn_mm_ctx *mmctx);
|
||||
|
||||
int gprs_gmm_rx_suspend(struct gprs_ra_id *raid, uint32_t tlli);
|
||||
int gprs_gmm_rx_resume(struct gprs_ra_id *raid, uint32_t tlli,
|
||||
uint8_t suspend_ref);
|
||||
|
||||
time_t gprs_max_time_to_idle(void);
|
||||
|
||||
int iu_rab_act_ps(uint8_t rab_id, struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
#endif /* _GPRS_GMM_H */
|
|
@ -1,284 +0,0 @@
|
|||
#ifndef _GPRS_LLC_H
|
||||
#define _GPRS_LLC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <openbsc/gprs_sgsn.h>
|
||||
#include <openbsc/gprs_llc_xid.h>
|
||||
|
||||
/* Section 4.7 LLC Layer Structure */
|
||||
enum gprs_llc_sapi {
|
||||
GPRS_SAPI_GMM = 1,
|
||||
GPRS_SAPI_TOM2 = 2,
|
||||
GPRS_SAPI_SNDCP3 = 3,
|
||||
GPRS_SAPI_SNDCP5 = 5,
|
||||
GPRS_SAPI_SMS = 7,
|
||||
GPRS_SAPI_TOM8 = 8,
|
||||
GPRS_SAPI_SNDCP9 = 9,
|
||||
GPRS_SAPI_SNDCP11 = 11,
|
||||
};
|
||||
|
||||
/* Section 6.4 Commands and Responses */
|
||||
enum gprs_llc_u_cmd {
|
||||
GPRS_LLC_U_DM_RESP = 0x01,
|
||||
GPRS_LLC_U_DISC_CMD = 0x04,
|
||||
GPRS_LLC_U_UA_RESP = 0x06,
|
||||
GPRS_LLC_U_SABM_CMD = 0x07,
|
||||
GPRS_LLC_U_FRMR_RESP = 0x08,
|
||||
GPRS_LLC_U_XID = 0x0b,
|
||||
GPRS_LLC_U_NULL_CMD = 0x00,
|
||||
};
|
||||
|
||||
/* Section 6.4.1.6 / Table 6 */
|
||||
enum gprs_llc_xid_type {
|
||||
GPRS_LLC_XID_T_VERSION = 0,
|
||||
GPRS_LLC_XID_T_IOV_UI = 1,
|
||||
GPRS_LLC_XID_T_IOV_I = 2,
|
||||
GPRS_LLC_XID_T_T200 = 3,
|
||||
GPRS_LLC_XID_T_N200 = 4,
|
||||
GPRS_LLC_XID_T_N201_U = 5,
|
||||
GPRS_LLC_XID_T_N201_I = 6,
|
||||
GPRS_LLC_XID_T_mD = 7,
|
||||
GPRS_LLC_XID_T_mU = 8,
|
||||
GPRS_LLC_XID_T_kD = 9,
|
||||
GPRS_LLC_XID_T_kU = 10,
|
||||
GPRS_LLC_XID_T_L3_PAR = 11,
|
||||
GPRS_LLC_XID_T_RESET = 12,
|
||||
};
|
||||
|
||||
extern const struct value_string gprs_llc_xid_type_names[];
|
||||
|
||||
/* TS 04.64 Section 7.1.2 Table 7: LLC layer primitives (GMM/SNDCP/SMS/TOM) */
|
||||
/* TS 04.65 Section 5.1.2 Table 2: Service primitives used by SNDCP */
|
||||
enum gprs_llc_primitive {
|
||||
/* GMM <-> LLME */
|
||||
LLGMM_ASSIGN_REQ, /* GMM tells us new TLLI: TLLI old, TLLI new, Kc, CiphAlg */
|
||||
LLGMM_RESET_REQ, /* GMM tells us to perform XID negotiation: TLLI */
|
||||
LLGMM_RESET_CNF, /* LLC informs GMM that XID has completed: TLLI */
|
||||
LLGMM_SUSPEND_REQ, /* GMM tells us MS has suspended: TLLI, Page */
|
||||
LLGMM_RESUME_REQ, /* GMM tells us MS has resumed: TLLI */
|
||||
LLGMM_PAGE_IND, /* LLC asks GMM to page MS: TLLI */
|
||||
LLGMM_IOV_REQ, /* GMM tells us to perform XID: TLLI */
|
||||
LLGMM_STATUS_IND, /* LLC informs GMM about error: TLLI, Cause */
|
||||
/* LLE <-> (GMM/SNDCP/SMS/TOM) */
|
||||
LL_RESET_IND, /* TLLI */
|
||||
LL_ESTABLISH_REQ, /* TLLI, XID Req */
|
||||
LL_ESTABLISH_IND, /* TLLI, XID Req, N201-I, N201-U */
|
||||
LL_ESTABLISH_RESP, /* TLLI, XID Negotiated */
|
||||
LL_ESTABLISH_CONF, /* TLLI, XID Neg, N201-i, N201-U */
|
||||
LL_RELEASE_REQ, /* TLLI, Local */
|
||||
LL_RELEASE_IND, /* TLLI, Cause */
|
||||
LL_RELEASE_CONF, /* TLLI */
|
||||
LL_XID_REQ, /* TLLI, XID Requested */
|
||||
LL_XID_IND, /* TLLI, XID Req, N201-I, N201-U */
|
||||
LL_XID_RESP, /* TLLI, XID Negotiated */
|
||||
LL_XID_CONF, /* TLLI, XID Neg, N201-I, N201-U */
|
||||
LL_DATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
|
||||
LL_DATA_IND, /* TLLI, SN-PDU */
|
||||
LL_DATA_CONF, /* TLLI, Ref */
|
||||
LL_UNITDATA_REQ, /* TLLI, SN-PDU, Ref, QoS, Radio Prio, Ciph */
|
||||
LL_UNITDATA_IND, /* TLLI, SN-PDU */
|
||||
LL_STATUS_IND, /* TLLI, Cause */
|
||||
};
|
||||
|
||||
/* Section 4.5.2 Logical Link States + Annex C.2 */
|
||||
enum gprs_llc_lle_state {
|
||||
GPRS_LLES_UNASSIGNED = 1, /* No TLLI yet */
|
||||
GPRS_LLES_ASSIGNED_ADM = 2, /* TLLI assigned */
|
||||
GPRS_LLES_LOCAL_EST = 3, /* Local Establishment */
|
||||
GPRS_LLES_REMOTE_EST = 4, /* Remote Establishment */
|
||||
GPRS_LLES_ABM = 5,
|
||||
GPRS_LLES_LOCAL_REL = 6, /* Local Release */
|
||||
GPRS_LLES_TIMER_REC = 7, /* Timer Recovery */
|
||||
};
|
||||
|
||||
enum gprs_llc_llme_state {
|
||||
GPRS_LLMS_UNASSIGNED = 1, /* No TLLI yet */
|
||||
GPRS_LLMS_ASSIGNED = 2, /* TLLI assigned */
|
||||
};
|
||||
|
||||
/* Section 8.9.9 LLC layer parameter default values */
|
||||
struct gprs_llc_params {
|
||||
uint16_t iov_i_exp;
|
||||
uint16_t t200_201;
|
||||
uint16_t n200;
|
||||
uint16_t n201_u;
|
||||
uint16_t n201_i;
|
||||
uint16_t mD;
|
||||
uint16_t mU;
|
||||
uint16_t kD;
|
||||
uint16_t kU;
|
||||
};
|
||||
|
||||
/* Section 4.7.1: Logical Link Entity: One per DLCI (TLLI + SAPI) */
|
||||
struct gprs_llc_lle {
|
||||
struct llist_head list;
|
||||
|
||||
uint32_t sapi;
|
||||
|
||||
struct gprs_llc_llme *llme;
|
||||
|
||||
enum gprs_llc_lle_state state;
|
||||
|
||||
struct osmo_timer_list t200;
|
||||
struct osmo_timer_list t201; /* wait for acknowledgement */
|
||||
|
||||
uint16_t v_sent;
|
||||
uint16_t v_ack;
|
||||
uint16_t v_recv;
|
||||
|
||||
uint16_t vu_send;
|
||||
uint16_t vu_recv;
|
||||
|
||||
/* non-standard LLC state */
|
||||
uint16_t vu_recv_last;
|
||||
uint16_t vu_recv_duplicates;
|
||||
|
||||
/* Overflow Counter for ABM */
|
||||
uint32_t oc_i_send;
|
||||
uint32_t oc_i_recv;
|
||||
|
||||
/* Overflow Counter for unconfirmed transfer */
|
||||
uint32_t oc_ui_send;
|
||||
uint32_t oc_ui_recv;
|
||||
|
||||
unsigned int retrans_ctr;
|
||||
|
||||
struct gprs_llc_params params;
|
||||
};
|
||||
|
||||
#define NUM_SAPIS 16
|
||||
|
||||
struct gprs_llc_llme {
|
||||
struct llist_head list;
|
||||
|
||||
enum gprs_llc_llme_state state;
|
||||
|
||||
uint32_t tlli;
|
||||
uint32_t old_tlli;
|
||||
|
||||
/* Crypto parameters */
|
||||
enum gprs_ciph_algo algo;
|
||||
uint8_t kc[16];
|
||||
uint8_t cksn;
|
||||
/* 3GPP TS 44.064 § 8.9.2: */
|
||||
uint32_t iov_ui;
|
||||
|
||||
/* over which BSSGP BTS ctx do we need to transmit */
|
||||
uint16_t bvci;
|
||||
uint16_t nsei;
|
||||
struct gprs_llc_lle lle[NUM_SAPIS];
|
||||
|
||||
/* Copy of the XID fields we have sent with the last
|
||||
* network originated XID-Request. Since the phone
|
||||
* may strip the optional fields in the confirmation
|
||||
* we need to remeber those fields in order to be
|
||||
* able to create the compression entity. */
|
||||
struct llist_head *xid;
|
||||
|
||||
/* Compression entities */
|
||||
struct {
|
||||
/* In these two list_heads we will store the
|
||||
* data and protocol compression entities,
|
||||
* together with their compression states */
|
||||
struct llist_head *proto;
|
||||
struct llist_head *data;
|
||||
} comp;
|
||||
|
||||
/* Internal management */
|
||||
uint32_t age_timestamp;
|
||||
};
|
||||
|
||||
#define GPRS_LLME_RESET_AGE (0)
|
||||
|
||||
extern struct llist_head gprs_llc_llmes;
|
||||
|
||||
/* LLC low level types */
|
||||
|
||||
enum gprs_llc_cmd {
|
||||
GPRS_LLC_NULL,
|
||||
GPRS_LLC_RR,
|
||||
GPRS_LLC_ACK,
|
||||
GPRS_LLC_RNR,
|
||||
GPRS_LLC_SACK,
|
||||
GPRS_LLC_DM,
|
||||
GPRS_LLC_DISC,
|
||||
GPRS_LLC_UA,
|
||||
GPRS_LLC_SABM,
|
||||
GPRS_LLC_FRMR,
|
||||
GPRS_LLC_XID,
|
||||
GPRS_LLC_UI,
|
||||
};
|
||||
|
||||
struct gprs_llc_hdr_parsed {
|
||||
uint8_t sapi;
|
||||
uint8_t is_cmd:1,
|
||||
ack_req:1,
|
||||
is_encrypted:1;
|
||||
uint32_t seq_rx;
|
||||
uint32_t seq_tx;
|
||||
uint32_t fcs;
|
||||
uint32_t fcs_calc;
|
||||
uint8_t *data;
|
||||
uint16_t data_len;
|
||||
uint16_t crc_length;
|
||||
enum gprs_llc_cmd cmd;
|
||||
};
|
||||
|
||||
|
||||
/* BSSGP-UL-UNITDATA.ind */
|
||||
int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv);
|
||||
|
||||
/* LL-UNITDATA.req */
|
||||
int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command,
|
||||
struct sgsn_mm_ctx *mmctx, bool encryptable);
|
||||
|
||||
/* Chapter 7.2.1.2 LLGMM-RESET.req */
|
||||
int gprs_llgmm_reset(struct gprs_llc_llme *llme);
|
||||
int gprs_llgmm_reset_oldmsg(struct msgb* oldmsg, uint8_t sapi,
|
||||
struct gprs_llc_llme *llme);
|
||||
|
||||
/* Set of LL-XID negotiation (See also: TS 101 351, Section 7.2.2.4) */
|
||||
int gprs_ll_xid_req(struct gprs_llc_lle *lle,
|
||||
struct gprs_llc_xid_field *l3_xid_field);
|
||||
|
||||
/* 04.64 Chapter 7.2.1.1 LLGMM-ASSIGN */
|
||||
int gprs_llgmm_assign(struct gprs_llc_llme *llme,
|
||||
uint32_t old_tlli, uint32_t new_tlli);
|
||||
int gprs_llgmm_unassign(struct gprs_llc_llme *llme);
|
||||
|
||||
int gprs_llc_init(const char *cipher_plugin_path);
|
||||
int gprs_llc_vty_init(void);
|
||||
|
||||
/**
|
||||
* \short Check if N(U) should be considered a retransmit
|
||||
*
|
||||
* Implements the range check as of GSM 04.64 8.4.2
|
||||
* Receipt of unacknowledged information.
|
||||
*
|
||||
* @returns Returns 1 if (V(UR)-32) <= N(U) < V(UR)
|
||||
* @param nu N(U) unconfirmed sequence number of the UI frame
|
||||
* @param vur V(UR) unconfirmend received state variable
|
||||
*/
|
||||
static inline int gprs_llc_is_retransmit(uint16_t nu, uint16_t vur)
|
||||
{
|
||||
int delta = (vur - nu) & 0x1ff;
|
||||
return 0 < delta && delta < 32;
|
||||
}
|
||||
|
||||
/* LLC low level functions */
|
||||
void gprs_llme_copy_key(struct sgsn_mm_ctx *mm, struct gprs_llc_llme *llme);
|
||||
|
||||
/* parse a GPRS LLC header, also check for invalid frames */
|
||||
int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp,
|
||||
uint8_t *llc_hdr, int len);
|
||||
void gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph, struct gprs_llc_lle *lle);
|
||||
int gprs_llc_fcs(uint8_t *data, unsigned int len);
|
||||
|
||||
|
||||
/* LLME handling routines */
|
||||
struct llist_head *gprs_llme_list(void);
|
||||
struct gprs_llc_lle *gprs_lle_get_or_create(const uint32_t tlli, uint8_t sapi);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,57 +0,0 @@
|
|||
/* GPRS LLC XID field encoding/decoding as per 3GPP TS 44.064 */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
/* 3GPP TS 44.064 6.4.1.6 Exchange Identification (XID)
|
||||
command/response parameter field */
|
||||
struct gprs_llc_xid_field {
|
||||
struct llist_head list;
|
||||
uint8_t type; /* See also Table 6: LLC layer parameter
|
||||
negotiation */
|
||||
uint8_t *data; /* Payload data (memory is owned by the
|
||||
* creator of the struct) */
|
||||
unsigned int data_len; /* Payload length */
|
||||
};
|
||||
|
||||
/* Transform a list with XID fields into a XID message (dst) */
|
||||
int gprs_llc_compile_xid(uint8_t *dst, int dst_maxlen,
|
||||
const struct llist_head *xid_fields);
|
||||
|
||||
/* Transform a XID message (dst) into a list of XID fields */
|
||||
struct llist_head *gprs_llc_parse_xid(const void *ctx, const uint8_t *src,
|
||||
int src_len);
|
||||
|
||||
/* Create a duplicate of an XID-Field */
|
||||
struct gprs_llc_xid_field *gprs_llc_dup_xid_field(const void *ctx,
|
||||
const struct gprs_llc_xid_field *xid_field);
|
||||
|
||||
/* Copy an llist with xid fields */
|
||||
struct llist_head *gprs_llc_copy_xid(const void *ctx,
|
||||
const struct llist_head *xid_fields);
|
||||
|
||||
/* Dump a list with XID fields (Debug) */
|
||||
void gprs_llc_dump_xid_fields(const struct llist_head *xid_fields,
|
||||
unsigned int logl);
|
||||
|
|
@ -1,478 +0,0 @@
|
|||
#ifndef _GPRS_SGSN_H
|
||||
#define _GPRS_SGSN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/crypt/gprs_cipher.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
#define GSM_EXTENSION_LENGTH 15
|
||||
#define GSM_APN_LENGTH 102
|
||||
|
||||
struct gprs_llc_lle;
|
||||
struct ctrl_handle;
|
||||
struct gprs_subscr;
|
||||
|
||||
enum gsm48_gsm_cause;
|
||||
|
||||
/* TS 04.08 4.1.3.3 GMM mobility management states on the network side */
|
||||
enum gprs_gmm_state {
|
||||
GMM_DEREGISTERED, /* 4.1.3.3.1.1 */
|
||||
GMM_COMMON_PROC_INIT, /* 4.1.3.3.1.2 */
|
||||
GMM_REGISTERED_NORMAL, /* 4.1.3.3.2.1 */
|
||||
GMM_REGISTERED_SUSPENDED, /* 4.1.3.3.2.2 */
|
||||
GMM_DEREGISTERED_INIT, /* 4.1.3.3.1.4 */
|
||||
};
|
||||
|
||||
/* TS 23.060 6.1.1 and 6.1.2 Mobility management states A/Gb and Iu mode */
|
||||
enum gprs_pmm_state {
|
||||
PMM_DETACHED,
|
||||
PMM_CONNECTED,
|
||||
PMM_IDLE,
|
||||
MM_IDLE,
|
||||
MM_READY,
|
||||
MM_STANDBY,
|
||||
};
|
||||
|
||||
enum gprs_mm_ctr {
|
||||
GMM_CTR_PKTS_SIG_IN,
|
||||
GMM_CTR_PKTS_SIG_OUT,
|
||||
GMM_CTR_PKTS_UDATA_IN,
|
||||
GMM_CTR_PKTS_UDATA_OUT,
|
||||
GMM_CTR_BYTES_UDATA_IN,
|
||||
GMM_CTR_BYTES_UDATA_OUT,
|
||||
GMM_CTR_PDP_CTX_ACT,
|
||||
GMM_CTR_SUSPEND,
|
||||
GMM_CTR_PAGING_PS,
|
||||
GMM_CTR_PAGING_CS,
|
||||
GMM_CTR_RA_UPDATE,
|
||||
};
|
||||
|
||||
enum gprs_pdp_ctx {
|
||||
PDP_CTR_PKTS_UDATA_IN,
|
||||
PDP_CTR_PKTS_UDATA_OUT,
|
||||
PDP_CTR_BYTES_UDATA_IN,
|
||||
PDP_CTR_BYTES_UDATA_OUT,
|
||||
};
|
||||
|
||||
enum gprs_t3350_mode {
|
||||
GMM_T3350_MODE_NONE,
|
||||
GMM_T3350_MODE_ATT,
|
||||
GMM_T3350_MODE_RAU,
|
||||
GMM_T3350_MODE_PTMSI_REALL,
|
||||
};
|
||||
|
||||
/* Authorization/ACL handling */
|
||||
enum sgsn_auth_state {
|
||||
SGSN_AUTH_UNKNOWN,
|
||||
SGSN_AUTH_AUTHENTICATE,
|
||||
SGSN_AUTH_UMTS_RESYNC,
|
||||
SGSN_AUTH_ACCEPTED,
|
||||
SGSN_AUTH_REJECTED
|
||||
};
|
||||
|
||||
#define MS_RADIO_ACCESS_CAPA
|
||||
|
||||
enum sgsn_ggsn_lookup_state {
|
||||
SGSN_GGSN_2DIGIT,
|
||||
SGSN_GGSN_3DIGIT,
|
||||
};
|
||||
|
||||
struct sgsn_ggsn_lookup {
|
||||
int state;
|
||||
|
||||
struct sgsn_mm_ctx *mmctx;
|
||||
|
||||
/* APN string */
|
||||
char apn_str[GSM_APN_LENGTH];
|
||||
|
||||
/* the original data */
|
||||
struct msgb *orig_msg;
|
||||
struct tlv_parsed tp;
|
||||
|
||||
/* for dealing with re-transmissions */
|
||||
uint8_t nsapi;
|
||||
uint8_t sapi;
|
||||
uint8_t ti;
|
||||
};
|
||||
|
||||
enum sgsn_ran_type {
|
||||
/* GPRS/EDGE via Gb */
|
||||
MM_CTX_T_GERAN_Gb,
|
||||
/* UMTS via Iu */
|
||||
MM_CTX_T_UTRAN_Iu,
|
||||
/* GPRS/EDGE via Iu */
|
||||
MM_CTX_T_GERAN_Iu,
|
||||
};
|
||||
|
||||
struct service_info {
|
||||
uint8_t type;
|
||||
uint16_t pdp_status;
|
||||
};
|
||||
|
||||
struct ranap_ue_conn_ctx;
|
||||
|
||||
/* According to TS 03.60, Table 5: SGSN MM and PDP Contexts */
|
||||
/* Extended by 3GPP TS 23.060, Table 6: SGSN MM and PDP Contexts */
|
||||
struct sgsn_mm_ctx {
|
||||
struct llist_head list;
|
||||
|
||||
enum sgsn_ran_type ran_type;
|
||||
|
||||
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
enum gprs_gmm_state gmm_state;
|
||||
enum gprs_pmm_state pmm_state; /* Iu: page when in PMM-IDLE mode */
|
||||
uint32_t p_tmsi;
|
||||
uint32_t p_tmsi_old; /* old P-TMSI before new is confirmed */
|
||||
uint32_t p_tmsi_sig;
|
||||
char imei[GSM23003_IMEISV_NUM_DIGITS+1];
|
||||
/* Opt: Software Version Numbber / TS 23.195 */
|
||||
char msisdn[GSM_EXTENSION_LENGTH];
|
||||
struct gprs_ra_id ra;
|
||||
struct {
|
||||
uint16_t cell_id; /* Gb only */
|
||||
uint32_t cell_id_age; /* Gb only */
|
||||
uint8_t radio_prio_sms;
|
||||
|
||||
/* Additional bits not present in the GSM TS */
|
||||
uint16_t nsei;
|
||||
uint16_t bvci;
|
||||
struct gprs_llc_llme *llme;
|
||||
uint32_t tlli;
|
||||
uint32_t tlli_new;
|
||||
} gb;
|
||||
struct {
|
||||
int new_key;
|
||||
uint16_t sac; /* Iu: Service Area Code */
|
||||
uint32_t sac_age; /* Iu: Service Area Code age */
|
||||
/* CSG ID */
|
||||
/* CSG Membership */
|
||||
/* Access Mode */
|
||||
/* Seelected CN Operator ID (TS 23.251) */
|
||||
/* CSG Subscription Data */
|
||||
/* LIPA Allowed */
|
||||
/* Voice Support Match Indicator */
|
||||
struct ranap_ue_conn_ctx *ue_ctx;
|
||||
struct service_info service;
|
||||
} iu;
|
||||
/* VLR number */
|
||||
uint32_t new_sgsn_addr;
|
||||
/* Authentication Triplet */
|
||||
struct gsm_auth_tuple auth_triplet;
|
||||
/* Kc */
|
||||
/* Iu: CK, IK, KSI */
|
||||
/* CKSN */
|
||||
enum gprs_ciph_algo ciph_algo;
|
||||
/* Auth & Ciphering Request reference from 3GPP TS 24.008 § 10.5.5.19: */
|
||||
uint8_t ac_ref_nr_used;
|
||||
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t buf[50]; /* GSM 04.08 10.5.5.12a, extended in TS 24.008 */
|
||||
} ms_radio_access_capa;
|
||||
/* Supported Codecs (SRVCC) */
|
||||
struct {
|
||||
uint8_t len;
|
||||
uint8_t buf[8]; /* GSM 04.08 10.5.5.12, extended in TS 24.008 */
|
||||
} ms_network_capa;
|
||||
/* UE Netowrk Capability (E-UTRAN) */
|
||||
uint16_t drx_parms;
|
||||
/* Active Time value for PSM */
|
||||
int mnrg; /* MS reported to HLR? */
|
||||
int ngaf; /* MS reported to MSC/VLR? */
|
||||
int ppf; /* paging for GPRS + non-GPRS? */
|
||||
/* Subscribed Charging Characteristics */
|
||||
/* Trace Reference */
|
||||
/* Trace Type */
|
||||
/* Trigger ID */
|
||||
/* OMC Identity */
|
||||
/* SMS Parameters */
|
||||
int recovery;
|
||||
/* Access Restriction */
|
||||
/* GPRS CSI (CAMEL) */
|
||||
/* MG-CSI (CAMEL) */
|
||||
/* Subscribed UE-AMBR */
|
||||
/* UE-AMBR */
|
||||
/* APN Subscribed */
|
||||
|
||||
struct llist_head pdp_list;
|
||||
|
||||
struct rate_ctr_group *ctrg;
|
||||
struct osmo_timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
|
||||
enum gprs_t3350_mode t3350_mode;
|
||||
uint8_t t3370_id_type;
|
||||
uint8_t pending_req; /* the request's message type */
|
||||
/* TODO: There isn't much semantic difference between t3350_mode
|
||||
* (refers to the timer) and pending_req (refers to the procedure),
|
||||
* where mm->T == 3350 => mm->t3350_mode == f(mm->pending_req). Check
|
||||
* whether one of them can be dropped. */
|
||||
|
||||
enum sgsn_auth_state auth_state;
|
||||
int is_authenticated;
|
||||
|
||||
/* the string representation of the current hlr */
|
||||
char hlr[GSM_EXTENSION_LENGTH];
|
||||
|
||||
/* the current GGSN look-up operation */
|
||||
struct sgsn_ggsn_lookup *ggsn_lookup;
|
||||
|
||||
struct gprs_subscr *subscr;
|
||||
};
|
||||
|
||||
#define LOGMMCTXP(level, mm, fmt, args...) \
|
||||
LOGP(DMM, level, "MM(%s/%08x) " fmt, (mm) ? (mm)->imsi : "---", \
|
||||
(mm) ? (mm)->p_tmsi : GSM_RESERVED_TMSI, ## args)
|
||||
|
||||
/* look-up a SGSN MM context based on TLLI + RAI */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ptmsi(uint32_t tmsi);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_imsi(const char *imsi);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_ue_ctx(const void *uectx);
|
||||
|
||||
/* look-up by matching TLLI and P-TMSI (think twice before using this) */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_by_tlli_and_ptmsi(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
|
||||
/* Allocate a new SGSN MM context */
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_gb(uint32_t tlli,
|
||||
const struct gprs_ra_id *raid);
|
||||
struct sgsn_mm_ctx *sgsn_mm_ctx_alloc_iu(void *uectx);
|
||||
|
||||
void sgsn_mm_ctx_cleanup_free(struct sgsn_mm_ctx *ctx);
|
||||
|
||||
struct sgsn_ggsn_ctx *sgsn_mm_ctx_find_ggsn_ctx(struct sgsn_mm_ctx *mmctx,
|
||||
struct tlv_parsed *tp,
|
||||
enum gsm48_gsm_cause *gsm_cause,
|
||||
char *apn_str);
|
||||
|
||||
enum pdp_ctx_state {
|
||||
PDP_STATE_NONE,
|
||||
PDP_STATE_CR_REQ,
|
||||
PDP_STATE_CR_CONF,
|
||||
|
||||
/* 04.08 / Figure 6.2 / 6.1.2.2 */
|
||||
PDP_STATE_INACT_PEND,
|
||||
PDP_STATE_INACTIVE = PDP_STATE_NONE,
|
||||
};
|
||||
|
||||
enum pdp_type {
|
||||
PDP_TYPE_NONE,
|
||||
PDP_TYPE_ETSI_PPP,
|
||||
PDP_TYPE_IANA_IPv4,
|
||||
PDP_TYPE_IANA_IPv6,
|
||||
};
|
||||
|
||||
struct sgsn_pdp_ctx {
|
||||
struct llist_head list; /* list_head for mmctx->pdp_list */
|
||||
struct llist_head g_list; /* list_head for global list */
|
||||
struct sgsn_mm_ctx *mm; /* back pointer to MM CTX */
|
||||
int destroy_ggsn; /* destroy it on destruction */
|
||||
struct sgsn_ggsn_ctx *ggsn; /* which GGSN serves this PDP */
|
||||
struct rate_ctr_group *ctrg;
|
||||
|
||||
//unsigned int id;
|
||||
struct pdp_t *lib; /* pointer to libgtp PDP ctx */
|
||||
enum pdp_ctx_state state;
|
||||
enum pdp_type type;
|
||||
uint32_t address;
|
||||
char *apn_subscribed;
|
||||
//char *apn_used;
|
||||
uint16_t nsapi; /* SNDCP */
|
||||
uint16_t sapi; /* LLC */
|
||||
uint8_t ti; /* transaction identifier */
|
||||
int vplmn_allowed;
|
||||
uint32_t qos_profile_subscr;
|
||||
//uint32_t qos_profile_req;
|
||||
//uint32_t qos_profile_neg;
|
||||
uint8_t radio_prio;
|
||||
//uint32_t charging_id;
|
||||
|
||||
struct osmo_timer_list timer;
|
||||
unsigned int T; /* Txxxx number */
|
||||
unsigned int num_T_exp; /* number of consecutive T expirations */
|
||||
|
||||
struct osmo_timer_list cdr_timer; /* CDR record wird timer */
|
||||
struct timespec cdr_start; /* The start of the CDR */
|
||||
uint64_t cdr_bytes_in;
|
||||
uint64_t cdr_bytes_out;
|
||||
uint32_t cdr_charging_id;
|
||||
};
|
||||
|
||||
#define LOGPDPCTXP(level, pdp, fmt, args...) \
|
||||
LOGP(DGPRS, level, "PDP(%s/%u) " \
|
||||
fmt, (pdp)->mm ? (pdp)->mm->imsi : "---", (pdp)->ti, ## args)
|
||||
|
||||
/* look up PDP context by MM context and NSAPI */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_nsapi(const struct sgsn_mm_ctx *mm,
|
||||
uint8_t nsapi);
|
||||
/* look up PDP context by MM context and transaction ID */
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_by_tid(const struct sgsn_mm_ctx *mm,
|
||||
uint8_t tid);
|
||||
|
||||
struct sgsn_pdp_ctx *sgsn_pdp_ctx_alloc(struct sgsn_mm_ctx *mm,
|
||||
uint8_t nsapi);
|
||||
void sgsn_pdp_ctx_terminate(struct sgsn_pdp_ctx *pdp);
|
||||
void sgsn_pdp_ctx_free(struct sgsn_pdp_ctx *pdp);
|
||||
|
||||
|
||||
struct sgsn_ggsn_ctx {
|
||||
struct llist_head list;
|
||||
uint32_t id;
|
||||
unsigned int gtp_version;
|
||||
struct in_addr remote_addr;
|
||||
int remote_restart_ctr;
|
||||
struct gsn_t *gsn;
|
||||
};
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_alloc(uint32_t id);
|
||||
void sgsn_ggsn_ctx_free(struct sgsn_ggsn_ctx *ggc);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_id(uint32_t id);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_by_addr(struct in_addr *addr);
|
||||
struct sgsn_ggsn_ctx *sgsn_ggsn_ctx_find_alloc(uint32_t id);
|
||||
|
||||
struct apn_ctx {
|
||||
struct llist_head list;
|
||||
struct sgsn_ggsn_ctx *ggsn;
|
||||
char *name;
|
||||
char *imsi_prefix;
|
||||
char *description;
|
||||
};
|
||||
|
||||
struct apn_ctx *sgsn_apn_ctx_find_alloc(const char *name, const char *imsi_prefix);
|
||||
void sgsn_apn_ctx_free(struct apn_ctx *actx);
|
||||
struct apn_ctx *sgsn_apn_ctx_by_name(const char *name, const char *imsi_prefix);
|
||||
struct apn_ctx *sgsn_apn_ctx_match(const char *name, const char *imsi_prefix);
|
||||
|
||||
extern struct llist_head sgsn_mm_ctxts;
|
||||
extern struct llist_head sgsn_ggsn_ctxts;
|
||||
extern struct llist_head sgsn_apn_ctxts;
|
||||
extern struct llist_head sgsn_pdp_ctxts;
|
||||
|
||||
uint32_t sgsn_alloc_ptmsi(void);
|
||||
void sgsn_inst_init(void);
|
||||
|
||||
/* High-level function to be called in case a GGSN has disappeared or
|
||||
* ottherwise lost state (recovery procedure) */
|
||||
int drop_all_pdp_for_ggsn(struct sgsn_ggsn_ctx *ggsn);
|
||||
|
||||
char *gprs_pdpaddr2str(uint8_t *pdpa, uint8_t len);
|
||||
|
||||
/*
|
||||
* ctrl interface related work
|
||||
*/
|
||||
struct gsm_network;
|
||||
struct ctrl_handle *sgsn_controlif_setup(struct gsm_network *,
|
||||
const char *bind_addr, uint16_t port);
|
||||
int sgsn_ctrl_cmds_install(void);
|
||||
|
||||
/*
|
||||
* Authorization/ACL handling
|
||||
*/
|
||||
struct imsi_acl_entry {
|
||||
struct llist_head list;
|
||||
char imsi[16+1];
|
||||
};
|
||||
|
||||
/* see GSM 09.02, 17.7.1, PDP-Context and GPRSSubscriptionData */
|
||||
/* see GSM 09.02, B.1, gprsSubscriptionData */
|
||||
struct sgsn_subscriber_pdp_data {
|
||||
struct llist_head list;
|
||||
|
||||
unsigned int context_id;
|
||||
uint16_t pdp_type;
|
||||
char apn_str[GSM_APN_LENGTH];
|
||||
uint8_t qos_subscribed[20];
|
||||
size_t qos_subscribed_len;
|
||||
uint8_t pdp_charg[2];
|
||||
bool has_pdp_charg;
|
||||
};
|
||||
|
||||
struct sgsn_subscriber_data {
|
||||
struct sgsn_mm_ctx *mm;
|
||||
struct gsm_auth_tuple auth_triplets[5];
|
||||
int auth_triplets_updated;
|
||||
struct llist_head pdp_list;
|
||||
int error_cause;
|
||||
|
||||
uint8_t msisdn[9];
|
||||
size_t msisdn_len;
|
||||
|
||||
uint8_t hlr[9];
|
||||
size_t hlr_len;
|
||||
|
||||
uint8_t pdp_charg[2];
|
||||
bool has_pdp_charg;
|
||||
};
|
||||
|
||||
#define SGSN_ERROR_CAUSE_NONE (-1)
|
||||
|
||||
#define LOGGSUBSCRP(level, subscr, fmt, args...) \
|
||||
LOGP(DGPRS, level, "SUBSCR(%s) " fmt, \
|
||||
(subscr) ? (subscr)->imsi : "---", \
|
||||
## args)
|
||||
|
||||
struct sgsn_config;
|
||||
struct sgsn_instance;
|
||||
extern const struct value_string *sgsn_auth_state_names;
|
||||
|
||||
void sgsn_auth_init(void);
|
||||
struct imsi_acl_entry *sgsn_acl_lookup(const char *imsi, struct sgsn_config *cfg);
|
||||
int sgsn_acl_add(const char *imsi, struct sgsn_config *cfg);
|
||||
int sgsn_acl_del(const char *imsi, struct sgsn_config *cfg);
|
||||
/* Request authorization */
|
||||
int sgsn_auth_request(struct sgsn_mm_ctx *mm);
|
||||
enum sgsn_auth_state sgsn_auth_state(struct sgsn_mm_ctx *mm);
|
||||
void sgsn_auth_update(struct sgsn_mm_ctx *mm);
|
||||
struct gsm_auth_tuple *sgsn_auth_get_tuple(struct sgsn_mm_ctx *mmctx,
|
||||
unsigned key_seq);
|
||||
|
||||
/*
|
||||
* GPRS subscriber data
|
||||
*/
|
||||
#define GPRS_SUBSCRIBER_FIRST_CONTACT 0x00000001
|
||||
#define GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING (1 << 16)
|
||||
#define GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING (1 << 17)
|
||||
#define GPRS_SUBSCRIBER_CANCELLED (1 << 18)
|
||||
#define GPRS_SUBSCRIBER_ENABLE_PURGE (1 << 19)
|
||||
|
||||
#define GPRS_SUBSCRIBER_UPDATE_PENDING_MASK ( \
|
||||
GPRS_SUBSCRIBER_UPDATE_LOCATION_PENDING | \
|
||||
GPRS_SUBSCRIBER_UPDATE_AUTH_INFO_PENDING \
|
||||
)
|
||||
|
||||
int gprs_subscr_init(struct sgsn_instance *sgi);
|
||||
int gprs_subscr_request_update_location(struct sgsn_mm_ctx *mmctx);
|
||||
int gprs_subscr_request_auth_info(struct sgsn_mm_ctx *mmctx,
|
||||
const uint8_t *auts,
|
||||
const uint8_t *auts_rand);
|
||||
int gprs_subscr_auth_sync(struct gprs_subscr *subscr,
|
||||
const uint8_t *auts, const uint8_t *auts_rand);
|
||||
void gprs_subscr_cleanup(struct gprs_subscr *subscr);
|
||||
struct gprs_subscr *gprs_subscr_get_or_create(const char *imsi);
|
||||
struct gprs_subscr *gprs_subscr_get_or_create_by_mmctx( struct sgsn_mm_ctx *mmctx);
|
||||
struct gprs_subscr *gprs_subscr_get_by_imsi(const char *imsi);
|
||||
void gprs_subscr_cancel(struct gprs_subscr *subscr);
|
||||
void gprs_subscr_update(struct gprs_subscr *subscr);
|
||||
void gprs_subscr_update_auth_info(struct gprs_subscr *subscr);
|
||||
int gprs_subscr_rx_gsup_message(struct msgb *msg);
|
||||
|
||||
/* Called on subscriber data updates */
|
||||
void sgsn_update_subscriber_data(struct sgsn_mm_ctx *mmctx);
|
||||
|
||||
int gprs_sndcp_vty_init(void);
|
||||
struct sgsn_instance;
|
||||
int sgsn_gtp_init(struct sgsn_instance *sgi);
|
||||
|
||||
void sgsn_rate_ctr_init();
|
||||
|
||||
#endif /* _GPRS_SGSN_H */
|
|
@ -1,79 +0,0 @@
|
|||
#ifndef _INT_SNDCP_H
|
||||
#define _INT_SNDCP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
/* A fragment queue header, maintaining list of fragments for one N-PDU */
|
||||
struct defrag_state {
|
||||
/* PDU number for which the defragmentation state applies */
|
||||
uint16_t npdu;
|
||||
/* highest segment number we have received so far */
|
||||
uint8_t highest_seg;
|
||||
/* bitmask of the segments we already have */
|
||||
uint32_t seg_have;
|
||||
/* do we still expect more segments? */
|
||||
unsigned int no_more;
|
||||
/* total length of all segments together */
|
||||
unsigned int tot_len;
|
||||
|
||||
/* linked list of defrag_queue_entry: one for each fragment */
|
||||
struct llist_head frag_list;
|
||||
|
||||
struct osmo_timer_list timer;
|
||||
|
||||
/* Holds state to know which compression mode is used
|
||||
* when the packet is re-assembled */
|
||||
uint8_t pcomp;
|
||||
uint8_t dcomp;
|
||||
|
||||
/* Holds the pointers to the compression entity list
|
||||
* that is used when the re-assembled packet is decompressed */
|
||||
struct llist_head *proto;
|
||||
struct llist_head *data;
|
||||
};
|
||||
|
||||
/* See 6.7.1.2 Reassembly */
|
||||
enum sndcp_rx_state {
|
||||
SNDCP_RX_S_FIRST,
|
||||
SNDCP_RX_S_SUBSEQ,
|
||||
SNDCP_RX_S_DISCARD,
|
||||
};
|
||||
|
||||
struct gprs_sndcp_entity {
|
||||
struct llist_head list;
|
||||
|
||||
/* FIXME: move this RA_ID up to the LLME or even higher */
|
||||
struct gprs_ra_id ra_id;
|
||||
/* reference to the LLC Entity below this SNDCP entity */
|
||||
struct gprs_llc_lle *lle;
|
||||
/* The NSAPI we shall use on top of LLC */
|
||||
uint8_t nsapi;
|
||||
|
||||
/* NPDU number for the GTP->SNDCP side */
|
||||
uint16_t tx_npdu_nr;
|
||||
/* SNDCP eeceiver state */
|
||||
enum sndcp_rx_state rx_state;
|
||||
/* The defragmentation queue */
|
||||
struct defrag_state defrag;
|
||||
};
|
||||
|
||||
extern struct llist_head gprs_sndcp_entities;
|
||||
|
||||
/* Set of SNDCP-XID negotiation (See also: TS 144 065,
|
||||
* Section 6.8 XID parameter negotiation) */
|
||||
int sndcp_sn_xid_req(struct gprs_llc_lle *lle, uint8_t nsapi);
|
||||
|
||||
/* Process SNDCP-XID indication (See also: TS 144 065,
|
||||
* Section 6.8 XID parameter negotiation) */
|
||||
int sndcp_sn_xid_ind(struct gprs_llc_xid_field *xid_field_indication,
|
||||
struct gprs_llc_xid_field *xid_field_response,
|
||||
struct gprs_llc_lle *lle);
|
||||
|
||||
/* Process SNDCP-XID indication
|
||||
* (See also: TS 144 065, Section 6.8 XID parameter negotiation) */
|
||||
int sndcp_sn_xid_conf(struct gprs_llc_xid_field *xid_field_conf,
|
||||
struct gprs_llc_xid_field *xid_field_request,
|
||||
struct gprs_llc_lle *lle);
|
||||
|
||||
#endif /* INT_SNDCP_H */
|
|
@ -1,82 +0,0 @@
|
|||
/* GPRS SNDCP header compression entity management tools */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <openbsc/gprs_sndcp_xid.h>
|
||||
|
||||
/* Header / Data compression entity */
|
||||
struct gprs_sndcp_comp {
|
||||
struct llist_head list;
|
||||
|
||||
/* Serves as an ID in case we want to delete this entity later */
|
||||
unsigned int entity; /* see also: 6.5.1.1.3 and 6.6.1.1.3 */
|
||||
|
||||
/* Specifies to which NSAPIs the compression entity is assigned */
|
||||
uint8_t nsapi_len; /* Number of applicable NSAPIs (default 0) */
|
||||
uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
|
||||
|
||||
/* Assigned pcomp values */
|
||||
uint8_t comp_len; /* Number of contained PCOMP / DCOMP values */
|
||||
uint8_t comp[MAX_COMP]; /* see also: 6.5.1.1.5 and 6.6.1.1.5 */
|
||||
|
||||
/* Algorithm parameters */
|
||||
int algo; /* Algorithm type (see gprs_sndcp_xid.h) */
|
||||
int compclass; /* See gprs_sndcp_xid.h/c */
|
||||
void *state; /* Algorithm status and parameters */
|
||||
};
|
||||
|
||||
#define MAX_COMP 16 /* Maximum number of possible pcomp/dcomp values */
|
||||
#define MAX_NSAPI 11 /* Maximum number usable NSAPIs */
|
||||
|
||||
/* Allocate a compression enitiy list */
|
||||
struct llist_head *gprs_sndcp_comp_alloc(const void *ctx);
|
||||
|
||||
/* Free a compression entitiy list */
|
||||
void gprs_sndcp_comp_free(struct llist_head *comp_entities);
|
||||
|
||||
/* Delete a compression entity */
|
||||
void gprs_sndcp_comp_delete(struct llist_head *comp_entities, unsigned int entity);
|
||||
|
||||
/* Create and Add a new compression entity
|
||||
* (returns a pointer to the compression entity that has just been created) */
|
||||
struct gprs_sndcp_comp *gprs_sndcp_comp_add(const void *ctx,
|
||||
struct llist_head *comp_entities,
|
||||
const struct gprs_sndcp_comp_field
|
||||
*comp_field);
|
||||
|
||||
/* Find which compression entity handles the specified pcomp/dcomp */
|
||||
struct gprs_sndcp_comp *gprs_sndcp_comp_by_comp(const struct llist_head
|
||||
*comp_entities, uint8_t comp);
|
||||
|
||||
/* Find which compression entity handles the specified nsapi */
|
||||
struct gprs_sndcp_comp *gprs_sndcp_comp_by_nsapi(const struct llist_head
|
||||
*comp_entities, uint8_t nsapi);
|
||||
|
||||
/* Find a comp_index for a given pcomp/dcomp value */
|
||||
uint8_t gprs_sndcp_comp_get_idx(const struct gprs_sndcp_comp *comp_entity,
|
||||
uint8_t comp);
|
||||
|
||||
/* Find a pcomp/dcomp value for a given comp_index */
|
||||
uint8_t gprs_sndcp_comp_get_comp(const struct gprs_sndcp_comp *comp_entity,
|
||||
uint8_t comp_index);
|
|
@ -1,53 +0,0 @@
|
|||
/* GPRS SNDCP data compression handler */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <openbsc/gprs_sndcp_comp.h>
|
||||
|
||||
/* Note: The decompressed packet may have a maximum size of:
|
||||
* Return value * MAX_DATADECOMPR_FAC */
|
||||
#define MAX_DATADECOMPR_FAC 10
|
||||
|
||||
/* Note: In unacknowledged mode (SN_UNITDATA), the comression state is reset
|
||||
* for every NPDU. The compressor needs a reasonably large payload to operate
|
||||
* effectively (yield positive compression gain). For packets shorter than 100
|
||||
* byte, no positive compression gain can be expected so we will skip the
|
||||
* compression for short packets. */
|
||||
#define MIN_COMPR_PAYLOAD 100
|
||||
|
||||
/* Initalize data compression */
|
||||
int gprs_sndcp_dcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
|
||||
const struct gprs_sndcp_comp_field *comp_field);
|
||||
|
||||
/* Terminate data compression */
|
||||
void gprs_sndcp_dcomp_term(struct gprs_sndcp_comp *comp_entity);
|
||||
|
||||
/* Expand packet */
|
||||
int gprs_sndcp_dcomp_expand(uint8_t *data, unsigned int len, uint8_t pcomp,
|
||||
const struct llist_head *comp_entities);
|
||||
|
||||
/* Compress packet */
|
||||
int gprs_sndcp_dcomp_compress(uint8_t *data, unsigned int len, uint8_t *pcomp,
|
||||
const struct llist_head *comp_entities,
|
||||
uint8_t nsapi);
|
|
@ -1,46 +0,0 @@
|
|||
/* GPRS SNDCP header compression handler */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <openbsc/gprs_sndcp_comp.h>
|
||||
|
||||
/* Note: The decompressed packet may have a maximum size of:
|
||||
* Return value + MAX_DECOMPR_INCR */
|
||||
#define MAX_HDRDECOMPR_INCR 64
|
||||
|
||||
/* Initalize header compression */
|
||||
int gprs_sndcp_pcomp_init(const void *ctx, struct gprs_sndcp_comp *comp_entity,
|
||||
const struct gprs_sndcp_comp_field *comp_field);
|
||||
|
||||
/* Terminate header compression */
|
||||
void gprs_sndcp_pcomp_term(struct gprs_sndcp_comp *comp_entity);
|
||||
|
||||
/* Expand packet header */
|
||||
int gprs_sndcp_pcomp_expand(uint8_t *data, unsigned int len, uint8_t pcomp,
|
||||
const struct llist_head *comp_entities);
|
||||
|
||||
/* Compress packet header */
|
||||
int gprs_sndcp_pcomp_compress(uint8_t *data, unsigned int len, uint8_t *pcomp,
|
||||
const struct llist_head *comp_entities,
|
||||
uint8_t nsapi);
|
|
@ -1,218 +0,0 @@
|
|||
/* GPRS SNDCP XID field encoding/decoding as per 3GPP TS 44.065 */
|
||||
|
||||
/* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Philipp Maier
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
|
||||
#define DEFAULT_SNDCP_VERSION 0 /* See 3GPP TS 44.065, clause 8 */
|
||||
#define MAX_ENTITIES 32 /* 3GPP TS 44.065 reserves 5 bit
|
||||
* for compression enitity number */
|
||||
|
||||
#define MAX_COMP 16 /* Maximum number of possible pcomp/dcomp values */
|
||||
#define MAX_NSAPI 11 /* Maximum number usable NSAPIs */
|
||||
#define MAX_ROHC 16 /* Maximum number of ROHC compression profiles */
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.1.1 Format of the protocol control
|
||||
* information compression field (Figure 7) and 3GPP TS 44.065,
|
||||
* 6.6.1.1 Format of the data compression field (Figure 9) */
|
||||
struct gprs_sndcp_comp_field {
|
||||
struct llist_head list;
|
||||
|
||||
/* Propose bit (P), see also: 6.5.1.1.2 and 6.6.1.1.2 */
|
||||
unsigned int p;
|
||||
|
||||
/* Entity number, see also: 6.5.1.1.3 and 6.6.1.1.3 */
|
||||
unsigned int entity;
|
||||
|
||||
/* Algorithm identifier, see also: 6.5.1.1.4 and 6.6.1.1.4 */
|
||||
int algo;
|
||||
|
||||
/* Number of contained PCOMP / DCOMP values */
|
||||
uint8_t comp_len;
|
||||
|
||||
/* PCOMP / DCOMP values, see also: 6.5.1.1.5 and 6.6.1.1.5 */
|
||||
uint8_t comp[MAX_COMP];
|
||||
|
||||
/* Note: Only one of the following struct pointers may,
|
||||
be used. Unused pointers must be set to NULL! */
|
||||
struct gprs_sndcp_pcomp_rfc1144_params *rfc1144_params;
|
||||
struct gprs_sndcp_pcomp_rfc2507_params *rfc2507_params;
|
||||
struct gprs_sndcp_pcomp_rohc_params *rohc_params;
|
||||
struct gprs_sndcp_dcomp_v42bis_params *v42bis_params;
|
||||
struct gprs_sndcp_dcomp_v44_params *v44_params;
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.1.1.4 Algorithm identifier */
|
||||
enum gprs_sndcp_hdr_comp_algo {
|
||||
RFC_1144, /* TCP/IP header compression, see also 6.5.2 */
|
||||
RFC_2507, /* TCP/UDP/IP header compression, see also: 6.5.3 */
|
||||
ROHC /* Robust Header Compression, see also 6.5.4 */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.1.1.4 Algorithm identifier */
|
||||
enum gprs_sndcp_data_comp_algo {
|
||||
V42BIS, /* V.42bis data compression, see also 6.6.2 */
|
||||
V44 /* V44 data compression, see also: 6.6.3 */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 8 SNDCP XID parameters */
|
||||
enum gprs_sndcp_xid_param_types {
|
||||
SNDCP_XID_VERSION_NUMBER,
|
||||
SNDCP_XID_DATA_COMPRESSION, /* See also: subclause 6.6.1 */
|
||||
SNDCP_XID_PROTOCOL_COMPRESSION, /* See also: subclause 6.5.1 */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.2.1 Parameters (Table 5) */
|
||||
struct gprs_sndcp_pcomp_rfc1144_params {
|
||||
uint8_t nsapi_len; /* Number of applicable NSAPIs
|
||||
* (default 0) */
|
||||
uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
|
||||
int s01; /* (default 15) */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.2.2 Assignment of PCOMP values */
|
||||
enum gprs_sndcp_pcomp_rfc1144_pcomp {
|
||||
RFC1144_PCOMP1, /* Uncompressed TCP */
|
||||
RFC1144_PCOMP2, /* Compressed TCP */
|
||||
RFC1144_PCOMP_NUM /* Number of pcomp values */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.3.1 Parameters (Table 6) */
|
||||
struct gprs_sndcp_pcomp_rfc2507_params {
|
||||
uint8_t nsapi_len; /* Number of applicable NSAPIs
|
||||
* (default 0) */
|
||||
uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
|
||||
int f_max_period; /* (default 256) */
|
||||
int f_max_time; /* (default 5) */
|
||||
int max_header; /* (default 168) */
|
||||
int tcp_space; /* (default 15) */
|
||||
int non_tcp_space; /* (default 15) */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.3.2 Assignment of PCOMP values for RFC2507 */
|
||||
enum gprs_sndcp_pcomp_rfc2507_pcomp {
|
||||
RFC2507_PCOMP1, /* Full Header */
|
||||
RFC2507_PCOMP2, /* Compressed TCP */
|
||||
RFC2507_PCOMP3, /* Compressed TCP non delta */
|
||||
RFC2507_PCOMP4, /* Compressed non TCP */
|
||||
RFC2507_PCOMP5, /* Context state */
|
||||
RFC2507_PCOMP_NUM /* Number of pcomp values */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.4.1 Parameter (Table 10) */
|
||||
struct gprs_sndcp_pcomp_rohc_params {
|
||||
uint8_t nsapi_len; /* Number of applicable NSAPIs
|
||||
* (default 0) */
|
||||
uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
|
||||
int max_cid; /* (default 15) */
|
||||
int max_header; /* (default 168) */
|
||||
uint8_t profile_len; /* (default 1) */
|
||||
uint16_t profile[MAX_ROHC]; /* (default 0, ROHC uncompressed) */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.5.4.2 Assignment of PCOMP values for ROHC */
|
||||
enum gprs_sndcp_pcomp_rohc_pcomp {
|
||||
ROHC_PCOMP1, /* ROHC small CIDs */
|
||||
ROHC_PCOMP2, /* ROHC large CIDs */
|
||||
ROHC_PCOMP_NUM /* Number of pcomp values */
|
||||
};
|
||||
|
||||
/* ROHC compression profiles, see also:
|
||||
http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.xhtml */
|
||||
enum gprs_sndcp_xid_rohc_profiles {
|
||||
ROHC_UNCOMPRESSED = 0x0000, /* ROHC uncompressed [RFC5795] */
|
||||
ROHC_RTP = 0x0001, /* ROHC RTP [RFC3095] */
|
||||
ROHCV2_RTP = 0x0101, /* ROHCv2 RTP [RFC5225] */
|
||||
ROHC_UDP = 0x0002, /* ROHC UDP [RFC3095] */
|
||||
ROHCv2_UDP = 0x0102, /* ROHCv2 UDP [RFC5225] */
|
||||
ROHC_ESP = 0x0003, /* ROHC ESP [RFC3095] */
|
||||
ROHCV2_ESP = 0x0103, /* ROHCv2 ESP [RFC5225] */
|
||||
ROHC_IP = 0x0004, /* ROHC IP [RFC3843] */
|
||||
ROHCV2_IP = 0x0104, /* ROHCv2 IP [RFC5225] */
|
||||
ROHC_LLA = 0x0005, /* ROHC LLA [RFC4362] */
|
||||
ROHC_LLA_WITH_R_MODE = 0x0105, /* ROHC LLA with R-mode [RFC3408] */
|
||||
ROHC_TCP = 0x0006, /* ROHC TCP [RFC6846] */
|
||||
ROHC_RTP_UDP_LITE = 0x0007, /* ROHC RTP/UDP-Lite [RFC4019] */
|
||||
ROHCV2_RTP_UDP_LITE = 0x0107, /* ROHCv2 RTP/UDP-Lite [RFC5225] */
|
||||
ROHC_UDP_LITE = 0x0008, /* ROHC UDP-Lite [RFC4019] */
|
||||
ROHCV2_UDP_LITE = 0x0108, /* ROHCv2 UDP-Lite [RFC5225] */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.6.2.1 Parameters (Table 7a) */
|
||||
struct gprs_sndcp_dcomp_v42bis_params {
|
||||
uint8_t nsapi_len; /* Number of applicable NSAPIs
|
||||
* (default 0) */
|
||||
uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
|
||||
int p0; /* (default 3) */
|
||||
int p1; /* (default 2048) */
|
||||
int p2; /* (default 20) */
|
||||
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.6.2.2 Assignment of DCOMP values */
|
||||
enum gprs_sndcp_dcomp_v42bis_dcomp {
|
||||
V42BIS_DCOMP1, /* V.42bis enabled */
|
||||
V42BIS_DCOMP_NUM /* Number of dcomp values */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.6.3.1 Parameters (Table 7c) */
|
||||
struct gprs_sndcp_dcomp_v44_params {
|
||||
uint8_t nsapi_len; /* Number of applicable NSAPIs
|
||||
* (default 0) */
|
||||
uint8_t nsapi[MAX_NSAPI]; /* Applicable NSAPIs (default 0) */
|
||||
int c0; /* (default 10000000) */
|
||||
int p0; /* (default 3) */
|
||||
int p1t; /* Refer to subclause 6.6.3.1.4 */
|
||||
int p1r; /* Refer to subclause 6.6.3.1.5 */
|
||||
int p3t; /* (default 3 x p1t) */
|
||||
int p3r; /* (default 3 x p1r) */
|
||||
};
|
||||
|
||||
/* According to: 3GPP TS 44.065, 6.6.3.2 Assignment of DCOMP values */
|
||||
enum gprs_sndcp_dcomp_v44_dcomp {
|
||||
V44_DCOMP1, /* Packet method compressed */
|
||||
V44_DCOMP2, /* Multi packet method compressed */
|
||||
V44_DCOMP_NUM /* Number of dcomp values */
|
||||
};
|
||||
|
||||
/* Transform a list with compression fields into an SNDCP-XID message (dst) */
|
||||
int gprs_sndcp_compile_xid(uint8_t *dst, unsigned int dst_maxlen,
|
||||
const struct llist_head *comp_fields, int version);
|
||||
|
||||
/* Transform an SNDCP-XID message (src) into a list of SNDCP-XID fields */
|
||||
struct llist_head *gprs_sndcp_parse_xid(int *version,
|
||||
const void *ctx,
|
||||
const uint8_t *src,
|
||||
unsigned int src_len,
|
||||
const struct llist_head
|
||||
*comp_fields_req);
|
||||
|
||||
/* Find out to which compression class the specified comp-field belongs
|
||||
* (header compression or data compression?) */
|
||||
int gprs_sndcp_get_compression_class(
|
||||
const struct gprs_sndcp_comp_field *comp_field);
|
||||
|
||||
/* Dump a list with SNDCP-XID fields (Debug) */
|
||||
void gprs_sndcp_dump_comp_fields(const struct llist_head *comp_fields,
|
||||
unsigned int logl);
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* GPRS subscriber details for use in SGSN land */
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
extern struct llist_head * const gprs_subscribers;
|
||||
|
||||
struct gprs_subscr {
|
||||
struct llist_head entry;
|
||||
int use_count;
|
||||
|
||||
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
uint32_t tmsi;
|
||||
char imei[GSM23003_IMEISV_NUM_DIGITS+1];
|
||||
bool authorized;
|
||||
bool keep_in_ram;
|
||||
uint32_t flags;
|
||||
uint16_t lac;
|
||||
|
||||
struct sgsn_subscriber_data *sgsn_data;
|
||||
};
|
||||
|
||||
struct gprs_subscr *_gprs_subscr_get(struct gprs_subscr *gsub,
|
||||
const char *file, int line);
|
||||
struct gprs_subscr *_gprs_subscr_put(struct gprs_subscr *gsub,
|
||||
const char *file, int line);
|
||||
#define gprs_subscr_get(gsub) _gprs_subscr_get(gsub, __BASE_FILE__, __LINE__)
|
||||
#define gprs_subscr_put(gsub) _gprs_subscr_put(gsub, __BASE_FILE__, __LINE__)
|
|
@ -1,44 +0,0 @@
|
|||
/* GPRS utility functions */
|
||||
|
||||
/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
|
||||
* (C) 2010-2014 by On-Waves
|
||||
* (C) 2013 by Holger Hans Peter Freyther
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct msgb;
|
||||
struct gprs_ra_id;
|
||||
|
||||
struct msgb *gprs_msgb_copy(const struct msgb *msg, const char *name);
|
||||
int gprs_msgb_resize_area(struct msgb *msg, uint8_t *area,
|
||||
size_t old_size, size_t new_size);
|
||||
int gprs_str_to_apn(uint8_t *apn_enc, size_t max_len, const char *str);
|
||||
|
||||
/* GSM 04.08, 10.5.7.3 GPRS Timer */
|
||||
int gprs_tmr_to_secs(uint8_t tmr);
|
||||
uint8_t gprs_secs_to_tmr_floor(int secs);
|
||||
|
||||
int gprs_is_mi_tmsi(const uint8_t *value, size_t value_len);
|
||||
int gprs_is_mi_imsi(const uint8_t *value, size_t value_len);
|
||||
int gprs_parse_mi_tmsi(const uint8_t *value, size_t value_len, uint32_t *tmsi);
|
||||
void gprs_parse_tmsi(const uint8_t *value, uint32_t *tmsi);
|
||||
|
||||
int gprs_ra_id_equals(const struct gprs_ra_id *id1, const struct gprs_ra_id *id2);
|
|
@ -1,85 +0,0 @@
|
|||
#ifndef _GSM_04_08_H
|
||||
#define _GSM_04_08_H
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/gsm_utils.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||
|
||||
#include <openbsc/meas_rep.h>
|
||||
|
||||
struct msgb;
|
||||
struct gsm_bts;
|
||||
struct gsm_network;
|
||||
struct gsm_trans;
|
||||
struct gsm_subscriber_connection;
|
||||
struct amr_multirate_conf;
|
||||
struct amr_mode;
|
||||
struct bsc_subscr;
|
||||
|
||||
#define GSM48_ALLOC_SIZE 2048
|
||||
#define GSM48_ALLOC_HEADROOM 256
|
||||
|
||||
static inline struct msgb *gsm48_msgb_alloc_name(const char *name)
|
||||
{
|
||||
return msgb_alloc_headroom(GSM48_ALLOC_SIZE, GSM48_ALLOC_HEADROOM,
|
||||
name);
|
||||
}
|
||||
|
||||
void cm_service_request_concludes(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg);
|
||||
|
||||
/* config options controlling the behaviour of the lower leves */
|
||||
void gsm0408_allow_everyone(int allow);
|
||||
void gsm0408_clear_all_trans(struct gsm_network *net, int protocol);
|
||||
int gsm0408_dispatch(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
|
||||
int gsm0408_rcvmsg(struct msgb *msg, uint8_t link_id);
|
||||
enum gsm_chan_t get_ctype_by_chreq(struct gsm_network *bts, uint8_t ra);
|
||||
/* don't use "enum gsm_chreq_reason_t" to avoid circular dependency */
|
||||
int get_reason_by_chreq(uint8_t ra, int neci);
|
||||
void gsm_net_update_ctype(struct gsm_network *net);
|
||||
|
||||
int gsm48_tx_mm_info(struct gsm_subscriber_connection *conn);
|
||||
int gsm48_tx_mm_auth_req(struct gsm_subscriber_connection *conn, uint8_t *rand,
|
||||
uint8_t *autn, int key_seq);
|
||||
int gsm48_tx_mm_auth_rej(struct gsm_subscriber_connection *conn);
|
||||
int gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
|
||||
int gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
|
||||
enum gsm48_reject_value value);
|
||||
int gsm48_send_rr_release(struct gsm_lchan *lchan);
|
||||
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv);
|
||||
int gsm48_send_rr_app_info(struct gsm_subscriber_connection *conn, uint8_t apdu_id,
|
||||
uint8_t apdu_len, const uint8_t *apdu);
|
||||
int gsm48_send_rr_ass_cmd(struct gsm_lchan *dest_lchan, struct gsm_lchan *lchan, uint8_t power_class);
|
||||
int gsm48_send_ho_cmd(struct gsm_lchan *old_lchan, struct gsm_lchan *new_lchan,
|
||||
uint8_t power_command, uint8_t ho_ref);
|
||||
|
||||
int mncc_tx_to_cc(struct gsm_network *net, int msg_type, void *arg);
|
||||
|
||||
/* convert a ASCII phone number to call-control BCD */
|
||||
int encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
|
||||
int h_len, const char *input);
|
||||
int decode_bcd_number(char *output, int output_len, const uint8_t *bcd_lv,
|
||||
int h_len);
|
||||
|
||||
int send_siemens_mrpci(struct gsm_lchan *lchan, uint8_t *classmark2_lv);
|
||||
int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type);
|
||||
int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type);
|
||||
|
||||
int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode);
|
||||
int gsm48_rx_rr_modif_ack(struct msgb *msg);
|
||||
int gsm48_parse_meas_rep(struct gsm_meas_rep *rep, struct msgb *msg);
|
||||
|
||||
struct msgb *gsm48_create_mm_serv_rej(enum gsm48_reject_value value);
|
||||
struct msgb *gsm48_create_loc_upd_rej(uint8_t cause);
|
||||
void gsm48_lchan2chan_desc(struct gsm48_chan_desc *cd,
|
||||
const struct gsm_lchan *lchan);
|
||||
|
||||
void release_security_operation(struct gsm_subscriber_connection *conn);
|
||||
void allocate_security_operation(struct gsm_subscriber_connection *conn);
|
||||
|
||||
int gsm48_multirate_config(uint8_t *lv, const struct amr_multirate_conf *mr, const struct amr_mode *modes);
|
||||
|
||||
int gsm48_tch_rtp_create(struct gsm_trans *trans);
|
||||
|
||||
#endif
|
|
@ -1,53 +0,0 @@
|
|||
#ifndef _GSM_04_11_H
|
||||
#define _GSM_04_11_H
|
||||
|
||||
#include <osmocom/gsm/protocol/gsm_04_11.h>
|
||||
|
||||
struct vlr_subscr;
|
||||
struct gsm_subscriber_connection;
|
||||
struct gsm_trans;
|
||||
|
||||
#define UM_SAPI_SMS 3 /* See GSM 04.05/04.06 */
|
||||
|
||||
/* SMS deliver PDU */
|
||||
struct sms_deliver {
|
||||
uint8_t mti:2; /* message type indicator */
|
||||
uint8_t mms:1; /* more messages to send */
|
||||
uint8_t rp:1; /* reply path */
|
||||
uint8_t udhi:1; /* user data header indicator */
|
||||
uint8_t sri:1; /* status report indication */
|
||||
uint8_t *orig_addr; /* originating address */
|
||||
uint8_t pid; /* protocol identifier */
|
||||
uint8_t dcs; /* data coding scheme */
|
||||
/* service centre time stamp */
|
||||
uint8_t ud_len; /* user data length */
|
||||
uint8_t *user_data; /* user data */
|
||||
|
||||
uint8_t msg_ref; /* message reference */
|
||||
uint8_t *smsc;
|
||||
};
|
||||
|
||||
struct msgb;
|
||||
|
||||
int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn, struct msgb *msg);
|
||||
|
||||
struct gsm_sms *sms_alloc(void);
|
||||
void sms_free(struct gsm_sms *sms);
|
||||
struct gsm_sms *sms_from_text(struct vlr_subscr *receiver,
|
||||
struct vlr_subscr *sender,
|
||||
int dcs, const char *text);
|
||||
|
||||
void _gsm411_sms_trans_free(struct gsm_trans *trans);
|
||||
int gsm411_send_sms_subscr(struct vlr_subscr *vsub,
|
||||
struct gsm_sms *sms);
|
||||
int gsm411_send_sms(struct gsm_subscriber_connection *conn,
|
||||
struct gsm_sms *sms);
|
||||
void gsm411_sapi_n_reject(struct gsm_subscriber_connection *conn);
|
||||
|
||||
uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref);
|
||||
|
||||
int gsm411_send_rp_ack(struct gsm_trans *trans, uint8_t msg_ref);
|
||||
int gsm411_send_rp_error(struct gsm_trans *trans, uint8_t msg_ref,
|
||||
uint8_t cause);
|
||||
|
||||
#endif
|
|
@ -1,25 +0,0 @@
|
|||
#ifndef _GSM_04_80_H
|
||||
#define _GSM_04_80_H
|
||||
|
||||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/gsm/protocol/gsm_04_80.h>
|
||||
#include <osmocom/gsm/gsm0480.h>
|
||||
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
int gsm0480_send_ussd_response(struct gsm_subscriber_connection *conn,
|
||||
const struct msgb *in_msg, const char* response_text,
|
||||
const struct ss_request *req);
|
||||
int gsm0480_send_ussd_reject(struct gsm_subscriber_connection *conn,
|
||||
const struct msgb *msg,
|
||||
const struct ss_request *request);
|
||||
|
||||
int msc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level,
|
||||
const char *text);
|
||||
int msc_send_ussd_release_complete(struct gsm_subscriber_connection *conn);
|
||||
|
||||
int bsc_send_ussd_notify(struct gsm_subscriber_connection *conn, int level,
|
||||
const char *text);
|
||||
int bsc_send_ussd_release_complete(struct gsm_subscriber_connection *conn);
|
||||
|
||||
#endif
|
|
@ -1,691 +0,0 @@
|
|||
#ifndef _GSM_DATA_H
|
||||
#define _GSM_DATA_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <regex.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/stats.h>
|
||||
|
||||
#include <osmocom/crypt/auth.h>
|
||||
#include <osmocom/sigtran/sccp_sap.h>
|
||||
|
||||
#include <openbsc/common.h>
|
||||
#include <openbsc/rest_octets.h>
|
||||
#include <openbsc/common_cs.h>
|
||||
#include <openbsc/mgcpgw_client.h>
|
||||
|
||||
|
||||
/** annotations for msgb ownership */
|
||||
#define __uses
|
||||
|
||||
#define OBSC_NM_W_ACK_CB(__msgb) (__msgb)->cb[3]
|
||||
|
||||
struct mncc_sock_state;
|
||||
struct gsm_subscriber_group;
|
||||
struct bsc_subscr;
|
||||
struct vlr_instance;
|
||||
struct vlr_subscr;
|
||||
struct ranap_ue_conn_ctx;
|
||||
|
||||
#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
|
||||
|
||||
#define tmsi_from_string(str) strtoul(str, NULL, 10)
|
||||
|
||||
/* 3-bit long values */
|
||||
#define EARFCN_PRIO_INVALID 8
|
||||
#define EARFCN_MEAS_BW_INVALID 8
|
||||
/* 5-bit long values */
|
||||
#define EARFCN_QRXLV_INVALID 32
|
||||
#define EARFCN_THRESH_LOW_INVALID 32
|
||||
|
||||
enum gsm_security_event {
|
||||
GSM_SECURITY_NOAVAIL,
|
||||
GSM_SECURITY_AUTH_FAILED,
|
||||
GSM_SECURITY_SUCCEEDED,
|
||||
GSM_SECURITY_ALREADY,
|
||||
};
|
||||
|
||||
struct msgb;
|
||||
typedef int gsm_cbfn(unsigned int hooknum,
|
||||
unsigned int event,
|
||||
struct msgb *msg,
|
||||
void *data, void *param);
|
||||
|
||||
/* Real authentication information containing Ki */
|
||||
enum gsm_auth_algo {
|
||||
AUTH_ALGO_NONE,
|
||||
AUTH_ALGO_XOR,
|
||||
AUTH_ALGO_COMP128v1,
|
||||
};
|
||||
|
||||
struct gsm_auth_info {
|
||||
enum gsm_auth_algo auth_algo;
|
||||
unsigned int a3a8_ki_len;
|
||||
uint8_t a3a8_ki[16];
|
||||
};
|
||||
|
||||
struct gsm_auth_tuple {
|
||||
int use_count;
|
||||
int key_seq;
|
||||
struct osmo_auth_vector vec;
|
||||
};
|
||||
#define GSM_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
|
||||
|
||||
/*
|
||||
* AUTHENTICATION/CIPHERING state
|
||||
*/
|
||||
struct gsm_security_operation {
|
||||
struct gsm_auth_tuple atuple;
|
||||
gsm_cbfn *cb;
|
||||
void *cb_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* A dummy to keep a connection up for at least
|
||||
* a couple of seconds to work around MSC issues.
|
||||
*/
|
||||
struct gsm_anchor_operation {
|
||||
struct osmo_timer_list timeout;
|
||||
};
|
||||
|
||||
/* Maximum number of neighbor cells whose average we track */
|
||||
#define MAX_NEIGH_MEAS 10
|
||||
/* Maximum size of the averaging window for neighbor cells */
|
||||
#define MAX_WIN_NEIGH_AVG 10
|
||||
|
||||
/* processed neighbor measurements for one cell */
|
||||
struct neigh_meas_proc {
|
||||
uint16_t arfcn;
|
||||
uint8_t bsic;
|
||||
uint8_t rxlev[MAX_WIN_NEIGH_AVG];
|
||||
unsigned int rxlev_cnt;
|
||||
uint8_t last_seen_nr;
|
||||
};
|
||||
|
||||
enum ran_type {
|
||||
RAN_UNKNOWN,
|
||||
RAN_GERAN_A, /* 2G / A-interface */
|
||||
RAN_UTRAN_IU, /* 3G / Iu-interface (IuCS or IuPS) */
|
||||
};
|
||||
|
||||
extern const struct value_string ran_type_names[];
|
||||
static inline const char *ran_type_name(enum ran_type val)
|
||||
{ return get_value_string(ran_type_names, val); }
|
||||
|
||||
struct gsm_classmark {
|
||||
bool classmark1_set;
|
||||
struct gsm48_classmark1 classmark1;
|
||||
uint8_t classmark2_len;
|
||||
uint8_t classmark2[3];
|
||||
uint8_t classmark3_len;
|
||||
uint8_t classmark3[14]; /* if cm3 gets extended by spec, it will be truncated */
|
||||
};
|
||||
|
||||
enum integrity_protection_state {
|
||||
INTEGRITY_PROTECTION_NONE = 0,
|
||||
INTEGRITY_PROTECTION_IK = 1,
|
||||
INTEGRITY_PROTECTION_IK_CK = 2,
|
||||
};
|
||||
|
||||
/* active radio connection of a mobile subscriber */
|
||||
struct gsm_subscriber_connection {
|
||||
/* global linked list of subscriber_connections */
|
||||
struct llist_head entry;
|
||||
|
||||
/* usage count. If this drops to zero, we start the release
|
||||
* towards A/Iu */
|
||||
uint32_t use_count;
|
||||
|
||||
/* The MS has opened the conn with a CM Service Request, and we shall
|
||||
* keep it open for an actual request (or until timeout). */
|
||||
bool received_cm_service_request;
|
||||
|
||||
/* libbsc subscriber information (if available) */
|
||||
struct bsc_subscr *bsub;
|
||||
|
||||
/* libmsc/libvlr subscriber information (if available) */
|
||||
struct vlr_subscr *vsub;
|
||||
|
||||
/* LU expiration handling */
|
||||
uint8_t expire_timer_stopped;
|
||||
/* SMS helpers for libmsc */
|
||||
uint8_t next_rp_ref;
|
||||
|
||||
/*
|
||||
* Operations that have a state and might be pending
|
||||
*/
|
||||
struct gsm_security_operation *sec_operation;
|
||||
struct gsm_anchor_operation *anch_operation;
|
||||
|
||||
struct osmo_fsm_inst *conn_fsm;
|
||||
|
||||
/* Are we part of a special "silent" call */
|
||||
int silent_call;
|
||||
|
||||
/* MNCC rtp bridge markers */
|
||||
int mncc_rtp_bridge;
|
||||
int mncc_rtp_create_pending;
|
||||
int mncc_rtp_connect_pending;
|
||||
|
||||
/* bsc structures */
|
||||
struct osmo_bsc_sccp_con *sccp_con; /* BSC */
|
||||
|
||||
/* back pointers */
|
||||
struct gsm_network *network;
|
||||
|
||||
bool in_release;
|
||||
struct gsm_lchan *lchan; /* BSC */
|
||||
struct gsm_lchan *ho_lchan; /* BSC */
|
||||
struct gsm_bts *bts; /* BSC */
|
||||
|
||||
/* for assignment handling */
|
||||
struct osmo_timer_list T10; /* BSC */
|
||||
struct gsm_lchan *secondary_lchan; /* BSC */
|
||||
|
||||
/* connected via 2G or 3G? */
|
||||
enum ran_type via_ran;
|
||||
|
||||
struct gsm_classmark classmark;
|
||||
|
||||
uint16_t lac;
|
||||
struct gsm_encr encr;
|
||||
|
||||
struct {
|
||||
unsigned int mgcp_rtp_endpoint;
|
||||
uint16_t port_subscr;
|
||||
uint16_t port_cn;
|
||||
} rtp;
|
||||
|
||||
/* which Iu-CS connection, if any. */
|
||||
struct {
|
||||
struct ranap_ue_conn_ctx *ue_ctx;
|
||||
uint8_t rab_id;
|
||||
} iu;
|
||||
|
||||
struct {
|
||||
/* A pointer to the SCCP user that handles
|
||||
* the SCCP connections for this subscriber
|
||||
* connection */
|
||||
struct osmo_sccp_user *scu;
|
||||
|
||||
/* The address of the BSC that is associated
|
||||
* with this subscriber connection */
|
||||
struct osmo_sccp_addr bsc_addr;
|
||||
|
||||
/* The connection identifier that is used
|
||||
* to reference the SCCP connection that is
|
||||
* associated with this subscriber connection */
|
||||
int conn_id;
|
||||
} a;
|
||||
};
|
||||
|
||||
|
||||
#define ROLE_BSC
|
||||
#include "gsm_data_shared.h"
|
||||
|
||||
|
||||
enum {
|
||||
BSC_CTR_CHREQ_TOTAL,
|
||||
BSC_CTR_CHREQ_NO_CHANNEL,
|
||||
BSC_CTR_HANDOVER_ATTEMPTED,
|
||||
BSC_CTR_HANDOVER_NO_CHANNEL,
|
||||
BSC_CTR_HANDOVER_TIMEOUT,
|
||||
BSC_CTR_HANDOVER_COMPLETED,
|
||||
BSC_CTR_HANDOVER_FAILED,
|
||||
BSC_CTR_PAGING_ATTEMPTED,
|
||||
BSC_CTR_PAGING_DETACHED,
|
||||
BSC_CTR_PAGING_COMPLETED,
|
||||
BSC_CTR_PAGING_EXPIRED,
|
||||
BSC_CTR_CHAN_RF_FAIL,
|
||||
BSC_CTR_CHAN_RLL_ERR,
|
||||
BSC_CTR_BTS_OML_FAIL,
|
||||
BSC_CTR_BTS_RSL_FAIL,
|
||||
BSC_CTR_CODEC_AMR_F,
|
||||
BSC_CTR_CODEC_AMR_H,
|
||||
BSC_CTR_CODEC_EFR,
|
||||
BSC_CTR_CODEC_V1_FR,
|
||||
BSC_CTR_CODEC_V1_HR,
|
||||
};
|
||||
|
||||
static const struct rate_ctr_desc bsc_ctr_description[] = {
|
||||
[BSC_CTR_CHREQ_TOTAL] = {"chreq.total", "Received channel requests."},
|
||||
[BSC_CTR_CHREQ_NO_CHANNEL] = {"chreq.no_channel", "Sent to MS no channel available."},
|
||||
[BSC_CTR_HANDOVER_ATTEMPTED] = {"handover.attempted", "Received handover attempts."},
|
||||
[BSC_CTR_HANDOVER_NO_CHANNEL] = {"handover.no_channel", "Sent no channel available responses."},
|
||||
[BSC_CTR_HANDOVER_TIMEOUT] = {"handover.timeout", "Count the amount of timeouts of timer T3103."},
|
||||
[BSC_CTR_HANDOVER_COMPLETED] = {"handover.completed", "Received handover completed."},
|
||||
[BSC_CTR_HANDOVER_FAILED] = {"handover.failed", "Receive HO FAIL messages."},
|
||||
[BSC_CTR_PAGING_ATTEMPTED] = {"paging.attempted", "Paging attempts for a MS."},
|
||||
[BSC_CTR_PAGING_DETACHED] = {"paging.detached", "Counts the amount of paging attempts which couldn't sent out any paging request because no responsible bts found."},
|
||||
[BSC_CTR_PAGING_COMPLETED] = {"paging.completed", "Paging successful completed."},
|
||||
[BSC_CTR_PAGING_EXPIRED] = {"paging.expired", "Paging Request expired because of timeout T3113."},
|
||||
[BSC_CTR_CHAN_RF_FAIL] = {"chan.rf_fail", "Received a RF failure indication from BTS."},
|
||||
[BSC_CTR_CHAN_RLL_ERR] = {"chan.rll_err", "Received a RLL failure with T200 cause from BTS."},
|
||||
[BSC_CTR_BTS_OML_FAIL] = {"bts.oml_fail", "Received a TEI down on a OML link."},
|
||||
[BSC_CTR_BTS_RSL_FAIL] = {"bts.rsl_fail", "Received a TEI down on a OML link."},
|
||||
[BSC_CTR_CODEC_AMR_F] = {"bts.codec_amr_f", "Count the usage of AMR/F codec by channel mode requested."},
|
||||
[BSC_CTR_CODEC_AMR_H] = {"bts.codec_amr_h", "Count the usage of AMR/H codec by channel mode requested."},
|
||||
[BSC_CTR_CODEC_EFR] = {"bts.codec_efr", "Count the usage of EFR codec by channel mode requested."},
|
||||
[BSC_CTR_CODEC_V1_FR] = {"bts.codec_fr", "Count the usage of FR codec by channel mode requested."},
|
||||
[BSC_CTR_CODEC_V1_HR] = {"bts.codec_hr", "Count the usage of HR codec by channel mode requested."},
|
||||
};
|
||||
|
||||
enum {
|
||||
MSC_CTR_LOC_UPDATE_TYPE_ATTACH,
|
||||
MSC_CTR_LOC_UPDATE_TYPE_NORMAL,
|
||||
MSC_CTR_LOC_UPDATE_TYPE_PERIODIC,
|
||||
MSC_CTR_LOC_UPDATE_TYPE_DETACH,
|
||||
MSC_CTR_LOC_UPDATE_FAILED,
|
||||
MSC_CTR_LOC_UPDATE_COMPLETED,
|
||||
MSC_CTR_SMS_SUBMITTED,
|
||||
MSC_CTR_SMS_NO_RECEIVER,
|
||||
MSC_CTR_SMS_DELIVERED,
|
||||
MSC_CTR_SMS_RP_ERR_MEM,
|
||||
MSC_CTR_SMS_RP_ERR_OTHER,
|
||||
MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR,
|
||||
MSC_CTR_CALL_MO_SETUP,
|
||||
MSC_CTR_CALL_MO_CONNECT_ACK,
|
||||
MSC_CTR_CALL_MT_SETUP,
|
||||
MSC_CTR_CALL_MT_CONNECT,
|
||||
MSC_CTR_CALL_ACTIVE,
|
||||
MSC_CTR_CALL_COMPLETE,
|
||||
MSC_CTR_CALL_INCOMPLETE,
|
||||
};
|
||||
|
||||
static const struct rate_ctr_desc msc_ctr_description[] = {
|
||||
[MSC_CTR_LOC_UPDATE_TYPE_ATTACH] = {"loc_update_type.attach", "Received location update imsi attach requests."},
|
||||
[MSC_CTR_LOC_UPDATE_TYPE_NORMAL] = {"loc_update_type.normal", "Received location update normal requests."},
|
||||
[MSC_CTR_LOC_UPDATE_TYPE_PERIODIC] = {"loc_update_type.periodic", "Received location update periodic requests."},
|
||||
[MSC_CTR_LOC_UPDATE_TYPE_DETACH] = {"loc_update_type.detach", "Received location update detach indication."},
|
||||
[MSC_CTR_LOC_UPDATE_FAILED] = {"loc_update_resp.failed", "Rejected location updates."},
|
||||
[MSC_CTR_LOC_UPDATE_COMPLETED] = {"loc_update_resp.completed", "Successful location updates."},
|
||||
[MSC_CTR_SMS_SUBMITTED] = {"sms.submitted", "Received a RPDU from a MS (MO)."},
|
||||
[MSC_CTR_SMS_NO_RECEIVER] = {"sms.no_receiver", "Counts SMS which couldn't routed because no receiver found."},
|
||||
[MSC_CTR_SMS_DELIVERED] = {"sms.delivered", "Global SMS Deliver attempts."},
|
||||
[MSC_CTR_SMS_RP_ERR_MEM] = {"sms.rp_err_mem", "CAUSE_MT_MEM_EXCEEDED errors of MS responses on a sms deliver attempt."},
|
||||
[MSC_CTR_SMS_RP_ERR_OTHER] = {"sms.rp_err_other", "Other error of MS responses on a sms delive attempt."},
|
||||
[MSC_CTR_SMS_DELIVER_UNKNOWN_ERROR] = {"sms.deliver_unknown_error", "Unknown error occured during sms delivery."},
|
||||
/* FIXME: count also sms delivered */
|
||||
[MSC_CTR_CALL_MO_SETUP] = {"call.mo_setup", "Received setup requests from a MS to init a MO call."},
|
||||
[MSC_CTR_CALL_MO_CONNECT_ACK] = {"call.mo_connect_ack", "Received a connect ack from MS of a MO call. Call is now succesful connected up."},
|
||||
[MSC_CTR_CALL_MT_SETUP] = {"call.mt_setup", "Sent setup requests to the MS (MT)."},
|
||||
[MSC_CTR_CALL_MT_CONNECT] = {"call.mt_connect", "Sent a connect to the MS (MT)."},
|
||||
[MSC_CTR_CALL_ACTIVE] = {"call.active", "Count total amount of calls that ever reached active state."},
|
||||
[MSC_CTR_CALL_COMPLETE] = {"call.complete", "Count total amount of calls which got terminated by disconnect req or ind after reaching active state."},
|
||||
[MSC_CTR_CALL_INCOMPLETE] = {"call.incomplete", "Count total amount of call which got terminated by any other reason after reaching active state."},
|
||||
};
|
||||
|
||||
|
||||
static const struct rate_ctr_group_desc bsc_ctrg_desc = {
|
||||
"bsc",
|
||||
"base station controller",
|
||||
OSMO_STATS_CLASS_GLOBAL,
|
||||
ARRAY_SIZE(bsc_ctr_description),
|
||||
bsc_ctr_description,
|
||||
};
|
||||
|
||||
static const struct rate_ctr_group_desc msc_ctrg_desc = {
|
||||
"msc",
|
||||
"mobile switching center",
|
||||
OSMO_STATS_CLASS_GLOBAL,
|
||||
ARRAY_SIZE(msc_ctr_description),
|
||||
msc_ctr_description,
|
||||
};
|
||||
|
||||
enum gsm_auth_policy {
|
||||
GSM_AUTH_POLICY_CLOSED, /* only subscribers authorized in DB */
|
||||
GSM_AUTH_POLICY_ACCEPT_ALL, /* accept everyone, even if not authorized in DB */
|
||||
GSM_AUTH_POLICY_TOKEN, /* accept first, send token per sms, then revoke authorization */
|
||||
GSM_AUTH_POLICY_REGEXP, /* accept IMSIs matching given regexp */
|
||||
};
|
||||
|
||||
#define GSM_T3101_DEFAULT 10 /* s */
|
||||
#define GSM_T3103_DEFAULT 5 /* s */
|
||||
#define GSM_T3105_DEFAULT 100 /* ms */
|
||||
#define GSM_T3107_DEFAULT 5 /* s */
|
||||
#define GSM_T3109_DEFAULT 19 /* s, must be 2s + radio_link_timeout*0.48 */
|
||||
#define GSM_T3111_DEFAULT 2 /* s */
|
||||
#define GSM_T3113_DEFAULT 60
|
||||
#define GSM_T3115_DEFAULT 10
|
||||
#define GSM_T3117_DEFAULT 10
|
||||
#define GSM_T3119_DEFAULT 10
|
||||
#define GSM_T3122_DEFAULT 10
|
||||
#define GSM_T3141_DEFAULT 10
|
||||
|
||||
struct gsm_tz {
|
||||
int override; /* if 0, use system's time zone instead. */
|
||||
int hr; /* hour */
|
||||
int mn; /* minute */
|
||||
int dst; /* daylight savings */
|
||||
};
|
||||
|
||||
struct gsm_network {
|
||||
/* TODO MSCSPLIT the gsm_network struct is basically a kitchen sink for
|
||||
* global settings and variables, "madly" mixing BSC and MSC stuff. Split
|
||||
* this in e.g. struct osmo_bsc and struct osmo_msc, with the things
|
||||
* these have in common, like country and network code, put in yet
|
||||
* separate structs and placed as members in osmo_bsc and osmo_msc. */
|
||||
|
||||
/* global parameters */
|
||||
uint16_t country_code;
|
||||
uint16_t network_code;
|
||||
char *name_long;
|
||||
char *name_short;
|
||||
enum gsm_auth_policy auth_policy;
|
||||
regex_t authorized_regexp;
|
||||
char *authorized_reg_str;
|
||||
enum gsm48_reject_value reject_cause;
|
||||
int a5_encryption;
|
||||
bool authentication_required;
|
||||
int neci;
|
||||
int send_mm_info;
|
||||
struct {
|
||||
int active;
|
||||
/* Window RXLEV averaging */
|
||||
unsigned int win_rxlev_avg; /* number of SACCH frames */
|
||||
/* Window RXQUAL averaging */
|
||||
unsigned int win_rxqual_avg; /* number of SACCH frames */
|
||||
/* Window RXLEV neighbouring cells averaging */
|
||||
unsigned int win_rxlev_avg_neigh; /* number of SACCH frames */
|
||||
|
||||
/* how often should we check for power budget HO */
|
||||
unsigned int pwr_interval; /* SACCH frames */
|
||||
/* how much better does a neighbor cell have to be ? */
|
||||
unsigned int pwr_hysteresis; /* dBm */
|
||||
/* maximum distacne before we try a handover */
|
||||
unsigned int max_distance; /* TA values */
|
||||
} handover;
|
||||
|
||||
struct rate_ctr_group *bsc_ctrs;
|
||||
struct rate_ctr_group *msc_ctrs;
|
||||
struct osmo_counter *active_calls;
|
||||
|
||||
/* layer 4 */
|
||||
struct mncc_sock_state *mncc_state;
|
||||
mncc_recv_cb_t mncc_recv;
|
||||
struct llist_head upqueue;
|
||||
/*
|
||||
* TODO: Move the trans_list into the subscriber connection and
|
||||
* create a pending list for MT transactions. These exist before
|
||||
* we have a subscriber connection.
|
||||
*/
|
||||
struct llist_head trans_list;
|
||||
struct bsc_api *bsc_api;
|
||||
|
||||
unsigned int num_bts;
|
||||
struct llist_head bts_list;
|
||||
|
||||
/* timer values */
|
||||
int T3101;
|
||||
int T3103;
|
||||
int T3105;
|
||||
int T3107;
|
||||
int T3109;
|
||||
int T3111;
|
||||
int T3113;
|
||||
int T3115;
|
||||
int T3117;
|
||||
int T3119;
|
||||
int T3122;
|
||||
int T3141;
|
||||
|
||||
/* timer to expire old location updates */
|
||||
struct osmo_timer_list subscr_expire_timer;
|
||||
|
||||
/* Radio Resource Location Protocol (TS 04.31) */
|
||||
struct {
|
||||
enum rrlp_mode mode;
|
||||
} rrlp;
|
||||
|
||||
enum gsm_chan_t ctype_by_chreq[18];
|
||||
|
||||
/* Use a TCH for handling requests of type paging any */
|
||||
int pag_any_tch;
|
||||
|
||||
/* MSC data in case we are a true BSC */
|
||||
struct osmo_bsc_data *bsc_data;
|
||||
|
||||
struct gsm_sms_queue *sms_queue;
|
||||
|
||||
/* control interface */
|
||||
struct ctrl_handle *ctrl;
|
||||
|
||||
/* Allow or disallow TCH/F on dynamic TCH/F_TCH/H_PDCH; OS#1778 */
|
||||
bool dyn_ts_allow_tch_f;
|
||||
|
||||
/* all active subscriber connections. */
|
||||
struct llist_head subscr_conns;
|
||||
|
||||
/* if override is nonzero, this timezone data is used for all MM
|
||||
* contexts. */
|
||||
/* TODO: in OsmoNITB, tz-override used to be BTS-specific. To enable
|
||||
* BTS|RNC specific timezone overrides for multi-tz networks in
|
||||
* OsmoMSC, this should be tied to the location area code (LAC). */
|
||||
struct gsm_tz tz;
|
||||
|
||||
/* List of all struct bsc_subscr used in libbsc. This llist_head is
|
||||
* allocated so that the llist_head pointer itself can serve as a
|
||||
* talloc context (useful to not have to pass the entire gsm_network
|
||||
* struct to the bsc_subscr_* API, and for bsc_susbscr unit tests to
|
||||
* not require gsm_data.h). In an MSC-without-BSC environment, this
|
||||
* pointer is NULL to indicate absence of a bsc_subscribers list. */
|
||||
struct llist_head *bsc_subscribers;
|
||||
|
||||
/* MSC: GSUP server address of the HLR */
|
||||
const char *gsup_server_addr_str;
|
||||
uint16_t gsup_server_port;
|
||||
|
||||
struct vlr_instance *vlr;
|
||||
|
||||
/* Periodic location update default value */
|
||||
uint8_t t3212;
|
||||
|
||||
struct {
|
||||
struct mgcpgw_client_conf conf;
|
||||
struct mgcpgw_client *client;
|
||||
} mgcpgw;
|
||||
|
||||
struct {
|
||||
/* CS7 instance id number (set via VTY) */
|
||||
uint32_t cs7_instance;
|
||||
int rab_assign_addr_enc;
|
||||
struct osmo_sccp_instance *sccp;
|
||||
} iu;
|
||||
|
||||
struct {
|
||||
/* CS7 instance id number (set via VTY) */
|
||||
uint32_t cs7_instance;
|
||||
/* A list with the context information about
|
||||
* all BSCs we have connections with */
|
||||
struct llist_head bscs;
|
||||
struct osmo_sccp_instance *sccp;
|
||||
} a;
|
||||
};
|
||||
|
||||
struct osmo_esme;
|
||||
|
||||
enum gsm_sms_source_id {
|
||||
SMS_SOURCE_UNKNOWN = 0,
|
||||
SMS_SOURCE_MS, /* received from MS */
|
||||
SMS_SOURCE_VTY, /* received from VTY */
|
||||
SMS_SOURCE_SMPP, /* received via SMPP */
|
||||
};
|
||||
|
||||
#define SMS_HDR_SIZE 128
|
||||
#define SMS_TEXT_SIZE 256
|
||||
|
||||
struct gsm_sms_addr {
|
||||
uint8_t ton;
|
||||
uint8_t npi;
|
||||
char addr[21+1];
|
||||
};
|
||||
|
||||
struct gsm_sms {
|
||||
unsigned long long id;
|
||||
struct vlr_subscr *receiver;
|
||||
struct gsm_sms_addr src, dst;
|
||||
enum gsm_sms_source_id source;
|
||||
|
||||
struct {
|
||||
uint8_t transaction_id;
|
||||
uint32_t msg_ref;
|
||||
} gsm411;
|
||||
|
||||
struct {
|
||||
struct osmo_esme *esme;
|
||||
uint32_t sequence_nr;
|
||||
int transaction_mode;
|
||||
char msg_id[16];
|
||||
} smpp;
|
||||
|
||||
unsigned long validity_minutes;
|
||||
time_t created;
|
||||
bool is_report;
|
||||
uint8_t reply_path_req;
|
||||
uint8_t status_rep_req;
|
||||
uint8_t ud_hdr_ind;
|
||||
uint8_t protocol_id;
|
||||
uint8_t data_coding_scheme;
|
||||
uint8_t msg_ref;
|
||||
uint8_t user_data_len;
|
||||
uint8_t user_data[SMS_TEXT_SIZE];
|
||||
|
||||
char text[SMS_TEXT_SIZE];
|
||||
};
|
||||
|
||||
extern void talloc_ctx_init(void *ctx_root);
|
||||
|
||||
int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
|
||||
|
||||
enum gsm_bts_type parse_btstype(const char *arg);
|
||||
const char *btstype2str(enum gsm_bts_type type);
|
||||
struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
|
||||
struct gsm_bts *start_bts);
|
||||
|
||||
extern void *tall_bsc_ctx;
|
||||
extern int ipacc_rtp_direct;
|
||||
|
||||
/* this actaully refers to the IPA transport, not the BTS model */
|
||||
static inline int is_ipaccess_bts(struct gsm_bts *bts)
|
||||
{
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_NANOBTS:
|
||||
case GSM_BTS_TYPE_OSMOBTS:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int is_sysmobts_v2(struct gsm_bts *bts)
|
||||
{
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_OSMOBTS:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int is_siemens_bts(struct gsm_bts *bts)
|
||||
{
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int is_nokia_bts(struct gsm_bts *bts)
|
||||
{
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_NOKIA_SITE:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int is_e1_bts(struct gsm_bts *bts)
|
||||
{
|
||||
switch (bts->type) {
|
||||
case GSM_BTS_TYPE_BS11:
|
||||
case GSM_BTS_TYPE_RBS2000:
|
||||
case GSM_BTS_TYPE_NOKIA_SITE:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum gsm_auth_policy gsm_auth_policy_parse(const char *arg);
|
||||
const char *gsm_auth_policy_name(enum gsm_auth_policy policy);
|
||||
|
||||
enum rrlp_mode rrlp_mode_parse(const char *arg);
|
||||
const char *rrlp_mode_name(enum rrlp_mode mode);
|
||||
|
||||
enum bts_gprs_mode bts_gprs_mode_parse(const char *arg, int *valid);
|
||||
const char *bts_gprs_mode_name(enum bts_gprs_mode mode);
|
||||
int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode);
|
||||
|
||||
int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts);
|
||||
void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
|
||||
|
||||
int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
|
||||
int gsm_bts_model_register(struct gsm_bts_model *model);
|
||||
|
||||
struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lchan);
|
||||
void bsc_subscr_con_free(struct gsm_subscriber_connection *conn);
|
||||
|
||||
struct gsm_subscriber_connection *msc_subscr_con_allocate(struct gsm_network *network);
|
||||
void msc_subscr_con_free(struct gsm_subscriber_connection *conn);
|
||||
|
||||
struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net,
|
||||
enum gsm_bts_type type,
|
||||
uint8_t bsic);
|
||||
|
||||
void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr,
|
||||
uint8_t e1_ts, uint8_t e1_ts_ss);
|
||||
|
||||
void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked);
|
||||
bool gsm_btsmodel_has_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
|
||||
struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr);
|
||||
int gsm_bts_trx_set_system_infos(struct gsm_bts_trx *trx);
|
||||
int gsm_bts_set_system_infos(struct gsm_bts *bts);
|
||||
|
||||
/* generic E1 line operations for all ISDN-based BTS. */
|
||||
extern struct e1inp_line_ops bts_isdn_e1inp_line_ops;
|
||||
|
||||
extern const struct value_string bts_type_names[_NUM_GSM_BTS_TYPE+1];
|
||||
extern const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1];
|
||||
|
||||
/* control interface handling */
|
||||
int bsc_base_ctrl_cmds_install(void);
|
||||
int msc_ctrl_cmds_install(struct gsm_network *net);
|
||||
|
||||
/* dependency handling */
|
||||
void bts_depend_mark(struct gsm_bts *bts, int dep);
|
||||
void bts_depend_clear(struct gsm_bts *bts, int dep);
|
||||
int bts_depend_check(struct gsm_bts *bts);
|
||||
int bts_depend_is_depedency(struct gsm_bts *base, struct gsm_bts *other);
|
||||
|
||||
int gsm_bts_get_radio_link_timeout(const struct gsm_bts *bts);
|
||||
void gsm_bts_set_radio_link_timeout(struct gsm_bts *bts, int value);
|
||||
|
||||
bool classmark_is_r99(struct gsm_classmark *cm);
|
||||
|
||||
#endif /* _GSM_DATA_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,68 +0,0 @@
|
|||
#ifndef _GSM_SUBSCR_H
|
||||
#define _GSM_SUBSCR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
|
||||
#define GSM_NAME_LENGTH 160
|
||||
|
||||
#define GSM_EXTENSION_LENGTH 15 /* MSISDN can only be 15 digits length */
|
||||
#define GSM_MIN_EXTEN 20000
|
||||
#define GSM_MAX_EXTEN 49999
|
||||
|
||||
#define GSM_SUBSCRIBER_FIRST_CONTACT 0x00000001
|
||||
/* gprs_sgsn.h defines additional flags including and above bit 16 (0x10000) */
|
||||
|
||||
#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0
|
||||
|
||||
enum gsm_subscriber_field {
|
||||
GSM_SUBSCRIBER_IMSI,
|
||||
GSM_SUBSCRIBER_TMSI,
|
||||
GSM_SUBSCRIBER_EXTENSION,
|
||||
GSM_SUBSCRIBER_ID,
|
||||
};
|
||||
|
||||
enum gsm_subscriber_update_reason {
|
||||
GSM_SUBSCRIBER_UPDATE_ATTACHED,
|
||||
GSM_SUBSCRIBER_UPDATE_DETACHED,
|
||||
GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct for pending channel requests. This is managed in the
|
||||
* llist_head requests of each subscriber. The reference counting
|
||||
* should work in such a way that a subscriber with a pending request
|
||||
* remains in memory.
|
||||
*/
|
||||
struct subscr_request {
|
||||
struct llist_head entry;
|
||||
|
||||
/* human readable label to be able to log pending request kinds */
|
||||
const char *label;
|
||||
|
||||
/* the callback data */
|
||||
gsm_cbfn *cbfn;
|
||||
void *param;
|
||||
};
|
||||
|
||||
int subscr_update(struct vlr_subscr *vsub, int reason);
|
||||
|
||||
/*
|
||||
* Paging handling with authentication
|
||||
*/
|
||||
struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
|
||||
gsm_cbfn *cbfn, void *param,
|
||||
const char *label);
|
||||
|
||||
void subscr_remove_request(struct subscr_request *req);
|
||||
int subscr_rx_paging_response(struct msgb *msg,
|
||||
struct gsm_subscriber_connection *conn);
|
||||
|
||||
int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
|
||||
struct msgb *msg, void *data, void *param);
|
||||
|
||||
#endif /* _GSM_SUBSCR_H */
|
|
@ -1,63 +0,0 @@
|
|||
/* GPRS Subscriber Update Protocol client */
|
||||
|
||||
/* (C) 2014 by Sysmocom s.f.m.c. GmbH
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Jacob Erlbeck
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <osmocom/core/timer.h>
|
||||
|
||||
#include <openbsc/oap_client.h>
|
||||
|
||||
#define GSUP_CLIENT_RECONNECT_INTERVAL 10
|
||||
#define GSUP_CLIENT_PING_INTERVAL 20
|
||||
|
||||
struct msgb;
|
||||
struct ipa_client_conn;
|
||||
struct gsup_client;
|
||||
|
||||
/* Expects message in msg->l2h */
|
||||
typedef int (*gsup_client_read_cb_t)(struct gsup_client *gsupc,
|
||||
struct msgb *msg);
|
||||
|
||||
struct gsup_client {
|
||||
const char *unit_name;
|
||||
|
||||
struct ipa_client_conn *link;
|
||||
gsup_client_read_cb_t read_cb;
|
||||
void *data;
|
||||
|
||||
struct oap_client_state oap_state;
|
||||
|
||||
struct osmo_timer_list ping_timer;
|
||||
struct osmo_timer_list connect_timer;
|
||||
int is_connected;
|
||||
int got_ipa_pong;
|
||||
};
|
||||
|
||||
struct gsup_client *gsup_client_create(const char *unit_name,
|
||||
const char *ip_addr,
|
||||
unsigned int tcp_port,
|
||||
gsup_client_read_cb_t read_cb,
|
||||
struct oap_client_config *oapc_config);
|
||||
|
||||
void gsup_client_destroy(struct gsup_client *gsupc);
|
||||
int gsup_client_send(struct gsup_client *gsupc, struct msgb *msg);
|
||||
struct msgb *gsup_client_msgb_alloc(void);
|
||||
|
|
@ -1,523 +0,0 @@
|
|||
/* GTP Hub Implementation */
|
||||
|
||||
/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* Author: Neels Hofmeyr
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <osmocom/core/select.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/rate_ctr.h>
|
||||
|
||||
#include <openbsc/gprs_sgsn.h>
|
||||
|
||||
|
||||
/* support */
|
||||
|
||||
/* TODO move to osmocom/core/socket.c ? */
|
||||
#include <netdb.h> /* for IPPROTO_* etc */
|
||||
struct osmo_sockaddr {
|
||||
struct sockaddr_storage a;
|
||||
socklen_t l;
|
||||
};
|
||||
|
||||
/* TODO move to osmocom/core/socket.c ? */
|
||||
/*! \brief Initialize a sockaddr
|
||||
* \param[out] addr Valid osmo_sockaddr pointer to write result to
|
||||
* \param[in] family Address Family like AF_INET, AF_INET6, AF_UNSPEC
|
||||
* \param[in] type Socket type like SOCK_DGRAM, SOCK_STREAM
|
||||
* \param[in] proto Protocol like IPPROTO_TCP, IPPROTO_UDP
|
||||
* \param[in] host Remote host name or IP address in string form
|
||||
* \param[in] port Remote port number in host byte order
|
||||
* \returns 0 on success, otherwise an error code (from getaddrinfo()).
|
||||
*
|
||||
* Copy the first result from a getaddrinfo() call with the given parameters to
|
||||
* *addr and *addr_len. On error, do not change *addr and return nonzero.
|
||||
*/
|
||||
int osmo_sockaddr_init(struct osmo_sockaddr *addr,
|
||||
uint16_t family, uint16_t type, uint8_t proto,
|
||||
const char *host, uint16_t port);
|
||||
|
||||
/* Conveniently pass AF_UNSPEC, SOCK_DGRAM and IPPROTO_UDP to
|
||||
* osmo_sockaddr_init(). */
|
||||
static inline int osmo_sockaddr_init_udp(struct osmo_sockaddr *addr,
|
||||
const char *host, uint16_t port)
|
||||
{
|
||||
return osmo_sockaddr_init(addr, AF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP,
|
||||
host, port);
|
||||
}
|
||||
|
||||
/*! \brief convert sockaddr to human readable string.
|
||||
* \param[out] addr_str Valid pointer to a buffer of length addr_str_len.
|
||||
* \param[in] addr_str_len Size of buffer addr_str points at.
|
||||
* \param[out] port_str Valid pointer to a buffer of length port_str_len.
|
||||
* \param[in] port_str_len Size of buffer port_str points at.
|
||||
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
|
||||
* \param[in] flags flags as passed to getnameinfo().
|
||||
* \returns 0 on success, an error code on error.
|
||||
*
|
||||
* Return the IPv4 or IPv6 address string and the port (a.k.a. service) string
|
||||
* representations of the given struct osmo_sockaddr in two caller provided
|
||||
* char buffers. Flags of (NI_NUMERICHOST | NI_NUMERICSERV) return numeric
|
||||
* address and port. Either one of addr_str or port_str may be NULL, in which
|
||||
* case nothing is returned there.
|
||||
*
|
||||
* See also osmo_sockaddr_to_str() (less flexible, but much more convenient). */
|
||||
int osmo_sockaddr_to_strs(char *addr_str, size_t addr_str_len,
|
||||
char *port_str, size_t port_str_len,
|
||||
const struct osmo_sockaddr *addr,
|
||||
int flags);
|
||||
|
||||
|
||||
/*! \brief concatenate the parts returned by osmo_sockaddr_to_strs().
|
||||
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
|
||||
* \param[in] buf A buffer to use for string operations.
|
||||
* \param[in] buf_len Length of the buffer.
|
||||
* \returns Address string (in buffer).
|
||||
*
|
||||
* Compose a string of the numeric IP-address and port represented by *addr of
|
||||
* the form "<ip-addr> port <port>". The returned string is valid until the
|
||||
* next invocation of this function.
|
||||
*/
|
||||
const char *osmo_sockaddr_to_strb(const struct osmo_sockaddr *addr,
|
||||
char *buf, size_t buf_len);
|
||||
|
||||
/*! \brief conveniently return osmo_sockaddr_to_strb() in a static buffer.
|
||||
* \param[in] addr Binary representation as returned by osmo_sockaddr_init().
|
||||
* \returns Address string in static buffer.
|
||||
*
|
||||
* See osmo_sockaddr_to_strb().
|
||||
*
|
||||
* Note: only one osmo_sockaddr_to_str() call will work per print/log
|
||||
* statement. For two or more, use osmo_sockaddr_to_strb() with a separate
|
||||
* buffer each.
|
||||
*/
|
||||
const char *osmo_sockaddr_to_str(const struct osmo_sockaddr *addr);
|
||||
|
||||
/*! \brief compare two osmo_sockaddr.
|
||||
* \param[in] a The first address to compare.
|
||||
* \param[in] b The other address to compare.
|
||||
* \returns 0 if equal, otherwise -1 or 1.
|
||||
*/
|
||||
int osmo_sockaddr_cmp(const struct osmo_sockaddr *a,
|
||||
const struct osmo_sockaddr *b);
|
||||
|
||||
/*! \brief Overwrite *dst with *src.
|
||||
* Like memcpy(), but copy only the valid bytes. */
|
||||
void osmo_sockaddr_copy(struct osmo_sockaddr *dst,
|
||||
const struct osmo_sockaddr *src);
|
||||
|
||||
|
||||
/* general */
|
||||
|
||||
enum gtphub_plane_idx {
|
||||
GTPH_PLANE_CTRL = 0,
|
||||
GTPH_PLANE_USER = 1,
|
||||
GTPH_PLANE_N
|
||||
};
|
||||
|
||||
enum gtphub_side_idx {
|
||||
GTPH_SIDE_SGSN = 0,
|
||||
GTPH_SIDE_GGSN = 1,
|
||||
GTPH_SIDE_N
|
||||
};
|
||||
|
||||
#define for_each_side(I) for (I = 0; I < GTPH_SIDE_N; I++)
|
||||
#define for_each_plane(I) for (I = 0; I < GTPH_PLANE_N; I++)
|
||||
#define for_each_side_and_plane(I,J) for_each_side(I) for_each_plane(J)
|
||||
|
||||
static inline int other_side_idx(int side_idx)
|
||||
{
|
||||
return (side_idx + 1) & 1;
|
||||
}
|
||||
|
||||
extern const char* const gtphub_plane_idx_names[GTPH_PLANE_N];
|
||||
extern const uint16_t gtphub_plane_idx_default_port[GTPH_PLANE_N];
|
||||
|
||||
extern const char* const gtphub_side_idx_names[GTPH_SIDE_N];
|
||||
|
||||
/* A host address in the form that is expected in the 7.7.32 GSN Address IE.
|
||||
* len is either 4 (IPv4) or 16 (IPv6), any other value is invalid. If no
|
||||
* address is set, len shall be 0. */
|
||||
struct gsn_addr {
|
||||
uint16_t len;
|
||||
uint8_t buf[16];
|
||||
};
|
||||
|
||||
void gsn_addr_copy(struct gsn_addr *gsna, const struct gsn_addr *src);
|
||||
int gsn_addr_from_str(struct gsn_addr *gsna, const char *numeric_addr_str);
|
||||
|
||||
/* Return gsna in numeric string form, in a static buffer. */
|
||||
const char *gsn_addr_to_str(const struct gsn_addr *gsna);
|
||||
|
||||
/* note: strbuf_len doesn't need to be larger than INET6_ADDRSTRLEN + 1. */
|
||||
const char *gsn_addr_to_strb(const struct gsn_addr *gsna,
|
||||
char *strbuf, int strbuf_len);
|
||||
|
||||
/* Return 1 on match, zero otherwise. */
|
||||
int gsn_addr_same(const struct gsn_addr *a, const struct gsn_addr *b);
|
||||
|
||||
/* Decode sa to gsna. Return 0 on success. If port is non-NULL, the port number
|
||||
* from sa is also returned. */
|
||||
int gsn_addr_from_sockaddr(struct gsn_addr *gsna, uint16_t *port,
|
||||
const struct osmo_sockaddr *sa);
|
||||
|
||||
/* expiry */
|
||||
|
||||
struct expiring_item;
|
||||
typedef void (*del_cb_t)(struct expiring_item *);
|
||||
|
||||
struct expiring_item {
|
||||
struct llist_head entry;
|
||||
time_t expiry;
|
||||
del_cb_t del_cb;
|
||||
};
|
||||
|
||||
struct expiry {
|
||||
int expiry_in_seconds;
|
||||
struct llist_head items;
|
||||
};
|
||||
|
||||
/* Initialize an expiry queue. */
|
||||
void expiry_init(struct expiry *exq, int expiry_in_seconds);
|
||||
|
||||
/* Add a new mapping, or restart the expiry timeout for an already listed
|
||||
* mapping. */
|
||||
void expiry_add(struct expiry *exq, struct expiring_item *item, time_t now);
|
||||
|
||||
/* Initialize to all-empty; must be called before using the item in any way. */
|
||||
void expiring_item_init(struct expiring_item *item);
|
||||
|
||||
/* Remove the given item from its expiry queue, and call item->del_cb, if set.
|
||||
* This sets item->del_cb to NULL and is harmless when run a second time on the
|
||||
* same item, so the del_cb may choose to call this function, too, to allow
|
||||
* deleting items from several code paths. */
|
||||
void expiring_item_del(struct expiring_item *item);
|
||||
|
||||
/* Carry out due expiry of mappings. Must be invoked regularly.
|
||||
* 'now' is the current clock count in seconds and must correspond to the clock
|
||||
* count passed to nr_map_add(). A monotonous clock counter should be used. */
|
||||
int expiry_tick(struct expiry *exq, time_t now);
|
||||
|
||||
/* Expire all items. */
|
||||
void expiry_clear(struct expiry *exq);
|
||||
|
||||
|
||||
/* number map */
|
||||
|
||||
/* A number map assigns a "random" mapped number to each user provided number.
|
||||
* If the same number is requested multiple times, the same mapped number is
|
||||
* returned.
|
||||
*
|
||||
* Number maps plug into possibly shared pools and expiry queues, for example:
|
||||
*
|
||||
* mapA -----------+-> pool1 <-+-- mapB
|
||||
* {10->1, 11->5} | {1, 2, 3, ...} | {10->2, 11->3}
|
||||
* | |
|
||||
* | |
|
||||
* /-> \-> expiry1 <-/
|
||||
* | (30 seconds)
|
||||
* |
|
||||
* mapC -------+-----> pool2 <-+-- mapD
|
||||
* {10->1, 11->3} {1, 2, 3, ...} | {10->2, 11->5}
|
||||
* |
|
||||
* expiry2 <-/
|
||||
* (60 seconds)
|
||||
*
|
||||
* A map contains mappings ("10->1"). Each map needs a number pool, which can
|
||||
* be shared with other maps. Each new mapping receives a number from the pool,
|
||||
* which is then unavailable to any other map using the same pool.
|
||||
*
|
||||
* A map may point at an expiry queue, in which case all mappings added to it
|
||||
* are also appended to the expiry queue (using a separate llist entry in the
|
||||
* mapping). Any number of maps may submit to the same expiry queue, if they
|
||||
* desire the same expiry timeout. An expiry queue stores the mappings in
|
||||
* chronological order, so that expiry checking is needed only from the start
|
||||
* of the queue; hence only mappings with identical expiry timeout can be added
|
||||
* to the same expiry queue. Upon expiry, a mapping is dropped from the map it
|
||||
* was submitted at. expiry_tick() needs to be called regularly for each expiry
|
||||
* queue.
|
||||
*
|
||||
* A nr_mapping can be embedded in a larger struct: each mapping can have a
|
||||
* distinct destructor (del_cb), and each del_cb can figure out the container
|
||||
* struct's address and free that upon expiry or manual deletion. So in expiry
|
||||
* queues (and even maps), mappings of different container types can be mixed.
|
||||
* This can help to drastically reduce the amount of unnecessary visits during
|
||||
* expiry checking, for the case that no expiry is pending. An expiry queue
|
||||
* always knows which mappings to expire next, because they are right at the
|
||||
* start of its list.
|
||||
*
|
||||
* Mapping allocation and a del_cb are provided by the caller. If del_cb is
|
||||
* NULL, no deallocation will be done (allowing statically allocated entries).
|
||||
*/
|
||||
|
||||
typedef unsigned int nr_t;
|
||||
|
||||
/* Generator for unused numbers. So far this counts upwards from zero, but the
|
||||
* implementation may change in the future. Treat this like an opaque struct.
|
||||
* If this becomes random, the tests need to be fixed. */
|
||||
struct nr_pool {
|
||||
nr_t last_nr;
|
||||
nr_t nr_min;
|
||||
nr_t nr_max;
|
||||
};
|
||||
|
||||
struct nr_mapping {
|
||||
struct llist_head entry;
|
||||
struct expiring_item expiry_entry;
|
||||
|
||||
void *origin;
|
||||
nr_t orig;
|
||||
nr_t repl;
|
||||
};
|
||||
|
||||
struct nr_map {
|
||||
struct nr_pool *pool; /* multiple nr_maps can share a nr_pool. */
|
||||
struct expiry *add_items_to_expiry;
|
||||
struct llist_head mappings;
|
||||
};
|
||||
|
||||
|
||||
void nr_pool_init(struct nr_pool *pool, nr_t nr_min, nr_t nr_max);
|
||||
|
||||
/* Return the next unused number from the nr_pool. */
|
||||
nr_t nr_pool_next(struct nr_pool *pool);
|
||||
|
||||
/* Initialize the nr_mapping to zero/empty values. */
|
||||
void nr_mapping_init(struct nr_mapping *mapping);
|
||||
|
||||
/* Remove the given mapping from its parent map and expiry queue, and call
|
||||
* mapping->del_cb, if set. */
|
||||
void nr_mapping_del(struct nr_mapping *mapping);
|
||||
|
||||
/* Initialize an (already allocated) nr_map, and set the map's number pool.
|
||||
* Multiple nr_map instances may use the same nr_pool. Set the nr_map's expiry
|
||||
* queue to exq, so that all added mappings are automatically expired after the
|
||||
* time configured in exq. exq may be NULL to disable automatic expiry. */
|
||||
void nr_map_init(struct nr_map *map, struct nr_pool *pool,
|
||||
struct expiry *exq);
|
||||
|
||||
/* Add a new entry to the map. mapping->orig, mapping->origin and
|
||||
* mapping->del_cb must be set before calling this function. The remaining
|
||||
* fields of *mapping will be overwritten. mapping->repl is set to the next
|
||||
* available mapped number from map->pool. 'now' is the current clock count in
|
||||
* seconds; if no map->expiry is used, just pass 0 for 'now'. */
|
||||
void nr_map_add(struct nr_map *map, struct nr_mapping *mapping,
|
||||
time_t now);
|
||||
|
||||
/* Restart the timeout for the given mapping. mapping must be a member of map.
|
||||
*/
|
||||
void nr_map_refresh(struct nr_map *map, struct nr_mapping *mapping,
|
||||
time_t now);
|
||||
|
||||
/* Return a known mapping from nr_orig and the given origin. If nr_orig is
|
||||
* unknown, return NULL. */
|
||||
struct nr_mapping *nr_map_get(const struct nr_map *map,
|
||||
void *origin, nr_t nr_orig);
|
||||
|
||||
/* Return a known mapping to nr_repl. If nr_repl is unknown, return NULL. */
|
||||
struct nr_mapping *nr_map_get_inv(const struct nr_map *map, nr_t nr_repl);
|
||||
|
||||
/* Remove all mappings from map. */
|
||||
void nr_map_clear(struct nr_map *map);
|
||||
|
||||
/* Return 1 if map has no entries, 0 otherwise. */
|
||||
int nr_map_empty(const struct nr_map *map);
|
||||
|
||||
|
||||
/* config */
|
||||
|
||||
static const int GTPH_EXPIRE_QUICKLY_SECS = 30; /* TODO is there a spec for this? */
|
||||
static const int GTPH_EXPIRE_SLOWLY_MINUTES = 6 * 60; /* TODO is there a spec for this? */
|
||||
|
||||
struct gtphub_cfg_addr {
|
||||
const char *addr_str;
|
||||
uint16_t port;
|
||||
};
|
||||
|
||||
struct gtphub_cfg_bind {
|
||||
struct gtphub_cfg_addr bind;
|
||||
};
|
||||
|
||||
struct gtphub_cfg {
|
||||
struct gtphub_cfg_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N];
|
||||
struct gtphub_cfg_addr proxy[GTPH_SIDE_N][GTPH_PLANE_N];
|
||||
int sgsn_use_sender; /* Use sender, not GSN addr IE with std ports */
|
||||
};
|
||||
|
||||
|
||||
/* state */
|
||||
|
||||
struct gtphub_peer {
|
||||
struct llist_head entry;
|
||||
|
||||
struct llist_head addresses; /* Alternatives, not load balancing. */
|
||||
struct nr_pool seq_pool;
|
||||
struct nr_map seq_map;
|
||||
};
|
||||
|
||||
struct gtphub_peer_addr {
|
||||
struct llist_head entry;
|
||||
|
||||
struct gtphub_peer *peer;
|
||||
struct gsn_addr addr;
|
||||
struct llist_head ports;
|
||||
};
|
||||
|
||||
struct gtphub_peer_port {
|
||||
struct llist_head entry;
|
||||
|
||||
struct gtphub_peer_addr *peer_addr;
|
||||
uint16_t port;
|
||||
unsigned int ref_count; /* references from other peers' seq_maps */
|
||||
struct osmo_sockaddr sa; /* a "cache" for (peer_addr->addr, port) */
|
||||
int last_restart_count; /* 0..255 = valid, all else means unknown */
|
||||
|
||||
struct rate_ctr_group *counters_io;
|
||||
};
|
||||
|
||||
struct gtphub_tunnel_endpoint {
|
||||
struct gtphub_peer_port *peer;
|
||||
uint32_t tei_orig; /* from/to peer */
|
||||
|
||||
struct rate_ctr_group *counters_io;
|
||||
};
|
||||
|
||||
struct gtphub_tunnel {
|
||||
struct llist_head entry;
|
||||
struct expiring_item expiry_entry;
|
||||
|
||||
uint32_t tei_repl; /* unique TEI to replace peers' TEIs */
|
||||
struct gtphub_tunnel_endpoint endpoint[GTPH_SIDE_N][GTPH_PLANE_N];
|
||||
};
|
||||
|
||||
struct gtphub_bind {
|
||||
struct gsn_addr local_addr;
|
||||
uint16_t local_port;
|
||||
struct osmo_fd ofd;
|
||||
|
||||
/* list of struct gtphub_peer */
|
||||
struct llist_head peers;
|
||||
|
||||
const char *label; /* For logging */
|
||||
struct rate_ctr_group *counters_io;
|
||||
};
|
||||
|
||||
struct gtphub_resolved_ggsn {
|
||||
struct llist_head entry;
|
||||
struct expiring_item expiry_entry;
|
||||
|
||||
/* The APN OI, the Operator Identifier, is the combined address,
|
||||
* including parts of the IMSI and APN NI, and ending with ".gprs". */
|
||||
char apn_oi_str[GSM_APN_LENGTH];
|
||||
|
||||
/* Which address and port we resolved that to. */
|
||||
struct gtphub_peer_port *peer;
|
||||
};
|
||||
|
||||
struct gtphub {
|
||||
struct gtphub_bind to_gsns[GTPH_SIDE_N][GTPH_PLANE_N];
|
||||
|
||||
/* pointers to an entry of to_gsns[s][p].peers */
|
||||
struct gtphub_peer_port *proxy[GTPH_SIDE_N][GTPH_PLANE_N];
|
||||
|
||||
/* The TEI numbers will simply wrap and be reused, which will work out
|
||||
* in practice. Problems would arise if one given peer maintained the
|
||||
* same TEI for a time long enough for the TEI nr map to wrap an entire
|
||||
* uint32_t; if a new TEI were mapped every second, this would take
|
||||
* more than 100 years (in which a single given TEI must not time out)
|
||||
* to cause a problem. */
|
||||
struct nr_pool tei_pool;
|
||||
|
||||
struct llist_head tunnels; /* struct gtphub_tunnel */
|
||||
struct llist_head pending_deletes; /* opaque (gtphub.c) */
|
||||
|
||||
struct llist_head ggsn_lookups; /* opaque (gtphub_ares.c) */
|
||||
struct llist_head resolved_ggsns; /* struct gtphub_resolved_ggsn */
|
||||
|
||||
struct osmo_timer_list gc_timer;
|
||||
struct expiry expire_quickly;
|
||||
struct expiry expire_slowly;
|
||||
|
||||
uint8_t restart_counter;
|
||||
|
||||
int sgsn_use_sender;
|
||||
};
|
||||
|
||||
struct gtp_packet_desc;
|
||||
|
||||
|
||||
/* api */
|
||||
|
||||
int gtphub_vty_init(struct gtphub *global_hub, struct gtphub_cfg *global_cfg);
|
||||
int gtphub_cfg_read(struct gtphub_cfg *cfg, const char *config_file);
|
||||
|
||||
/* Initialize and start gtphub: bind to ports, run expiry timers. */
|
||||
int gtphub_start(struct gtphub *hub, struct gtphub_cfg *cfg,
|
||||
uint8_t restart_counter);
|
||||
|
||||
/* Close all sockets, expire all maps and peers and free all allocations. The
|
||||
* struct is then unusable, unless gtphub_start() is run on it again. */
|
||||
void gtphub_stop(struct gtphub *hub);
|
||||
|
||||
time_t gtphub_now(void);
|
||||
|
||||
/* Remove expired items, empty peers, ... */
|
||||
void gtphub_gc(struct gtphub *hub, time_t now);
|
||||
|
||||
/* Return the string of the first address for this peer. */
|
||||
const char *gtphub_peer_str(struct gtphub_peer *peer);
|
||||
|
||||
/* Return a human readable description of tun in a static buffer. */
|
||||
const char *gtphub_tunnel_str(struct gtphub_tunnel *tun);
|
||||
|
||||
/* Return 1 if all of tun's endpoints are fully established, 0 otherwise. */
|
||||
int gtphub_tunnel_complete(struct gtphub_tunnel *tun);
|
||||
|
||||
int gtphub_handle_buf(struct gtphub *hub,
|
||||
unsigned int side_idx,
|
||||
unsigned int port_idx,
|
||||
const struct osmo_sockaddr *from_addr,
|
||||
uint8_t *buf,
|
||||
size_t received,
|
||||
time_t now,
|
||||
uint8_t **reply_buf,
|
||||
struct osmo_fd **to_ofd,
|
||||
struct osmo_sockaddr *to_addr);
|
||||
|
||||
struct gtphub_peer_port *gtphub_port_have(struct gtphub *hub,
|
||||
struct gtphub_bind *bind,
|
||||
const struct gsn_addr *addr,
|
||||
uint16_t port);
|
||||
|
||||
struct gtphub_peer_port *gtphub_port_find_sa(const struct gtphub_bind *bind,
|
||||
const struct osmo_sockaddr *addr);
|
||||
|
||||
void gtphub_resolved_ggsn(struct gtphub *hub, const char *apn_oi_str,
|
||||
struct gsn_addr *resolved_addr,
|
||||
time_t now);
|
||||
|
||||
const char *gtphub_port_str(struct gtphub_peer_port *port);
|
||||
|
||||
int gtphub_write(const struct osmo_fd *to,
|
||||
const struct osmo_sockaddr *to_addr,
|
||||
const uint8_t *buf, size_t buf_len);
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef _HANDOVER_H
|
||||
#define _HANDOVER_H
|
||||
|
||||
struct gsm_subscriber_connection;
|
||||
|
||||
int bsc_handover_start(struct gsm_lchan *old_lchan, struct gsm_bts *bts);
|
||||
|
||||
/* clear any operation for this connection */
|
||||
void bsc_clear_handover(struct gsm_subscriber_connection *conn, int free_lchan);
|
||||
|
||||
/* Return the old lchan or NULL. This is meant for audio handling */
|
||||
struct gsm_lchan *bsc_handover_pending(struct gsm_lchan *new_lchan);
|
||||
|
||||
#endif /* _HANDOVER_H */
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef _HANDOVER_DECISION_H
|
||||
#define _HANDOVER_DECISION_H
|
||||
|
||||
void on_dso_load_ho_dec(void);
|
||||
|
||||
#endif /* _HANDOVER_DECISION_H */
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
#ifndef _IPACCESS_H
|
||||
#define _IPACCESS_H
|
||||
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
#include "gsm_subscriber.h"
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/ipaccess.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
struct ipac_msgt_sccp_state {
|
||||
uint8_t src_ref[3];
|
||||
uint8_t dst_ref[3];
|
||||
uint8_t trans_id;
|
||||
uint8_t invoke_id;
|
||||
char imsi[GSM23003_IMSI_MAX_DIGITS+1];
|
||||
uint8_t data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
* @add_remove 0 for remove, 1 for add, 3 to asK
|
||||
* @nr_lacs Number of extra lacs inside this package
|
||||
* @lac One lac entry
|
||||
*/
|
||||
struct ipac_ext_lac_cmd {
|
||||
uint8_t add_remove;
|
||||
uint8_t nr_extra_lacs;
|
||||
uint16_t lac;
|
||||
uint8_t data[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
void ipaccess_drop_oml(struct gsm_bts *bts);
|
||||
void ipaccess_drop_rsl(struct gsm_bts_trx *trx);
|
||||
|
||||
struct sdp_header_item {
|
||||
struct sdp_header_entry header_entry;
|
||||
struct llist_head entry;
|
||||
off_t absolute_offset;
|
||||
};
|
||||
|
||||
struct sdp_header {
|
||||
struct sdp_firmware firmware_info;
|
||||
|
||||
/* for more_magic a list of sdp_header_entry_list */
|
||||
struct llist_head header_list;
|
||||
|
||||
/* the entry of the sdp_header */
|
||||
struct llist_head entry;
|
||||
};
|
||||
|
||||
int ipaccess_analyze_file(int fd, const unsigned int st_size, const unsigned base_offset, struct llist_head *list);
|
||||
|
||||
#endif /* _IPACCESS_H */
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
int gsm0408_rcvmsg_iucs(struct gsm_network *network, struct msgb *msg,
|
||||
uint16_t *lac);
|
||||
|
||||
struct gsm_subscriber_connection *subscr_conn_lookup_iu(struct gsm_network *network,
|
||||
struct ranap_ue_conn_ctx *ue);
|
|
@ -1,7 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
struct gsm_network;
|
||||
struct ranap_ue_conn_ctx;
|
||||
|
||||
int iucs_rx_ranap_event(struct gsm_network *network,
|
||||
struct ranap_ue_conn_ctx *ue_ctx, int type, void *data);
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef _OPENBSC_MEAS_FEED_H
|
||||
#define _OPENBSC_MEAS_FEED_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openbsc/meas_rep.h>
|
||||
|
||||
struct meas_feed_hdr {
|
||||
uint8_t msg_type;
|
||||
uint8_t reserved;
|
||||
uint16_t version;
|
||||
};
|
||||
|
||||
struct meas_feed_meas {
|
||||
struct meas_feed_hdr hdr;
|
||||
char imsi[15+1];
|
||||
char name[31+1];
|
||||
char scenario[31+1];
|
||||
struct gsm_meas_rep mr;
|
||||
/* The logical channel type, enum gsm_chan_t */
|
||||
uint8_t lchan_type;
|
||||
/* The physical channel type, enum gsm_phys_chan_config */
|
||||
uint8_t pchan_type;
|
||||
/* number of ths BTS in network */
|
||||
uint8_t bts_nr;
|
||||
/* number of this TRX in the BTS */
|
||||
uint8_t trx_nr;
|
||||
/* number of this timeslot at the TRX */
|
||||
uint8_t ts_nr;
|
||||
/* The logical subslot number in the TS */
|
||||
uint8_t ss_nr;
|
||||
};
|
||||
|
||||
enum meas_feed_msgtype {
|
||||
MEAS_FEED_MEAS = 0,
|
||||
};
|
||||
|
||||
#define MEAS_FEED_VERSION 1
|
||||
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue